8分钟看懂限流算法【视频】

视频介绍限流算法,分析漏桶算法和令牌算法的应用场景,算法原理和算法实现方法html

不想看文字的,就来看视频: 《8分钟看懂限流算法》https://www.bilibili.com/video/av26350725git

你好,我是好刚,这一讲咱们来了解限流算法 (Rate Limiting Throttling)。github

1. 应用场景

首先咱们看一个典型的应用场景,好比在商品抢购的场景里面,可能会有百万级别的用户请求咱们的抢购接口。算法

15308061436c94ee9e

这个时候若是不作任何保护措施,服务器就会承受很大的处理压力,请求量很高,服务器负载也很高,而且当请求超过服务器承载极限的时候,系统就会崩溃,致使全部人都不能访问。为了保证抢购服务的可用性,一个经常使用的办法是对秒杀请求进行限流,拦截掉大部分请求,只容许一部分请求真正进入后端服务器,这样就能够防止大量请求形成系统压力过大致使的系统崩溃,从而保护服务正常可用。这里限流的经常使用算法有漏桶算法和令牌桶算法。spring

2. 漏桶算法

咱们先来看漏桶算法(Leaky Bucket),先想象有一个木桶,新请求就像水滴同样,不断地滴进来,水滴进来的速度是不肯定的,有时会快一点,有时会慢一点,同时桶底下有个洞,能够按照固定的速度把水漏走,若是水进来的速度比漏走的快,桶就会满了,桶满了水就会漫出来,对应的就是拒绝请求。后端

漏桶算法的主要特色是能够平滑网络上的突发流量,请求能够被整造成稳定的流量。bash

1530806142c6c11

算法伪代码以下:服务器

C               // 水桶总容量
r               // 漏水速度
at              // 上一个请求时间
w               // 当前桶里面的水量

when (b):
  	bt = now();
  	wb = (bt - at) * r  // 已经流出的水
 	w = max(w - wb, 0)  // 桶里面的水量减去流走的水量等于当前水量,最多流干等于0

    if w < C:           // 水桶还没满,能够继续添加
        w ++;
        return true
    else:
        return false
复制代码

3. 令牌桶算法

咱们再看下令牌桶算法(Token Bucket)。也是先有一个木桶,系统按照固定速度,往桶里加入Token,若是桶已经满了就再也不添加。当有请求到来时,会各自拿走一个Token,取到Token 才能继续进行请求处理,没有Token 就拒绝服务。网络

这里若是一段时间没有请求时,桶内就会积累一些Token,下次一旦有突发流量,只要Token 足够,也能一次处理。因此令牌桶算法的特色是容许突发流量。ide

咱们看一个例子,看看令牌桶如何容许突发流量,假如令牌则按照每秒5 个的速度放入令牌桶,桶中最多存放20 个令牌,那系统能够支持两种类型的请求流量,一种是容许持续的每秒处理5 个请求,第二种是每隔4 秒,等桶中20 个令牌攒满后,就能够处理一次有20 个请求的突发状况。

1530806142d5a4f4e9

算法伪代码以下:

C   // 水桶总容量
r   // 添加令牌速度
at = // 上一个请求时间
w   // 当前令牌数

when (b):
    bt = now()
    wb = (bt - at) * r    // 两次请求期间新增的Token
    w = min(w + wb, C)    // 上一个请求剩余的Token 数加上新增的剩余数不能超过木桶的总容量

    if (w > 1.0):
        w --              // 令牌足够,能够处理请求而且将令牌数减一
        return true
    else:
        return false
复制代码

4. 两种算法比较

最后咱们对比下漏桶算法和令牌桶算法。其实在实现上,两种算法是效果同样但方向相反的算法。

1530806141436c428

漏桶算法是请求流入的速度不肯定,有时快有时慢,是存在突发状况的;可是请求流出的速度是固定的,它是流入会有突发状况,可是流出速度固定。

令牌桶算法就是固定的Token 流入速度,一个Token 表明一个请求能够被处理的机会;当系统有一段空闲时间以后,桶内有足够的token,这样能够处理突发的请求流量,它是流入速度固定,可是流出不固定。

总结下特色:漏桶算法由于流出速度固定,能够用来整流,不管你流入速率多大,我都按照固定的速度去处理。令牌桶算法的特色则是,支持突发状况,两种算法在实际使用时,应该根据具体场景灵活选用。

限流算法就介绍到这,我是好刚,好刚用在刀刃上。若是讲解对你有帮助,那就请你帮忙转发吧。

5. 令牌通算法实现

PHP 实现

//速度 桶大小 / 时间段
$rate = $maxRequests / $period;

$t_key = $keyTime($id); //最后一次获取令牌时间
$a_key = $keyAllow($id); //已有令牌数

//判断是否有最后一次获取令牌记录
if ($cache->exists($t_key)) {
    $c_time = time();
    //计算上一次获取令牌到如今过去的时间
    $time_passed = $c_time - $cache->get($t_key);
    $cache->set($t_key, $c_time, $ttl);

    //获取桶中令牌数
    $allow = $cache->get($a_key);
    $allow += $time_passed * $rate; //加上最后一次消费令牌到如今期间增加的令牌数

    //令牌数不能超过最大数
    if ($allow > $maxRequests) {
        $allow = $maxRequests;
    }

    //使用的令牌数不能超过最大限制
    if ($allow < $use) {
        $cache->set($a_key, $allow, $ttl);
        return 0;
    } else {
        //消费令牌
        $cache->set($a_key, $allow - $use, $ttl);
        return (int) ceil($allow);
    }
} else {
    //记录当前时间为最后一次处理时间,用于下次使用
    $cache->set($t_key, time(), $ttl);
    //没有令牌时按照最大令牌数处理
    $cache->set($a_key, $maxRequests - $use, $ttl);
    return $maxRequests;
}
复制代码

参考资料

相关文章
相关标签/搜索