系统分析与互联网架构设计
分析原则
高并发原则
保证项目在高并发环境下能正常运行
-
垂直扩展
提高单机性能 -
水平扩展
分布式
任务细分分配给多个服务器集群
服务器团结起来完成一个大任务
常见技术有
- 使用缓存减少对数据库的访问
- 熔断降级提高响应速度
- 流量削峰进行入口限流
容错原则
对各种潜在的问题做好预案
常见技术有
- SpringBoot + Redis 实现分布式缓存
- MQ实现分布式场景下的事务一致性
- MQ、PRG模式、Token令牌解决重复提交
CAP原则
分布式系统的多个节点之间数据应该同步,考虑的因素有
-
Consistency 一致性
-
Availability 可用性
在合理的时间范围内,系统能够提供正常的服务 -
Partition tolerance 分区容错性
当部分节点故障时,系统还能够正常运行
三者不可兼得,一般而言分区容错性是必须要求,因此常常在一致性和可用性之间根据业务来权衡
幂等性原则
无论对某个服务提供的接口调用多次和调用一次,其结果都是一样的。
解决的常见问题:
- 重复支付问题:先读再写、分布式系统的去重表、CAS算法、分布式锁、悲观锁
- 表单重复提交问题:Token令牌机制、PRG模式、数据库唯一约束等
可扩展原则
项目的规模会随着用户数目的增加而增大,设计大型系统的时候需要考虑项目扩展方案
企业实践中,常用到的方法有
面向接口开发、前后端分离及模块化的编程风格、无状态化的服务、使用HDFS分布式文件系统、合理设计数据库的分库分表策略及数据异构方式、采用分布式或微服务架构
可维护原则
系统开发完毕后,维护人员能够方便地进行改进和修复系统中存在的额问题。包含了可理解性、可修改性、可移植性等多方面因素。
实现可维护性
- 项目日志记录完善,方便追溯问题、统计操作
- 有BugFree等Bug管理工具
- 有丰富的项目文档和注释
- 统一的开发规范
- 模块化的编程模式
可监控原则
对系统中的流量、性能、服务、异常等情况进行实时监控。
规避问题
Session共享问题
要实现服务器集群化情况下客户端的Session共享问题,可以采取以下三种方法
-
Session Replication
一个服务节点更新后,将该Session对象在各服务节点之间进行同步优点:实现简单
缺点:
- 容易引起广播风暴造成巨大的网络开销
- 造成严重冗余 不适用于服务节点多的情况
-
Session Sticky
使用Nginx工具对各个用户进行标记(Cookie)使每个用户在经过负载均衡后都请求固定的服务节点优点:流量均衡、实现简单
缺点:单点故障问题
-
独立的Session服务器(企业常用)
建立独立的Session服务器,集群从共享的Session服务器中读取数据优点:适用于大规模的分布式系统
缺点:对于小规模系统来说开销高
优先考虑无状态服务
前文提到了无状态服务的概念,下面来简单的解释一下:
无状态服务:应用服务与用户状态无关
比如Nginx转发到的机器由于不持有用户的信息导致执行情况不同就属于有状态连接(也就是Session共享没做好)
无状态服务的优点:
-
不需要做数据同步,减少开销
-
方便快速部署
-
集中管理各种状态的方式
- Session等保存在内存中的数据:Session服务
- 结构化数据:MySQL等
- 非结构化数据:HBase、ElasticSearch
- 文件:CDN、独立文件服务器如HDFS、FastDFS
技术选型与数据库设计
搭建高可用的Redis集群,主从同步读写分离、哨兵模式选择新的Master
搭建双Master的MySQL集群,主从同步做数据备份
MyCat控制MySQL读写分离,对大容量数据进行分库分表
Haproxy搭建MyCat集群
Keepalived搭建Haproxy集群,生成一个VIP,与Redis建立连接
缓存穿透与缓存雪崩问题
缓存穿透:大量查询缓存中不存在的数据
解决方案:
- 拦截非法的查询请求,仅将合理的请求发送给数据库
- 缓存空对象
- 建立数据表示仓库,在缓存中放入一张数据库中所有可查数据的Hash仓库表,进入数据库前先查询
缓存雪崩:由于某种原因造成缓存失效,数据库的瞬间压力骤增
原因:
- Redis重启
- Redis中的大量缓存数据设置了相同的过期时间
解决方案:
- 搭建Redis集群,保证高可用
- 避免大量缓存对象的Key集中失效
- 通过队列、锁机制等控制并发访问MySQL的线程数
参考资料
《亿级流量Java高并发于网络编程实战》