高并发系统的架构设计思路
2023-05-09 14:40:00 25 举报
AI智能生成
高并发系统的架构设计思路
作者其他创作
大纲/内容
设计目标
高性能
性能体现了系统的并行处理能力,在有限的硬件投入下,提高性能意味着节省成本。同时,性能也反映了用户体验
常用指标
1.平均响应时间
最常用,但是缺陷很明显,对于慢请求不敏感,如1万次请求,其中9900次是1ms,100次是100ms,则平均响应时间为1.99ms,虽然平均耗时仅增加了0.99ms,但是1%请求的响应时间已经增加了100倍
2.TP90、TP99等分位值
将响应时间按照从小到大排序,TP90表示排在第90分位的响应时间, 分位值越大,对慢请求越敏感
3.吞吐量
和响应时间呈反比,比如响应时间是1ms,则吞吐量为每秒1000次
高可用
表示系统可以正常服务的时间
可用性 = 正常运行时间 / 系统总运行时间,一般使用几个9来描述系统的可用性
高扩展
表示系统的扩展能力,流量高峰时能否在短时间内完成扩容,更平稳地承接峰值流量,比如双11活动、明星离婚等热点事件
扩展性 = 性能提升比例 / 机器增加比例,
理想的扩展能力是:资源增加几倍,性能提升几倍。通常来说,扩展能力要维持在70%以上
理想的扩展能力是:资源增加几倍,性能提升几倍。通常来说,扩展能力要维持在70%以上
服务集群、数据库、缓存和消息队列等中间件、负载均衡、带宽、依赖的第三方等,当并发达到某一个量级后,上述每个因素都可能成为扩展的瓶颈点
三个目标相互关联和影响
例如考虑系统的扩展能力,你会将服务设计成无状态的,这种集群设计保证了高扩展性,其实也间接提升了系统的性能和可用性;
再比如为了保证可用性,通常会对服务接口进行超时设置,以防大量线程阻塞在慢请求上造成系统雪崩,那超时时间设置成多少合理呢?一般会参考依赖服务的性能表现进行设置
例如考虑系统的扩展能力,你会将服务设计成无状态的,这种集群设计保证了高扩展性,其实也间接提升了系统的性能和可用性;
再比如为了保证可用性,通常会对服务接口进行超时设置,以防大量线程阻塞在慢请求上造成系统雪崩,那超时时间设置成多少合理呢?一般会参考依赖服务的性能表现进行设置
设计方法
纵向扩展
1.提升单机的硬件性能
2.提升单机的软件性能
用缓存减少IO次数
用并发或者异步的方式增加吞吐量
横向扩展(集群)
1.做好分层架构
通过分层处理可以简化复杂问题,更容易做到横向扩展
通过分层处理可以简化复杂问题,更容易做到横向扩展
常见的分层架构,当然真实的高并发系统架构会在此基础上进一步完善。
比如会做动静分离并引入CDN,反向代理层可以是LVS+Nginx,Web层可以是统一的API网关,
业务服务层可进一步按垂直业务做微服务化,存储层可以是各种异构数据库
比如会做动静分离并引入CDN,反向代理层可以是LVS+Nginx,Web层可以是统一的API网关,
业务服务层可进一步按垂直业务做微服务化,存储层可以是各种异构数据库
2.各层进行水平扩展
无状态水平扩容
业务集群通常能设计成无状态
业务集群通常能设计成无状态
有状态做分片路由
数据库和缓存
数据库和缓存
设计分区键做好存储分片
主从同步
读写分离
实践方案
高性能方案
应用集群和负载均衡实现横向扩展
使用缓存
CDN
本地缓存
应用缓存(redis、内存缓存等)
注意问题
热点Key
缓存穿透
查找一个一定不存在数据库的数据,就叫缓存穿透
缓存击穿
访问量非常多,有多个C端同时查询同一数据,Redis缓存又恰好没缓存数据,此时,多个C端就会同时去查询数据库
原因:
1.机器刚刚启动,且没预热缓存,缓存都为空,又没用分布式锁
2.机器运行已运行一段时间,但缓存刚好失效,又没用分布式锁
3.Redis宕机
1.机器刚刚启动,且没预热缓存,缓存都为空,又没用分布式锁
2.机器运行已运行一段时间,但缓存刚好失效,又没用分布式锁
3.Redis宕机
缓存雪崩
缓存中有大量的key在同一时刻过期,或者Redis直接宕机了,导致大量的查询请求全部到达数据库
数据一致性问题
缓存与数据库双存储双写
旁路缓存模式:
适合读请求比较多的场景
适合读请求比较多的场景
写:
先更新 DB。
然后删除缓存
先更新 DB。
然后删除缓存
读:
从 cache 中读取数据,读取到就直接返回
cache中读取不到的话,就从 DB 中读取数据返回,再把数据放到 cache 中。
从 cache 中读取数据,读取到就直接返回
cache中读取不到的话,就从 DB 中读取数据返回,再把数据放到 cache 中。
读写穿透:
服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责
服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责
异步缓存写入:
和读写穿透很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写,但是改为异步批量的方式来更新 DB
如果缓存挂掉而数据没有更新的话,就会造成数据丢失,适用于对数据一致性要求没那么高的场景
和读写穿透很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写,但是改为异步批量的方式来更新 DB
如果缓存挂掉而数据没有更新的话,就会造成数据丢失,适用于对数据一致性要求没那么高的场景
数据分片
分库
分表
数据库索引
索引优化
搜索引擎
如es 、mysql 结合
异步化
次要流程多线程处理
MQ
延时任务
限流
前端限流
Nginx接入层限流
服务端限流
预先计算
缓存预热
减少IO次数
批量读写
增加冗余数据
压缩IO数据包大小
程序逻辑优化
池化技术
http请求池
线程池
数据库连接池
JVM优化
调整内存空间分配
调整GC回收器,减少GC频率耗时
选择合适的同步锁
读多写少用乐观锁
分段锁减少所冲突
高可用方案
对等节点的故障转移
非对等节点的故障转移,通过心跳检测并实施主备切换
接口层面的超时设置、重试策略和幂等设计
降级处理:保证核心服务,牺牲非核心服务,必要时进行熔断;或者核心链路出问题时,有备选链路
限流处理:对超过系统处理能力的请求直接拒绝或者返回错误码
MQ场景的消息可靠性保证,包括producer端的重试机制、broker侧的持久化、consumer端的ack机制等
灰度发布,能支持按机器维度进行小流量部署,观察系统日志和业务指标,等运行平稳后再推全量
监控报警:全方位的监控体系,包括最基础的CPU、内存、磁盘、网络的监控,以及Web服务器、JVM、数据库、各类中间件的监控和业务指标的监控
灾备演练:类似当前的“混沌工程”,对系统进行一些破坏性手段,观察局部故障是否会引起可用性问题
高扩展方案
合理的分层架构
存储层的拆分
按照数据特征维度进一步做水平拆分(分库分表)
业务层的拆分
按照核心接口和非核心接口拆
按照请求源拆(比如To C和To B,APP和H5 )
按照请求源拆(比如To C和To B,APP和H5 )
原则
秉承架构设计的3个原则:简单、合适和演进
过早的优化是万恶之源
0 条评论
下一页