高并发系统设计

通用方法

  • Scale-Out(横向扩展 ):采用分布式部署方式将流量分开,让每个服务器承担一部分并发和流量。(Scale-Up,提高单机性能,系统初期使用Scale-Up,并发超过单机极限使用Scale-out)
  • 缓存:使用缓存来提高性能。磁盘IO(10ms)速度远低于从内存(纳秒)和网卡(微秒)上读取。
  • 异步:在某些场景下,未处理完成之前可以让请求先返回,在数据准备好之后再另行通知。

架构分层

  • 简化系统设计,让不同层次专注做不同的事。
  • 分层后可以做到复用
  • 分层可以更容易横向扩展,比如只针对数据层做扩展。
  • 分层架构相邻层相互依赖,数据只在相邻层交互
  • 分层缺点:实现复杂,有些需求需要修改每一层的代码;如果层次单独部署,层次间通过网络来交互,性能会有损耗。

高并发三大目标

高性能

优化原则

  • 性能优化是问题导向的。
  • 性能优化遵循二八原则,20%精力解决80%性能问题,优先优化主要性能瓶颈点。
  • 性能优化需要数据支撑,优化过程中要时刻了解优化让响应时间减少了多少,提高了多少吞吐量
  • 性能优化过程是持续的。

度量指标

  • 某个时间段内接口响应时间的平均值:敏感度差些,如有少量超慢请求,并不容易发现
  • 某个时间段内接口响应时间的最大值:过于敏感,可能只有极少超慢请求
  • 分位值:比如90分位、75分位等。把某个时间段的请求响应时间从小到大排序,假如有100个请求,排在90位的响应时间就是90分位值。分位值排除了偶发极慢请求的影响,能够较好反应这段时间的性能情况,分位值越大,对于慢请求的影响越敏感
    高并发系统设计
  • 脱离并发谈性能是没有意义的,通常使用吞吐量和响应时间来度量并发和流量,吞吐量使用多些,两者呈倒数关系。响应时间1秒,吞吐量是每秒1次,响应时间10ms,吞吐量每秒100次。
  • 度量性能时,会兼顾吞吐量和响应时间,比如设立优化目标如下:每秒1万次请求,响应时间99分位值在10ms以下。
  • 通常响应在200ms下用户无感知,1s以内用户能感觉到延迟但可以接受,超过1s就会有明显等待感。健康系统的99分位值的响应时间通常需要控制在200ms内,不超过1s的请求占比超过99.99%。

性能优化

  • 假设系统中有一个处理核心,执行任务响应时间10ms,吞吐量每秒100次。优化思路有两种:
1、提高系统的处理核心数
  • 即增加系统并行处理能力,此时,吞吐量 = 并发进程数 / 响应时间,即两个核心,响应时间不变,吞吐量提高一倍
  • 阿姆达尔定律,固定负载下,并行计算的加速比,即并行化之后效率的提升情况:(Ws+Wp)/(Ws+Wp/s)。即效率提升百分比 =(串行计算量 + 并行计算量)/(串行计算量 + 并行计算量 / 并行进程数),可以推导出另外一个公式1/(1-p+p/s),即效率提升百分比 = 1/(1 - 并行任务占比 + 并行任务占比/并行进程数),p为0,即完全串行,加速比为1,完全无加速;s -> 无穷大,加速比为1/(1-p),即和p成正比,当p - > 1时,加速比无穷大。
  • 所以是不是无限增加处理核心就行呢?很遗憾,随着并非进程数增加,并行任务对于系统资源的争抢也会越来越严重,在某个节点继续增加并非进程数,反而会造成性能下降,这就是拐点。
    高并发系统设计
  • 并发数处于轻压力区,响应时间平稳,吞吐量和资源利用率稳步上升;重压力区,资源利用率达到极限,吞吐量随着并发数增长,有下降趋势,响应时间也有上升;此时再加大压力,则进入拐点区,处于超负荷,吞吐量下降,响应时间大幅上升。
  • 所以压力测试的目的就是找到拐点,从而知道系统的承载能力,便于找到瓶颈,持续优化系统性能。
2、较少单次任务响应时间
  • 系统是CPU密集型,需要处理大量的CPU计算,那么选用高效算法或者减少运算次数就是这类系统的重要优化手段,发现这类问题的主要方式,是通过一些Profile工具找到消耗CPU时间最多的方法或者模块(比如golang pprof)。
  • 系统是IO密集型,系统的大部分操作是在等待磁盘IO或者网络IO,比如数据库系统,缓存系统、Web系统等。这类系统的性能瓶颈可能在系统内部,也可能是依赖的其他系统,发现这类性能瓶颈的手段通常有两类:采集工具(如tcpdump)和监控(elk)。
  • 如果是数据库访问慢,那就要看是不是又锁表、全表扫描、索引是否合适等;如果是网络,就要看网络参数是否可以优化、是否有大量超时重传、网卡是否有大量丢包等。

高可用

可扩展