写在前面
面试的时候经常会被问到如何设计一个高并发系统,很多人都只能说出缓存、读写分离、异步等几个常见方法,今天就系统全面总结一下这个问题,希望能帮助到大家。
什么是高并发系统
简单说就是你的系统要能支持瞬间大量的请求。比如淘宝双11、过年抢红包等。那如何量化的定义一个系统是不是高并发呢?有一些名称需要了解一下。
名词解释
QPS
QPS 全称是 Query Per Second ,含义是每秒查询数,即服务每秒处理完成的请求数。
TPS
TPS 全称是 Transaction Per Second ,含义是每秒事务数,即服务每秒处理完成的事务数。
RT
RT 全称是 Response Time ,含义是响应时间,即服务处理一次请求的平均响应时间。
并发量
并发量指的是客户端同时发起的请求数。注意,这里并不是服务处理的请求数。
服务并发处理数
服务端同时处理的请求数。这里要注意和并发量作区分。
用户数
用户数可以分为并发用户数、注册用户数和在线用户数。
并发用户数在真实线上环境下,指的是同时发起请求的用户数。在压测环境下,指的是压测工具中的虚拟用户数(Virutal User)。注意,并发用户数是一定会对系统产生压力的用户数。
注册用户数一般指的是数据库中存在的用户数,对系统不产生压力。
在线用户数指的是当前使用系统的,“挂” 在系统上的用户数,一般不对系统造成压力。
吞吐量
吞吐量,指的是系统服务在网络上传输的数据总和。
吞吐量不能作为衡量系统能力的指标,因为随着时间的拉长,吞吐量自然就上去了。比如滴水一天可能比全量开 1 分钟水龙头的自来水的流量还多,而我们的感受肯定是全量开水龙头的水流量大。因此,衡量系统吞吐能力,一般用单位时间内的吞吐量来衡量。即吞吐率。
衡量吞吐能力的指标一般有 QPS 、 TPS 、字节数/秒 和 页面数/秒等。
用户思考时间
在真实场景中,用户要完成某个业务(如支付)需要多个步骤,而每个步骤用户都需要一定的思考时间,这里每步操作之间的停顿的时间,即用户思考时间。
TP99
TP 的全称是 Top Percentile,即 Top 百分位数,此指标衡量的是某百分位处的请求响应时间,主要用于衡量对响应时间敏感的服务。比如:
- TP90:按响应时间从小到大排列,位于 90% 处的响应时间;
- TP99:按响应时间从小到大排列,位于 99% 处的响应时间;
- TP999:按响应时间从小到大排列,位于 999% 处的响应时间。
TP 百分位数要求越高,则表示对性能要求越高。
PV
PV 的全称是 Page View,即页面访问量。
UV
UV 的全称是 Unique Visitor ,独立访客量,即去重后的访问用户数。
DAU
DAU 的全称是 Daily Active User,即日活跃用户数。
MAU
MAU 的全称是 Month Active User,即月活跃用户数。
名词概念之间的关系
了解了基本的名称概念后,还需要了解一些重要概念之间的关系,要知道有些指标概念之间是有一定的关系的,甚至是可以相互影响的。
下面介绍一些重要概念之间的关系。
QPS vs TPS
复杂场景下,用户要完成某个事务,可能需要访问多个或多次接口,此时:1TPS = nQPS。
对于简单场景,如完成一个事务,只需要访问一次一个接口,此时:1TPS = 1QPS。
并发用户数 vs 并发量
在多接口的复杂场景下,一个用户可能同时访问多个接口,此时对于系统来说,并发用户数 < 并发请求数。
在简单串行场景下,一个用户逐个访问单接口,此时对于系统来说,并发用户数 = 并发请求数。
并发量 vs 系统并发处理数
当并发量 > 系统并发处理能力时,并发量 > 系统并发处理数。
当并发量 <= 系统并发处理能力时,并发量 = 系统并发处理数。
TPS & RT & 系统并发处理数 & 用户思考时间
TPS = 系统并发处理数 / ( RT + 用户思考时间)。
系统并发处理数,是服务端同时处理的请求数。
RT 为系统平均响应时间,它的大小是网络传输时间总和、服务处理时间总和、数据库响应时间总和、缓存响应时间总和、磁盘IO时间总和以及其他时间的总和。
用户思考时间,对于单接口来说,是零;对于复杂接口(如完成支付事务)来说:用户思考时间 = 用户各操作步骤间隔时间。
TPS & RT & 并发数
系统 TPS 、RT 和并发数是相互影响的。其三者之间的影响关系,可以根据并发数的提升分为系统低负荷阶段、系统满负荷阶段和系统超负荷阶段。如下图所示。
在系统低负荷阶段(轻压力区),并发数很低,CPU 工作不饱和,随着并发数的增长, TPS 跟着增长, RT 几乎是平稳的。
随着并发数的增大,系统进入满负荷状态(重压力区),CPU 工作进入饱和状态,这时系统资源利用率达到最大值,TPS 达到最大值,RT 开始明显增长。
进一步增大并发数,系统就会进入超负荷状态(拐点区),这时系统开始处理大量请求,线程频繁切换,CPU load 超负荷,而此时真正处理的请求数反而会降低,最终导致 TPS 下降,RT指数级增长。
核心目标
要实现高并发系统,必须满足以下三个目标:
- 高性能
高性能,即系统的并行处理能力,其主要的衡量指标是 RT 和并发处理数。根据系统的 TPS 计算公式,TPS = 并发处理数 / RT ,要想提高系统的性能,一是要提高系统并发处理能力,二是要降低系统处理的 RT 。
显而易见,高性能是高并发系统最主要的目标之一。比如你的系统响应时间是 10S ,别人的系统响应时间是 0.1S ,那用户体验是截然不同的。再比如你的系统只能支持 100 人来抢购,别人的系统能支持 10000 人来抢购,很可能用户来一次就不想再来了。
- 高可用
高可用,即系统的稳定性。简单来讲,当秒杀活动的用户流量来临时,你的系统能不能稳定的处理这些流量,别流量一来,你的系统就崩掉了。
显而易见,系统的可用性也是高并发系统的最主要的目标之一。比如秒杀活动期间,流量一来,你的系统崩掉了,这时想必用户要崩溃了,不仅买不到自己想要的商品,也会影响平台口碑:招商招不来,用户不来买等等。
可用性的衡量指标一般用可用率来表示,可用率 = 正常运行时间 / 总运行时间。
业内一般用几个 9 来表示系统的可用性,比如可用性是 4 个 9 ,则表示可用率 = 99.99% ,总运行时间按一年时间来算的化,每年的不可用时间要小于 51.264m(356 * 24 * 60 * (1-99.99%))
- 高伸缩性
高伸缩性,指的是系统能不能通过增减硬件配置,来扩容和缩容集群吞吐能力。
在实际线上场景中,平时流量一般不会特别大,而秒杀活动期间的流量可能是平时流量的数十倍,甚至是上百倍。从成本上考虑,假如一直用秒杀活动的硬件配置,显然太过浪费了。最好的效果是可以在平时用少量的硬件配置,在活动期间增加到大流量的配置。以此来充分有效的节约机器成本。
衡量高伸缩性的方式,就是要看系统的吞吐能力是不是能随着机器的扩容而增强,随着机器的缩容而降低。比如增加一倍的机器,能不能增加一倍的吞吐能力。
如何设计高并发系统
系统拆分
就是把单体系统拆分成多个微服务,一个微服务挂了不会影响其他微服务,通过兼容、容错等方法忽略当前微服务宕机带来的影响。
集群部署
一个服务部署多个实例,通过负载均衡、服务发现做调度
缓存
一般用redis缓存、内存缓存,将那些经常需要查询并且变动较小的缓存起来,可以做长时间缓存,也可以做短暂的缓存,当前请求有效。
CDN
加速静态资源访问
异步排队
使用消息队列,将请求或者耗时的操作放到消息队列中慢慢处理,实现削峰填谷。
分库分表
按照某个业务关键字分库分表,比如按租户分库,按月份分表等
池子化技术
很多耗时耗资源的第三方链接可以通过连接池实现服用。比如http连接、rpc连接、db连接、redis连接、线程等,通过池化技术先初始化好连接,待到要使用的时候直接用,用完放回去,下次接着用。
读写分离
一般是主从分离,一主多从,写主读从。
ES
Elasticsearch 分布式、高扩展、高实时的搜索与数据分析引擎,简称为ES
。一般耗时的查询、统计、全文搜索可以用ES
熔断
当访问量突增或者某个机房遇到突发情况时,需要做一些降级措施,防止影响其他服务。比如通过开关,关闭某些请求或者服务,切换流量
限流
可以在接口上增加一些限流器来限制访问频率。
总结
参考
[1]架构系列:高并发架构的CDN知识介绍
[2]如何设计一个高并发系统?
[3]高并发系统,你真理解了吗?
[4]高并发系统设计 40 问
[5]高并发系统是如何设计的?
[6]字节三面:如何设计一个高并发系统