Redis 并發(fā)限流控制
令牌桶概念
令牌桶是一種用于控制請求速率的算法。它可以限制在特定時間內可以提交的請求數(shù)量,以避免超過系統(tǒng)的處理能力。令牌桶算法基于一個抽象的“令牌桶”,該桶中可以存放一定數(shù)量的令牌。在每個時間單位內,新的令牌會按一定的速率添加到桶中。如果一個請求需要處理,就需要從桶中消耗一定數(shù)量的令牌。如果桶中沒有足夠的令牌,則請求將被拒絕。令牌桶算法的優(yōu)點在于它可以根據(jù)當前的系統(tǒng)負載動態(tài)調整請求的處理速率,并可以控制請求的速率和延遲。
優(yōu)缺點
- 可能會導致請求延遲,如果請求速率較高,則桶中的令牌可能會被消耗完,導致新的請求無法被處理。
- 可以避免系統(tǒng)被大量請求涌入而導致的資源耗盡,并可以根據(jù)實際情況動態(tài)調整請求處理速率。
分析
核心參數(shù):
- 桶的容量:它表示桶中最多能存放多少令牌。
- 令牌添加速率:每個時間單位內(1s)令牌桶中能添加的令牌數(shù)量。
- 每個請求需要的令牌數(shù)量:表示每個請求需要消耗的令牌數(shù)量,一般默認為 1。
其中令牌添加速率的實現(xiàn)方式為:維護一個時間戳,來記錄上一次添加令牌的時間,以便在處理請求時計算令牌添加速率。
綜上可以進行代碼設計:
基于Redis+lua的分布式令牌桶限流
redis key 設計:
- Key[1] :記錄桶的剩余容量
- Key[2] :記錄桶上次刷新時間,以此推算當前需要填入的令牌數(shù)量
- 第一次:需要新填入的令牌數(shù)量 = (當前時間 - 0) * 速率
- 其他后:需要新填入的令牌數(shù)量 = (當前時間 - Key[2]) * 速率
綜上:當前桶內可用令牌數(shù) = 桶的剩余容量 + 需要新填入的令牌數(shù)量
參數(shù)設計:
- capacity:桶的容量:它表示桶中最多能存放多少令牌。
- rate:令牌添加速率:每個時間單位內(1s)令牌桶中能添加的令牌數(shù)量。
- requested:每個請求需要的令牌數(shù)量:表示每個請求需要消耗的令牌數(shù)量,一般默認為 1。
核心公式:
- fill_time:填充時間:capacity / rate,例如 10/2,即每秒填充 5 個令牌。
- ttl:redis key[1]、key[2] 的過期時間,填充時間*2;為什么是2倍:這樣可以保證令牌桶中的令牌能夠被充分利用,并避免過早的過期。例如,如果填充時間的值為 10 秒,那么過期時間的值就應該設置為 20 秒。這樣,在令牌桶的生存周期內,用戶就有足夠的時間來使用令牌桶中的令牌。
LUA 腳本
redis.replicate_commands() 是 Redis 客戶端的一個方法,它用于啟用命令復制(command replication)。命令復制是指,在多個 Redis 實例之間復制命令,以保證數(shù)據(jù)的一致性。
例如,如果你在一個 Redis 集群中執(zhí)行了一條寫入命令,那么這條命令就會被復制到集群中的其他實例中。這樣,就可以保證集群中的所有實例都保存了相同的數(shù)據(jù),并且可以提供高可用性和數(shù)據(jù)安全性。