[Redis],Lua分步式限流方案,限流分幾步?

Redis+Lua分步式限流方案

1. 背景

對於微服務這種分步式架構體系,雖然天生就具有高併發、高可用等特性,但現實條件下仍然會受各種條件制約而存在訪問瓶頸,比如經費、硬件、軟件等資源的限制,因此為了保證我們服務不被大流量(正常業務增長、突發流量等)所沖垮,我們不光要在各層添加集群的支持,同時還要為系統制定有效的限流策略來保護我們的系統。

另外,限流不光侷限於對大流量的訪問控制,還滲透在我們許多業務場景中,比如根據不同用戶制定不同的訪問策略(如:用戶下載,不同身份的用戶擁有不同的下載次數),可以說只要涉及到訪問控制,大部分會伴隨著限流。

2. 常用的限流算法

目前業界比較流行的限流算法為令牌桶算法與漏桶算法。

2.1 漏桶算法

漏桶(Leaky Bucket)算法思路很簡單,水(請求)先進入到漏桶裡,漏桶以一定的速度出水(接口有響應速率),當水流入速度過大會直接溢出(訪問頻率超過接口響應速率),然後就拒絕請求,可以看出漏桶算法能強行限制數據的傳輸速率.示意圖如下:

[Redis],Lua分步式限流方案,限流分幾步?

可見這裡有兩個變量,一個是桶的大小,支持流量突發增多時可以存多少的水(burst),另一個是水桶漏洞的大小(rate)。

因為漏桶的漏出速率是固定的參數,所以,即使網絡中不存在資源衝突(沒有發生擁塞),漏桶算法也不能使流突發(burst)到端口速率.因此,漏桶算法對於存在突發特性的流量來說缺乏效率.

2.2令牌桶算法

令牌桶算法(Token Bucket)和 Leaky Bucket 效果一樣但方向相反的算法,更加容易理解.隨著時間流逝,系統會按恆定1/QPS時間間隔(如果QPS=100,則間隔是10ms)往桶裡加入Token(想象和漏洞漏水相反,有個水龍頭在不斷的加水),如果桶已經滿了就不再加了.新請求來臨時,會各自拿走一個Token,如果沒有Token可拿了就阻塞或者拒絕服務。

[Redis],Lua分步式限流方案,限流分幾步?

令牌桶的另外一個好處是可以方便的改變速度. 一旦需要提高速率,則按需提高放入桶中的令牌的速率. 一般會定時(比如100毫秒)往桶中增加一定數量的令牌, 有些變種算法則實時的計算應該增加的令牌的數量.

3. 算法實現

3.1實現思路

因為要在分步式下進行限流,我們的各個服務都會以集群方式部署,所以我們同一服務間的不同節點必須是無狀態的。因此我們不能將我們限流信息保存在服務的內存當中。一般我們會選用獨立於服務之外的存儲媒介,比如數據庫、緩存服務(redis、memcachet等),對於傳統的數據庫明顯不合適,因為涉及大量的IO操作,且數據庫往往會成為服務的性能瓶頸。因此我們一般採用緩存系統,因為是純內存操作,性能比較好,且不容易出現瓶頸(只要內存能扛著即可)。這裡我們採用redis作為我們的存儲媒介。

上段解決了訪問信息存儲的問題,可以保證限流服務集群下各服務節點能進行統一的訪問,但存在明顯的弊端,因為不管是令牌桶算法還是漏桶算法,都需要通過代碼訪問限流信息,然後在代碼中進行判斷是否超限,然後再來操作緩存中的信息。問題是不能保存原子性,那就會存在併發問題(比如:多條流量同時到達,都從緩存取到的令牌為1,都認為自己可以訪問,然後同時改令牌為1-1=0,但明顯讓限流失效了)。因此我們想方設法來保證操作的原子性,下邊是常常會想到的方案:

[Redis],Lua分步式限流方案,限流分幾步?

3.2 算法實現

3.2.1 令牌桶

基於spring boot+redis+lua(關於lua腳本,大家可自行學習)

3.2.1.1 準備lua腳本

①初始化令牌桶緩存腳本(即當請求第一次進來時,需要將令牌信息存儲到緩存中)

[Redis],Lua分步式限流方案,限流分幾步?

②令牌桶限流腳本

[Redis],Lua分步式限流方案,限流分幾步?

3.2.1.2 程序加載lua腳本(本例中腳本放在resources/lua下)

[Redis],Lua分步式限流方案,限流分幾步?

3.2.1.3 程序限流(為了節省篇幅部分屬於偽代碼)

[Redis],Lua分步式限流方案,限流分幾步?

3.2.2 漏桶算法

漏桶算法相對邏輯比較簡單,當每次訪問時對訪問次數加1,如果超限則直接攔截即可。當過了時間週期,重新以新的時間為開始,將桶清空,繼續接受請求。可以採用redis過期時間策略+incr操作實現。

3.2.2.1 準備lua腳本

leakBucketRateLimit.lua

[Redis],Lua分步式限流方案,限流分幾步?

3.2.2.2 程序加載lua

參考3.2.1.2章節,此處不作贅述。

3.2.2.3 程序限流

參考3.2.1.3章節,此處不作贅述。

3.3 算法適用場景

[Redis],Lua分步式限流方案,限流分幾步?

4.總結

到此為止,已經給大家介紹了限流的必要性以及常用限流手段與程序實現。相信大家對分步式限流有了一個初步的瞭解,此文算是一篇入門文章,如果大家比較感興趣,下去可以找文章深入研究。

(Tx)


分享到:


相關文章: