限流算法:漏斗算法和令牌桶算法


限流算法:漏斗算法和令牌桶算法

来历

这两个算法来源于计算机网络。在网络传输数据时,为了防止网络拥塞,需要限制网络中的流量,即限流

漏斗算法

水(大量并发的用户请求)进入漏斗里,漏斗以一定的速度出水。当水流入的速度过大也就是漏斗满了的话,直接进行溢出。

漏斗算法被认为是一种粗暴的限流算法,因为并不是所有情况下当前没抢到商品的请求都要被抛弃,因此这种强制性过滤算法并不具备灵活性

优点:能强行限制数据的传输速率

缺点:不灵活,漏桶算法不能够有效地使用网络资源

令牌桶算法

令牌桶算法原理如下:水(用户请求)必须拿到令牌才代表消费成功。而“令牌数”有一个初始值,令牌桶也有一个令牌存储上限,当桶中的令牌耗光后,令牌桶会以自定义的速度生产令牌,此时所有的水(用户请求)会进入阻塞状态,阻塞时间内如果得到了令牌就会消费成功,如果阻塞时间过了还没有得到令牌,请求会被抛弃。

当用户请求没有经过时,令牌桶本身会不断生产令牌,直到令牌达到上限为止。这样做的好处是,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌,支持了突发请求

优点:突发传输

使用场景

漏桶算法:恒定速率流出,不支持突发流量。在依赖服务没有做限流的场景下,可以用于防止打垮我们依赖服务,因为第三方服务的最大水位及其在最大水位可持续服务多长时间,对上层服务是未知的。

令牌桶算法:恒定速率流入,可以支持突发流量。通常突发流量最大值对于我们自己维护的服务是清晰可控的,为保证系统的最大可用性(尽可能处理更多的请求),同时防止自己的服务被打垮,优先使用令牌桶算法。

Java使用

Guava中开源出来一个令牌桶算法的工具类RateLimiter,可以轻松实现限流的工作。

1、引入相关的依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

2、Demo

public class RateLimiterTest {
    public static void main(String[] args) throws InterruptedException {
        RateLimiter limiter = RateLimiter.create(10);
        Thread.currentThread().sleep(1000);
        if (limiter.tryAcquire(20))
            System.out.println("======== Time1:" + System.currentTimeMillis() / 1000);
        Thread.currentThread().sleep(1001);
        if (limiter.tryAcquire(1))//代码3
            System.out.println("======== Time2:" + System.currentTimeMillis() / 1000);
        if (limiter.tryAcquire(5))
            System.out.println("======== Time3:" + System.currentTimeMillis() / 1000);
    }
}

文章作者: Bxan
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bxan !
  目录