使用redis實現(xiàn)令牌桶算法和漏桶算法方式
流量控制算法,用于限制請求的速率。
可以應(yīng)對緩存雪崩
令牌桶算法
核心思想是:
- 有一個固定容量的桶,里面存放著令牌(token)。
- 每過一定時間(如 1 秒),桶中會自動增加一定數(shù)量的令牌,直到達(dá)到桶的容量上限。
- 當(dāng)有請求到來時,會從桶中取出一個令牌。如果桶中有令牌,則請求被允許通過;如果桶中沒有令牌,則拒絕該請求。
基于Redis的實現(xiàn)
- 初始化
使用 Redis 的 Sorted Set(有序集合)來存儲令牌。
初始化時,向有序集合中添加一定數(shù)量的令牌,每個令牌的時間戳作為分?jǐn)?shù)(score)。
ZADD user:rate_limit 1633072800 1633072800
或者,可以預(yù)先為每個用戶生成大量令牌,時間戳作為分?jǐn)?shù),均勻分布在一定時間段內(nèi)。
- 令牌生成
定期向桶中添加令牌??梢允褂?Redis 的 ZADD 命令來添加新的令牌,每個令牌的時間戳作為分?jǐn)?shù)。
ZADD user:rate_limit NX 1633072801 1633072801
這里的 NX 表示如果鍵不存在,則不執(zhí)行操作(可選)。
- 檢查和消耗令牌
當(dāng)請求到來時,檢查桶中是否有可用的令牌??梢允褂?ZCOUNT 命令統(tǒng)計當(dāng)前時間戳之前的有效令牌數(shù)量。
ZCOUNT user:rate_limit -inf +inf
如果有可用令牌,則使用 ZPOPMIN 命令取出一個令牌,并允許請求通過。
ZPOPMIN user:rate_limit
如果沒有可用令牌,則拒絕請求。
- 清理過期令牌
定期清理過期的令牌,避免數(shù)據(jù)堆積。例如,可以使用 ZREMRANGEBYSCORE 命令刪除時間戳小于當(dāng)前時間的令牌。
ZREMRANGEBYSCORE user:rate_limit -inf $(current_time)
漏桶算法
漏桶算法類似于一個漏斗,它的核心思想是:
- 有一個固定容量的漏桶,里面存儲著請求。
- 漏桶以恒定的速率將請求漏出(處理)。
- 當(dāng)請求到達(dá)時,如果漏桶未滿,則將請求放入漏桶;如果漏桶已滿,則拒絕該請求。
基于 Redis 的實現(xiàn)
- 初始化
使用 Redis 的 String 類型鍵來存儲漏桶的狀態(tài)。例如,鍵 user:leaky_bucket 可以存儲最后一個請求的時間戳。
SET user:leaky_bucket 1633072800
- 請求處理
當(dāng)請求到來時,首先檢查漏桶是否已滿。這可以通過比較當(dāng)前時間與最后一個請求的時間戳來實現(xiàn)。
如果當(dāng)前時間與最后一個請求的時間差小于漏桶的處理時間間隔(例如 1 秒),則認(rèn)為漏桶已滿,拒絕請求。
否則,更新漏桶的時間戳,并允許請求通過。
SET user:leaky_bucket $(current_time)
- 處理速率
通過設(shè)置漏桶的處理速率(例如每秒處理一個請求)來控制流量??梢酝ㄟ^ Redis 的 SET 命令中的參數(shù) NX 和 XX 來實現(xiàn)線程安全。
總結(jié)
令牌桶算法允許突發(fā)流量,適合作為速率限制器。
漏桶算法適用于平滑流量的情況,適用于需要恒定處理速率的場景。
在 Redis 中,可以通過組合使用有序集合、字符串等數(shù)據(jù)結(jié)構(gòu)以及原子操作(如 ZADD、ZPOPMIN 和 SET)來高效地實現(xiàn)這兩類限流算法。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis事務(wù)機(jī)制與Springboot項目中的使用方式
Redis事務(wù)機(jī)制允許將多個命令打包在一起,作為一個原子操作來執(zhí)行,開啟事務(wù)使用MULTI命令,執(zhí)行事務(wù)使用EXEC命令,取消事務(wù)使用DISCARD命令,監(jiān)視一個或多個鍵使用WATCH命令,Redis事務(wù)的核心思想是將多個命令放入一個隊列中2025-03-03小白也能看懂的Redis遍歷鍵和數(shù)據(jù)庫管理詳解
這篇文章主要為大家介紹了小白也能看懂的Redis遍歷鍵和數(shù)據(jù)庫管理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10