如果你的系统QPS突然提升10倍你会怎样设计
QPS即每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。QPS = req/sec = 请求数/秒,即每秒的响应请求数,也即是最大吞吐能力。
1、硬件的扩展+微服务的拆分
互联网早期时,单体架构足以支撑日常业务需求,所有业务服务都在同一个项目里,部署在同一台机器上。所有业务包括交易系统,会员信息,库存,商品等都夹杂在一起,当流量一旦起来后,单体架构的问题就暴露出来,机器挂了所有业务全部无法使用。
集群架构开始出现,单击无法抗住压力,最简单的办法就是水平拓展横向扩容,这样通过负载均衡把压力流量分摊到不同机器上,暂时解决了单点导致服务不可用问题。
随着业务发展,在一个项目里维护所有的业务场景使开发和代码维护变得复杂和困难,一个简单的需求改动都需要发布整个服务,代码合并冲突也会变得越来越频繁,同时线上故障出现的可能性越大。微服务的架构模式诞生了。
把每个独立的业务拆分开独立部署,开发和维护成本降低,集群能承受的压力也提高了,再也不会出现一个小小的改动点儿需要大量改动(牵一发而动全身)。
以上的点从高并发的角度而言,似乎都可以归类为通过服务拆分和集群物理机器的扩展,提高整个系统的抗压能力,那么,随之拆分而带来的问题也就是高并发系统需要解决问题。
2、高性能PRC
微服务拆分带来的好处和便利性是显而易见的,但是与此同时各个微服务之间通信就需要考虑了。传统HTTP的通信方式性能首先不好,大量的请求头之类无效的信息是对性能的浪费,这时候就需要引入诸如Dubbo类的RPC框架。
RPC 全称 Remote Procedure Call——远程过程调用。
- RPC技术简单说就是为了解决远程调用服务的一种技术,使得调用者像调用本地服务一样方便透明。
- RPC是一种通过网络从远程计算机程序上请求服务,不需要了解底层网络技术的协议。
为什么要有RPC?
服务化:微服务化,跨平台的服务之间远程调用;
分布式系统架构:分布式服务跨机器进行远程调用;
服务可重用:开发一个公共能力服务,供多个服务远程调用。
系统间交互调用:两台服务器A、B,服务器 A 上的应用 a 需要调用服务器 B 上的应用 b 提供的方法,而应用 a 和应用 b 不在一个内存空间,不能直接调用,此时,需要通过网络传输来表达需要调用的语义及传输调用的数据。使用场景
大型网站
:内部涉及多个子系统,服务、接口较多。注册发现机制
:如Nacos、Dubbo等,一般都有注册中心,服务有多个实例,调用方调用的哪个实例无感知。安全性
:不暴露资源。服务化治理
:微服务架构、分布式架构。
Dubbo RPC的性能相较于Feign RPC性能,测试约近提高10倍,我们假设原来来自客户端的QPS是9000,那么通过负载均衡策略分散到每台机器就是3000,而Fegin HTTP RPC改为Dubbo RPC之后,接口的耗时缩短了,单体服务和整个QPS就提升了。
而PRC框架本身一般都自带负载均衡,熔断降级的机制,可以更好的维护整个系统的高可用,国内应用较多的选择DUbbo。
3、消息队列削峰解耦
MQ的作用:
1.削峰填谷、解耦
2.同步转异步的方式,可以降低微服务之间的耦合
对于一些不需要同步执行的接口,可以通过引入消息队列的方式异步执行以提高接口响应时间,在完成交易之后需要扣库存,然后可能需要给会员发放积分,本质上发积分的动作应该所属履约服务,对实时性要求不高,我们只要保证最终一致行也就是能履约成功了。
对于这种同类性质的请求就可以走MQ异步,提高系统抗压性能。
4、三级缓存架构
缓存作为高性能的代表,在特殊业务可能承担90%以上的热点流量。
对于一些活动比如秒杀,这种并发QPS可能几十万的场景,引入缓存事先预热可以大幅降低对数据库的压力,10万的QPS对于单机的数据库来说可能就挂了,但对于入redis的缓存来说就不是问题
以秒杀系统举例,活动预热商品信息,可以提前缓存提供查询服务,库存数据可以提前缓存,下单流程可以完全走缓存扣减,秒杀结束再异步写入数据库,数据库承担的压力就小太多了。
5、数据库分库分表
对于整个系统而言,最终所有的流量的查询和写入都落在数据库上,数据库是支撑系统高并发能力的核心。
怎么降低数据库压力,提升数据的性能是支撑高并发的基石,主要的方式就是通过读写分离和分库分表来解决这个问题。
对于整个系统而言,流量应该是一个漏斗形式,比如我们日活跃用户数量DAU有20万,实际可能每天来到提单页的用户只有3万QPS,最终转换到下单支付成功的QPS只有1万,那么对于系统来说读是大于写的,这时候可以通过读写分离的方式降低数据的压力。
读写分离也就相当于数据库集群的方式降低了单节点压力,而面对数据的急剧增长,原来的单库单表的存储方式已经无法支撑整个业务的发展,这时候就需要对数据库进行分库分表。针对微服务而言垂直的分库本身已经做过的,剩下大部分都是分表的方案了。
6、高可用
6.1熔断
比如营销服务挂了或者接口大量超时的异常情况,不能影响下单的主链路,涉及到积分的扣减一些操作可以在事后做补救。
6.2限流
对突发如大促秒杀类的高并发,如果一些接口不做限流处理,可能直接就把服务打挂了,针对每个接口的压测性能的评估做出合适的限流尤为重要。
6.3降级
熔断之后可以说就是降级的一种,以熔断的举例来说,营销接口熔断之后降级方案就是短时间内不再调用营销的服务,等到营销恢复之后再调用。
6.4预案
一般来说,就算有统一配置中心,在业务的高峰期也是不允许做出任何变更的,但是通过配置合理的预案可以在紧急的时候做出一些修改。
6.5核对
针对各种分布式系统产生的分布式事务一致性或者受到攻击导致数据异常,就需要核对平台来做最后的数据兜底的数据验证。比如下游支付系统和订单系统的金额做核对是否正确,如果收到中间人攻击落库的数据是否保证正确性。
7、总结
其实可以看到,怎么设计高并发系统这个问题本身是不难的,无非是基于你知道的知识点,从物理硬件层面到软件的架构,代码层面的优化,使用什么中间件来不断提高系统的抗压能力。
但是,这个问题本身会带来很多问题,微服务本身的拆分带来了分布式事务问题,http,RPC框架的使用带来了通信效率。路由。容错的问题,MQ的引入带来了消息丢失、积压、事务消息、顺序消息问题。
缓存的引入又会带来一致性。雪崩。击穿的问题。
数据库的读写分离,分库分表又会带来主从同步延迟。分布式ID、事务一致性的问题,而为了解决这些问题,我们有要不断地加入各种措施熔断,限流,降级,离线核对,预案处理等等来防止和追溯这些问题。