跳到主要内容

认识

2024年04月24日
柏拉文
越努力,越幸运

一、认识


削峰限流 是为了避免激增的大数据量、恶意用户访问等高并发数据导致的服务崩溃。假设说,有某一个时间点,突然间流量爆炸,无数的数据向服务器访问过来,这时如果没有一个削峰限流的策略,很可能会导致机器 Down 掉。所以说我们有必要去做一个削峰限流,从概率学的角度上讲,在大数据量的基础上我们对于整体数据做一个百分比的截断,并不会影响整体的一个数据比例。

削峰限流 有如下方案:

  1. 随机丢弃策略

  2. 流量整型策略

二、随机丢弃策略


前端做削峰限流最简单的方法是什么?没错,就是 Math.random() ,我们让用户传入一个采样率:

if(Math.random()<0.5) return;

非常简单的就实现了!但是这个方案不是一个很优雅的解决办法,为什么呢?

  1. 大流量项目限制了 50% 的流量,它的流量仍然多

  2. 小流量项目限制了 50% 的流量,那就没有流量了

三、流量整型策略


现在做流量整形的方法很多,最常见的就是三种:

  1. 计数器算法: 计数器算法就是单位时间内入库数量固定,后面的数据全部丢弃;缺点是无法应对恶意用户。计数器能够削峰,限制最大并发数以保证服务高可用

  2. 漏桶算法: 漏桶算法就是系统以固有的速率处理请求,当请求太多超过了桶的容量时,请求就会被丢弃;缺点是漏桶算法对于骤增的流量来说缺乏效率

  3. 令牌桶算法: 令牌桶算法就是系统会以恒定的速度往固定容量的桶里放入令牌,当请求需要被处理时就会从桶里取一个令牌,当没有令牌可取的时候就会据拒绝服务。令牌桶实现流量均匀入库,保证下游服务健康

最后我们团队在上述的方案选择中,最终选择了 计数器 + 令牌桶 的方案:

  1. 首先从外部来的流量是我们无法预估的,假设如我们有三个服务器Pod ,如果总流量来的非常大,那么这时我们通过计数器算法,给它设置一个很大的最大值;这个最大值只防小人不防君子,可能 99% 的项目都不会触发

  2. 这样经过总流量的计数器削峰后,再到中心化的令牌桶限流:通过 redis 来实现,我们先做一个定时器每分钟都去令牌桶里写令牌,然后单机的流量每个进来后,都去 redis 里取令牌,有令牌就处理入库;没有令牌就把流量抛弃

  3. 这样子我们就实现了一个单机的削峰 + 中心化的限流,两者一结合,就是解决了小流量应用限流后没流量的问题,以及控制了入库的数量均匀且稳定