大型網站限流算法的實現和改造

最近寫了一個限流的插件,因此避免不了的接觸到了一些限流算法。本篇文章就來分析一下這幾種常見的限流算法nginx

分析以前

  1. 依我我的的理解來講限流的話應該靈活到能夠針對每個接口來作。好比說一個類裏面有5個接口,那麼個人限流插件就應該能針對每個接口就行不一樣的限流方案。因此呢,既然針對的每一個接口因此就須要一個能夠惟一標示這個接口的key(我取的是類名+方法名+入參)。
  2. 分佈式限流強烈推薦使用redis+lua或者nginx+lua來實現。
  3. 這裏用2個限流條件來作示例講一下常見的限流算法:
    1. 接口1它10秒鐘最大容許訪問100次
    2. 接口2它10秒鐘最大容許每一個人訪問100次。

計數器算法

這個算法能夠說是限流算法中最簡單的一種算法了。git

核心思想github

計數器算法的意思呢就是當接口在一個時間單位中被訪問時,我就記下來訪問次數,直到它訪問的次數到達上限。redis

涉及變量算法

  1. 接口(key)
  2. 時間單位(expire)
  3. 容許訪問多少次(limit)
  4. 訪問次數(value)

條件一框架

當一個請求過來時,咱們就會獲得這個key。分佈式

1
2
3
4
5
6
7
8
9
if(存在key){
   value++;
   if(value>=limit){
   		不能訪問
   	}
   }else{
   	添加key,value爲1
       設置key過時時間爲expire
   }

條件二lua

既然條件一已經實現了,那條件二會複雜麼 ?spa

相比於條件一來講就是同一個key對應了多個用戶。那麼咱們只須要把key加上用戶的信息就能夠了。好比說 key_用戶一、key_用戶2。插件

漏桶算法

核心思想

漏桶算法的意思呢就是一個接口在一個時間單位中容許被訪問次數是動態變化的(假如一分鐘容許訪問60次,那麼從開始計時時無論有沒有被訪問第59秒只容許訪問59次,30秒只容許30次)。爲何這樣呢,由於有另一個線程在進行遞減操做

涉及變量

  1. 接口(key)
  2. 時間單位(expire)
  3. 容許訪問多少次(limit)
  4. 遞減間隔時間(interval)
  5. 遞減步長(step)
  6. 剩餘可訪問次數(value)
  7. key的訪問時間(lastUpdateTime)
  8. 當前時間(nowTime)(注意nowTime的取值應爲應用取得的時間而不是redis或者nginx取得的時間)

條件一

線程一:

1
2
3
4
5
6
7
8
if(存在key){
   value--;
   if(value<=0){
   		不能訪問
   	}
   }else{
   	添加key,設置value爲limit
   }

線程二:

1
2
3
while(過去interval時間){
   全部key的value-step
   }

條件二

參考計數器算法條件二實現。

算法升級

能夠看到實現漏桶算法的話須要每隔interval時間都要另一條線程去遍歷所key的value去作遞減操做,那麼有沒有什麼辦法能夠省略這一步呢。答案是確定有。

1
2
3
4
5
6
7
8
9
10
11
12
13
if(存在key){
   value--;
   if((nowTime-lastUpdateTime)>interval){
   	value=value-(nowTime-lastUpdateTime)/interval*step;
       lastUpdateTime=nowTime;
   }
   if(value<=0){
   		不能訪問
   	}
   }else{
   	添加key,設置value爲limit;
       lastUpdateTime=nowTime;
   }

令牌桶算法

核心思想

令牌桶算法呢,偏偏是和漏桶算法相反的一個算法,不過仍是推薦你使用這個。這個算法的原理我不講,我以爲聰明的你看了僞代碼就明白了。

涉及變量

  1. 接口(key)
  2. 時間單位(expire)
  3. 容許訪問多少次(limit)
  4. 遞增間隔時間(interval)
  5. 遞增步長(step)
  6. 當前可訪問次數(value)
  7. key的訪問時間(lastUpdateTime)
  8. 當前時間(nowTime)(參照漏桶算法須要注意的點)

條件一

線程一:

1
2
3
4
5
6
7
8
if(存在key){
   value++;
   if(value>=limit){
   		不能訪問
   	}
   }else{
   	添加key,設置value爲limit
   }

線程二:

1
2
3
while(過去interval時間){
   全部key的value+step
   }

條件二

參考計算器算法條件二實現。

算法升級

參考漏桶算法升級實現。

代碼

代碼實現請參考個人限流框架https://github.com/2388386839/syj-ratelimit

本文出自http://zhixiang.org.cn,轉載請保留。

相關文章
相關標籤/搜索