高并发,几乎是每个程序员都想拥有的经验。原因很简单:随着流量变大,会遇到各种各样的技术问题,比如接口响应超时、CPU load 升高、GC 频繁、死锁、大数据量存储等等,这些问题能推动我们在技术深度上不断精进。
什么是高并发 ?
高并发 (High Concurrency): 高并发意味着大流量,需要运用技术手段抵抗流量的冲击,这些手段好比操作流量,能让流量更平稳地被系统所处理,带给用户更好的体验。
我们常见的高并发场景有:淘宝的双11、春运时的抢票、微博大V的热点新闻等。除了这些典型事情,每秒几十万请求的秒杀系统、每天千万级的订单系统、每天亿级日活的信息流系统等,都可以归为高并发。
高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等
那到底多大并发才算高并发呢 ?
不能只看数字,要看具体的业务场景.不能说 10W QPS 的秒杀是高并发,而 1W QPS 的信息流就不是高并发。信息流场景涉及复杂的推荐模型和各种人工策略,它的业务逻辑可能比秒杀场景复杂 10 倍不止。因此,不在同一个维度,没有任何比较意义。
业务都是从 0 到 1 做起来的,并发量和 QPS 只是参考指标,最重要的是:在业务量逐渐变成原来的 10 倍、100 倍的过程中,你是否用到了高并发的处理方法去严谨你的系统,从架构设计、编码实现、甚至产品方案等维度去预防和解决高并发引起的问题?
如何提升系统的并发能力 ?
互联网分布式架构设计,提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。
垂直扩展
- 垂直扩展:提升单机处理能力。垂直扩展的方式又有两种:
- 增强单机硬件性能,例如:增加CPU核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G;
- 提升单机架构性能,例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;
水平扩展
- 水平扩展:只要增加服务器数量,就能线性扩充系统性能。
实践方案
高性能的实践方案
- 集群部署, 通过负载均衡减轻单机压力
- 多级缓存, 包括静态数据使用CDN,本地缓存,分布式缓存等, 以及对缓存场景中的热点 key、缓存穿透、缓存并发、数据一致性等问题的处理。
- 分库分表和索引优化, 以及借助搜索引擎解决复杂查询问题
- 考虑 NoSQL 数据库的使用,比如 HBase、TiDB 等,但是团队必须熟悉这些组件,且有较强的运维能力。
- 异步化, 将次要流程通过多线程, MQ, 甚至延迟任务进行异步处理
- 限流, 需要先考虑业务是否允许限流,比如秒杀场景是允许的),包括前端限流、Nginx 接入层的限流、服务端的限流。
- 对流量进行削峰填谷,通过 MQ 承接流量。
- 并发处理,通过多线程将串行逻辑并行化
- 预计算,比如抢红包场景,可以提前计算好红包金额缓存起来,发红包时直接使用即可。
- 缓存预热,通过异步任务提前预热数据到本地缓存或者分布式缓存中。
- 减少 IO 次数,比如数据库和缓存的批量读写、RPC 的批量接口支持、或者通过冗余数据的方式干掉 RPC 调用。
- 减少 IO 时的数据包大小,包括采用轻量级的通信协议、合适的数据结构、去掉接口中的多余字段、减少缓存 key 的大小、压缩缓存 value 等。
- 程序逻辑优化,比如将大概率阻断执行流程的判断逻辑前置、For 循环的计算逻辑优化,或者采用更高效的算法。
- 各种池化技术的使用和池大小的设置,包括 HTTP 请求池、线程池(考虑 CPU 密集型还是 IO 密集型设置核心参数)、数据库和 Redis 连接池等。
- JVM 优化,包括新生代和老年代的大小、GC 算法的选择等,尽可能减少 GC 频率和耗时。
- 锁选择,读多写少的场景用乐观锁,或者考虑通过分段锁的方式减少锁冲突。
高可用的实践方案
- 对等节点的故障转移,Nginx 和服务治理框架均支持一个节点失败后访问另一个节点。
- 非对等节点的故障转移,通过心跳检测并实施主备切换(比如 redis 的哨兵模式或者集群模式、MySQL 的主从切换等)。
- 接口层面的超时设置、重试策略和幂等设计。
- 降级处理:保证核心服务,牺牲非核心服务,必要时进行熔断;或者核心链路出问题时,有备选链路。
- 限流处理:对超过系统处理能力的请求直接拒绝或者返回错误码。
- MQ 场景的消息可靠性保证,包括 producer 端的重试机制、broker 侧的持久化、consumer 端的 ack 机制等
- 灰度发布,能支持按机器维度进行小流量部署,观察系统日志和业务指标,等运行平稳后再推全量。
- 监控报警:全方位的监控体系,包括最基础的 CPU、内存、磁盘、网络的监控,以及 Web 服务器、JVM、数据库、各类中间件的监控和业务指标的监控。
- 灾备演练:类似当前的“混沌工程”,对系统进行一些破坏性手段,观察局部故障是否会引起可用性问题。
高扩展的实践方案
- 合理的分层架构:比如上面谈到的互联网最常见的分层架构,另外还能进一步按照数据访问层、业务逻辑层对微服务做更细粒度的分层(但是需要评估性能,会存在网络多一跳的情况)。
- 存储层的拆分:按照业务维度做垂直拆分、按照数据特征维度进一步做水平拆分(分库分表)。
- 业务层的拆分:最常见的是按照业务维度拆(比如电商场景的商品服务、订单服务等),也可以按照核心接口和非核心接口拆,还可以按照请求去拆(比如 To C 和 To B,APP 和 H5)。