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;
}
複製代碼

參考資料

相關文章
相關標籤/搜索