对高并发流量控制的一点思考

前言
在实际项目中 , 曾经遭遇过线上5W+QPS的峰值 , 也在压测状态下经历过10W+QPS的大流量请求 , 本篇的话题主要就是自己对高并发流量控制的一点思考 。
应对大流量的一些思路

首先 , 我们来说一下什么是大流量?
大流量 , 我们很可能会冒出:TPS(每秒事务量) , QPS(每秒请求量) , 1W+ , 5W+ , 10W+ , 100W+... 。其实并没有一个绝对的数字 , 如果这个量造成了系统的压力 , 影响了系统的性能 , 那么这个量就可以称之为大流量了 。
其次 , 应对大流量的一些常见手段是什么?
缓存:说白了 , 就是让数据尽早进入缓存 , 离程序近一点 , 不要大量频繁的访问DB 。
降级:如果不是核心链路 , 那么就把这个服务降级掉 。打个比喻 , 现在的App都讲究千人千面 , 拿到数据后 , 做个性化排序展示 , 如果在大流量下 , 这个排序就可以降级掉!
限流:大家都知道 , 北京地铁早高峰 , 地铁站都会做一件事情 , 就是限流了!想法很直接 , 就是想在一定时间内把请求限制在一定范围内 , 保证系统不被冲垮 , 同时尽可能提升系统的吞吐量 。
注意到 , 有些时候 , 缓存和降级是解决不了问题的 , 比如 , 电商的双十一 , 用户的购买 , 下单等行为 , 是涉及到大量写操作 , 而且是核心链路 , 无法降级的 , 这个时候 , 限流就比较重要了 。
那么接下来 , 我们重点说一下 , 限流 。
限流的常用方式
限流的常用处理手段有:计数器、滑动窗口、漏桶、令牌 。
计数器
 
计数器是一种比较简单的限流算法 , 用途比较广泛 , 在接口层面 , 很多地方使用这种方式限流 。在一段时间内 , 进行计数 , 与阀值进行比较 , 到了时间临界点 , 将计数器清0 。

对高并发流量控制的一点思考

文章插图
 

对高并发流量控制的一点思考

文章插图
【对高并发流量控制的一点思考】 
这里需要注意的是 , 存在一个时间临界点的问题 。举个栗子 , 在12:01:00到12:01:58这段时间内没有用户请求 , 然后在12:01:59这一瞬时发出100个请求 , OK , 然后在12:02:00这一瞬时又发出了100个请求 。这里你应该能感受到 , 在这个临界点可能会承受恶意用户的大量请求 , 甚至超出系统预期的承受 。
滑动窗口
 
由于计数器存在临界点缺陷 , 后来出现了滑动窗口算法来解决 。
滑动窗口的意思是说把固定时间片 , 进行划分 , 并且随着时间的流逝 , 进行移动 , 这样就巧妙的避开了计数器的临界点问题 。也就是说这些固定数量的可以移动的格子 , 将会进行计数判断阀值 , 因此格子的数量影响着滑动窗口算法的精度 。
漏桶
 
虽然滑动窗口有效避免了时间临界点的问题 , 但是依然有时间片的概念 , 而漏桶算法在这方面比滑动窗口而言 , 更加先进 。
有一个固定的桶 , 进水的速率是不确定的 , 但是出水的速率是恒定的 , 当水满的时候是会溢出的 。

对高并发流量控制的一点思考

文章插图
 

对高并发流量控制的一点思考

文章插图
 
令牌桶
 
注意到 , 漏桶的出水速度是恒定的 , 那么意味着如果瞬时大流量的话 , 将有大部分请求被丢弃掉(也就是所谓的溢出) 。为了解决这个问题 , 令牌桶进行了算法改进 。
生成令牌的速度是恒定的 , 而请求去拿令牌是没有速度限制的 。这意味 , 面对瞬时大流量 , 该算法可以在短时间内请求拿到大量令牌 , 而且拿令牌的过程并不是消耗很大的事情 。(有一点生产令牌 , 消费令牌的意味)


推荐阅读