• 常见限流算法


    常见限流算法

    计数器算法(固定窗口):

      描述:指定时间段内只能通过N个请求,多与的请求被拒绝,当时间节点到达下一个阶段的时候重置允许通过的数量N

      实现:一段时间我们可以时间毫秒除单位时间 做为阶段标志来区分时间段,初始化计数器的时候设置容量为N,来一个请求N-1,N=0 的时候拒绝后面的请求,如果毫秒取模最为阶段标志变化的时候重置容量N开始下一个阶段

      优点:简单,并且可以限流

      缺点:下一个阶段前后(重置容量的前后),瞬时运行通过数变成2N

    滑动窗算法:

      描述:相当于固定窗口细分成多个小窗口,每次移动一个小窗口,每次重置的小部分容量,这样通过的请求会更加平滑。

      实现:计数器算法的基础上,分成10 个阶段,用阶段标志/10,来区分小窗口,然后请求来了就计请求数量+1,这阶段的当前总容量动态计算 N/10*窗口小阶段编号。

      优点:比计算器算法平滑,

      缺点:滑动窗口还是有重置容量的问题,虽然分成了多个阶段重启,容量匀速增加。在小窗切换的过程中基本和令牌桶一样平滑,但是在切换到下一个大窗口的时候容量有一个重置的过程。总的来说没有令牌桶平滑。

      备注:滑动窗和令牌桶平滑程度没有严格的界限,他们都差不多,令牌桶说的匀速增加容量不可能是绝对的匀速增加。它们两个平滑程度通过量没有严格的界限,只是显现方式不一样。

    令牌桶算法:

      描述:向一个桶里面匀速的放入令牌,桶的容量有限,超过容量就不在放入,业务要执行钱需要去桶里拿到令牌,然后才能执行,如果桶空了,拿不到令牌,请求放弃。

      实现:一个队列作为桶,一个后台线程用恒定的速度向 里面加入令牌,业务线程在队列的出口领取令牌 (正常不一定会做真的有令牌,只要令牌数量增加就行,和滑动窗口最大的区别在于是另外的线程添加令牌,没有划过大窗口时候重置容量的抖动 )

      优点:平滑的添加容量,瞬时最大允许通过数是N(相对计数器的瞬时情况来说是N+1)

      缺点:相对漏桶,令牌桶桶只有限流作用,没用缓冲作用。

    漏桶算法:

      描述:请求过来,入桶,痛的容量固定,桶满拒绝,桶下游个洞,恒定的速度漏漏出(处理请求)

      实现:一个队列作为桶,请求过来直接入桶,然后别的线程恒定的速度异步的去消费漏下来的请求,为啥漏桶一般是异步的?因为入口速度任意,出口速度恒定,所以一般是异步的,当然算法死的人是活的,要等待然后同步返回也可以。

      优点:最平滑,如果设计合理并且业务运行,可以设置很大的桶容量,缓冲瞬时流量

      缺点:异步,瞬时通过数是恒定下游线程处理速率个,瞬时接受的请求最多是N(相对计数器的瞬时情况来说是N+1),这个瞬时接受的请求是放在桶里面的,并没有真的执行。真正瞬间是下游决定的。对瞬时请求的处理太弱。

      

    令牌桶限流类 RateLimiter(很多jar包都有他的实现),redisson有它支持集群的实现

      RateLimiter 的原理:

          1,RateLimiter 原理:下一次请求的时候,通过当前时间和上次生成最后一个令牌的时间算一个时间差,然算出这段时间应该生成多少令牌,然后计算可用牌数够不够,不够返回没有令牌(非阻塞),或者计算出一个令牌数量够了的时间点,睡眠等待时间达到然后返回(阻塞方式)
          2,另外 RateLimiter 有允许刚开始多发一小段时间(预消费 nextFreeTicketMicros )
          3,RateLimiter 精确到 每微秒 N个 令牌( double stableIntervalMicros; ),小于微秒以后就不是平每微秒都增加了

    限流类Semaphore(Java自带),redisson有它支持集群的实现,它强调的一瞬间并发只能允许多少通过,而不是一定时间内能通过多少个,和前面的限流算法有本质的区别。

    总结:计数器算法,滑动窗口算法,令牌桶算法,抛开实现方式,我们只谈通过情况他们是一类的

      单位指定后添加容量的是计数器算法

      单位时间中,阶段的添加容量的是滑动窗口,但是有大窗切换的容量重置

      单位时间中匀速的添加容量的令牌桶,没有容量重置。

      带有缓冲,更加适合业务允许异步的 是漏桶

      要求限制瞬时通过量,而不是单位时间通过量的 信号量(Semaphore)

  • 相关阅读:
    为什么 TCP 建立连接是三次握手,关闭连接确是四次挥手呢?
    一文搞懂 Java 中的枚举,写得非常好!
    IntelliJ IDEA For Mac 快捷键,够骚,速度收藏!
    Java Bean 为什么必须要有一个无参构造函数?
    18 个示例带你掌握 Java 8 日期时间处理!
    从入门到熟悉 HTTPS 的 9 个问题
    MyBatis的动态SQL详解
    MyBatis总结-实现关联表查询
    AngularJS
    Spring MVC url提交参数和获取参数
  • 原文地址:https://www.cnblogs.com/cxygg/p/16182134.html
Copyright © 2020-2023  润新知