什么是高并发
通过设计保证系统能够同时并行处理很多请求
如何提升系统的并发能力
1、垂直扩展
1)增强单机硬件性能
2)提升单机架构性能
2、水平扩展
只要增加服务器数量,就能线性扩充系统性能
常见互联网分布式架构:
(1)客户端层:典型调用方是浏览器browser或者手机应用APP
(2)反向代理层:系统入口,反向代理
(3)站点应用层:实现核心应用逻辑,返回html或者json
(4)服务层:如果实现了服务化,就有这一层
(5)数据-缓存层:缓存加速访问存储
(6)数据-数据库层:数据库固化数据存储
反向代理层:通过dns轮询实现,一个域名配置多个ip,每次访问轮询ip,当nginx成为瓶颈,只要增加服务器数量,增加外网ip就能做到扩展代理层
站点应用层:通过nginx实现,修改nginx.conf,设置多个web后端,增加web服务器数量,在nginx配置新的web后端,就可以实现扩展
服务层:通过服务连接池实现,连接池会建立与下游服务多个连接,增加服务部署,建立新的连接,就可以做到扩展
数据层:
1、范围水平拆分
两个库,按uid范围分别存储;规则简单,数据均衡性好,容易扩展;但请求的负载不一定均衡
2、哈希水平拆分
两个库,安hash值奇偶区分;规则简单,数据均衡好,请求均衡;但是不容易扩展,可能需要进行数据迁移
什么是高可用
通过设计减少系统不能提供服务的时间
如何保证系统高可用
1、高可用保证的原则就是集群化,或者叫冗余
2、通过自动故障转移实现高可用
(1)【客户端层】到【反向代理层】的高可用,是通过反向代理层的冗余实现的,常见实践是keepalived + virtual IP自动故障转移
(2)【反向代理层】到【站点层】的高可用,是通过站点层的冗余实现的,常见实践是nginx与web-server之间的存活性探测与自动故障转移
(3)【站点层】到【服务层】的高可用,是通过服务层的冗余实现的,常见实践是通过service-connection-pool来保证自动故障转移
(4)【服务层】到【缓存层】的高可用,是通过缓存数据的冗余实现的,常见实践是缓存客户端双读双写,或者利用缓存集群的主从数据同步与sentinel保活与自动故障转移;更多的业务场景,对缓存没有高可用要求,可以使用缓存服务化来对调用方屏蔽底层复杂性
(5)【服务层】到【数据库“读”】的高可用,是通过读库的冗余实现的,常见实践是通过db-connection-pool来保证自动故障转移
(6)【服务层】到【数据库“写”】的高可用,是通过写库的冗余实现的,常见实践是keepalived + virtual IP自动故障转移
缓存架构设计
读操作流程
有了数据库和缓存两个地方存放数据之后(uid->money),每当需要读取相关数据时(money),操作流程一般是这样的:
(1)读取缓存中是否有相关数据,uid->money
(2)如果缓存中有相关数据money,则返回【这就是所谓的数据命中“hit”】
(3)如果缓存中没有相关数据money,则从数据库读取相关数据money【这就是所谓的数据未命中“miss”】,放入缓存中uid->money,再返回
缓存的命中率 = 命中缓存请求个数/总缓存访问请求个数 = hit/(hit+miss)
更新缓存 VS 淘汰缓存
根据更新缓存的复杂度,决定更新缓存还是淘汰缓存
先操作数据库 vs 先操作缓存
谁先做对业务影响小,谁先执行
先淘汰缓存,再写数据库
优化方案就是服务化,加入服务层,向上游提供数据访问接口,屏蔽底层数据存储细节,业务线不需要关注数据来自cache还是DB
(1)淘汰缓存是一种通用的缓存处理方式
(2)先淘汰缓存,再写数据库的时序是毋庸置疑的
(3)服务化是向业务方屏蔽底层数据库与缓存复杂性的一种通用方式
如何保证数据的一致性
线下启动一个离线的扫描工具,不停的比对正表T1和反表T2,如果发现数据不一致,就进行补偿修复。
优点:
(1)比较简单,开发代价小
(2)线上服务无需修改,修复工具与线上服务解耦
缺点:
(1)扫描效率低,会扫描大量的“已经能够保证一致”的数据
(2)由于扫描的数据量大,扫描一轮的时间比较长,即数据如果不一致,不一致的时间窗口比较长
还是需要一个离线的扫描工具,不停的比对日志log1和日志log2,如果发现数据不一致,就进行补偿修复
优点:
(1)虽比方法一复杂,但仍然是比较简单的
(2)数据扫描效率高,只扫描增量数据
缺点:
(1)线上服务略有修改(代价不高,多写了2条日志)
(2)虽然比方法一更实时,但时效性还是不高,不一致窗口取决于扫描的周期
msg1和msg2的接收时间应该在3s以内,如果检测服务在收到msg1后没有收到msg2,就尝试检测数据的一致性,不一致时进行补偿修复
优点:
(1)效率高
(2)实时性高
缺点:
(1)方案比较复杂,上线引入了消息总线这个组件
(2)线下多了一个订阅总线的检测服务
分布式系统生产唯一ID
1、数据库自增序列或字段
优点:
1)简单,代码方便,性能可以接受
2)数字ID天然排序,对后续排序有助
缺点:
1)不同数据库语法不同,数据库迁移或多数据库版本支持的时候需要处理
2)单个数据库或者读写分离,只有一个库可以生成,容易单点故障
3)性能达不到要求,难于扩展
4)分库分表会有麻烦
2、UUID
优点:
1)简单方便
2)生产ID性能好
3)全球唯一,数据库不会影响
缺点:
1)没有排序
2)字符串存储,查询效率慢
3)存储空间大
4)传输数据量大
3、Redis生成ID;集群下,多个redis可以采用起始值不同,步长相同
优点:
1)不依赖数据库,灵活方便,性能好
2)数字ID天然排序
缺点:
1)系统中没有redis需要引入新的组件
2)编程和配置工作量大