流量削峰
一、流量削峰的场景
流量高峰主要是用于应对大流量的业务,短时间内大量的用户抢占有限的商品或资源所发生的高并发场景。比如我们春节火车票的抢购,上亿用户在线抢票,双十一疯狂的女人在线剁手;某促销活动几百万人同时在某个时间点抢购有限数量的折扣商品等。以促销活动为例,实际上真实能购买到该件商品的用户也只有固定的几百人(商品实际数量),但是从业务上来说,秒杀活动是希望更多的人来参与,也就是抢购之前希望有越来越多的人来看购买商品(大部分的高并发都是业务噱头,甚至可以通过业务来避免)。用户开始真正下单时,秒杀的服务器后端却不希望同时有几百万人同时发起抢购请求(无法承担)。我们知道服务器的处理资源是有限的,请求与业务处理都是需要消耗资源,所以当瞬间请求过多的时候,服务器的资源都会倾斜向处理接收请求,那么留给业务处理的资源也就少了,当瞬间请求到达一定的峰值时,便很容易导致请求阻塞,用户响应延迟,服务器宕机,系统崩溃等一系列问题出现。这就好比出行的时候存在早高峰和晚高峰的问题,为了解决这个问题,出行就有了错峰限行的解决方案。同理,在线上的秒杀等业务场景,也需要类似的解决方案,需要平安度过大批量数据并发抢购带来的流量峰值的问题,这就是流量削峰的由来。总结:有限的资源,超额的负载,系统不堪重负!
二、怎样来实现流量削峰方案
削峰从本质上来说是更多地延缓用户请求,以及层层过滤用户的访问需求,遵从“最后落地到数据库的请求数要尽量少”的原则。
1. 消息队列解决削峰
要对流量进行削峰,最通用的解决方案就是用消息队列来缓冲瞬时流量,把同步的直接调用转换成异步的间接推送,中间通过一个队列在一端承接瞬时的流量洪峰,在另一端平滑地将消息推送出去,消息队列本质就是一个缓冲区,用于延缓数据请求。在这里,消息队列就像“水库”一样,拦蓄上游的洪水,削减进入下游河道的洪峰流量,从而达到减免洪水灾害的目的。
消息队列中间件主要解决应用耦合,异步消息, 流量削锋等问题。常用消息队列系统:目前在并发生产环境,使用较多的消息队列有 ActiveMQ、RabbitMQ、 ZeroMQ、Kafka、MetaMQ、RocketMQ等。其中RabbitMQ几乎是各大并发系统的首选!
2. 流量削峰漏斗:层层削峰
针对秒杀场景还有一种方法,就是对请求进行分层过滤,从而过滤掉一些无效的请求。分层过滤可以类比为“漏斗”式设计来处理请求的,如下图所示:
这样就像漏斗一样,尽量把数据量和请求量一层一层地过滤和减少了。
1)分层过滤的核心思想 通过在不同的层次尽可能地过滤掉无效请求。在不影响用户体验的情况下降低用户的请求频率。通过CDN过滤掉大量的图片,静态资源的请求。通过类似Redis这样的高性能内存数据库进行缓存处理,过滤请求等上在游拦截读请求,从而尽量减少数据库的命中率。
2)分层过滤的基本原则 对写数据进行基于时间的合理分片,过滤掉过期的失效请求。对写请求做限流保护,将超出系统承载能力的请求过滤掉。涉及到的读数据不做强一致性校验,减少因为一致性校验产生瓶颈的问题。对写数据进行强一致性校验,只保留最后有效的数据。针对热点数据进行做好缓存处理并通过合理方式确保一致性。最终,让“漏斗”最末端(数据库)的才是有效请求。例如:当用户真实达到订单和支付的流程,这个是需要数据强一致性的。
三、总结
1.对于秒杀这样的高并发场景业务,最基本的原则就是将请求拦截在系统上游,降低下游压力,减少对数据库的访问。
2.划分好动静资源,静态资源使用CDN进行服务分发。
3.充分利用缓存(redis等):增加QPS,从而加大整个集群的吞吐量。
4.高峰值流量是压垮系统很重要的原因,所以在需要时可以利用Kafka等消息队列在一端承接瞬时的流量洪峰,在另一端平滑地将消息推送出去。
利用高可用的性能组件进行缓存热点数据,减少对数据库的访问。