最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis實(shí)現(xiàn)限流功能的幾種方法總結(jié)

 更新時(shí)間:2026年05月22日 08:43:30   作者:洛水水  
在實(shí)際業(yè)務(wù)場(chǎng)景中,限流是保護(hù)系統(tǒng)的重要手段:在一段時(shí)間(period)內(nèi),限定某個(gè)行為(action)的最大次數(shù)(max_count),本文介紹如何基于 Redis 實(shí)現(xiàn)多種限流方案,需要的朋友可以參考下

一、問題背景

在實(shí)際業(yè)務(wù)場(chǎng)景中,限流是保護(hù)系統(tǒng)的重要手段:在一段時(shí)間(period)內(nèi),限定某個(gè)行為(action)的最大次數(shù)(max_count)。本文介紹如何基于 Redis 實(shí)現(xiàn)多種限流方案。

二、限流類型總覽

限流類型核心思想優(yōu)點(diǎn)缺點(diǎn)
固定窗口限流時(shí)間窗口固定,到期自動(dòng)清零實(shí)現(xiàn)簡(jiǎn)單存在窗口邊界突擊流量問題
滑動(dòng)窗口限流窗口隨時(shí)間滑動(dòng),統(tǒng)計(jì)窗口內(nèi)請(qǐng)求數(shù)精確解決邊界問題實(shí)現(xiàn)稍復(fù)雜
漏斗限流容量固定,速率固定精確控制容量和速率需要 Redis 模塊支持
令牌桶限流令牌以固定速率放入桶中支持突發(fā)流量實(shí)現(xiàn)復(fù)雜

三、固定窗口限流

3.1 什么是固定窗口限流

將時(shí)間劃分為固定的窗口,例如每 5 分鐘為一個(gè)窗口:

|---5min---|---5min---|---5min---|---5min---|
20:00      20:05      20:10      20:15

在每個(gè)窗口內(nèi)獨(dú)立計(jì)數(shù),窗口到期后計(jì)數(shù)清零。

3.2 Redis 實(shí)現(xiàn)

-- 固定窗口限流實(shí)現(xiàn)
local key = "***" .. user_id .. ":" .. action
local limit = 10  -- 最大次數(shù)
local period = 10  -- 時(shí)間窗口(秒)

-- 方式1:INCR + EXPIRE(存在問題)
redis.call('INCR', key)
redis.call('EXPIRE', key, period)

-- 方式2:SET + INCR(正確實(shí)現(xiàn),解決競(jìng)態(tài)條件)
-- 使用 SET + EXPIRE 原子操作,避免窗口切換時(shí)丟失數(shù)據(jù)
redis.call('SET', key, 0, 'EX', period, 'NX')
local count = redis.call('INCR', key)

return count <= limit

關(guān)鍵點(diǎn):使用 SET + EXPIRE 代替單獨(dú) EXPIRE,避免 INCR 和 EXPIRE 之間進(jìn)程崩潰導(dǎo)致數(shù)據(jù)丟失。

可通過 Pipeline 保證兩個(gè)命令同時(shí)發(fā)送:

# Python 示例
pipe = redis.pipeline()
pipe.set(key, 0, ex=period, nx=True)
pipe.incr(key)
res = pipe.execute()
return res[1] <= limit

3.3 固定窗口的局限性

假設(shè) 5 分鐘內(nèi)限定 10 次請(qǐng)求:

20:04-20:05 發(fā)生 9 次請(qǐng)求
20:05-20:06 發(fā)生 9 次請(qǐng)求

在 20:04-20:06 這 2 分鐘內(nèi),實(shí)際發(fā)生了 18 次請(qǐng)求,遠(yuǎn)超每 5 分鐘 10 次的限制。

問題根源:固定窗口的邊界不連續(xù),在邊界處可能發(fā)生突發(fā)流量。

四、滑動(dòng)窗口限流

4.1 核心思想

滑動(dòng)窗口的核心是窗口隨時(shí)間連續(xù)滑動(dòng),而非固定邊界:

傳統(tǒng)固定窗口:      |-----5min-----|-----5min-----|
                   20:00         20:05         20:10

滑動(dòng)窗口:
                   現(xiàn)在時(shí)刻的窗口持續(xù)向前滑動(dòng)
                   |----5min-----|----5min-----|
                   20:01         20:06

4.2 Redis 實(shí)現(xiàn)(ZSET)

local function is_action_allowed(red, user_id, action, period, max_count)
    local key = "***" .. user_id .. ":" .. action
    local now = redis.call('TIME')  -- 獲取當(dāng)前時(shí)間戳(毫秒)

    -- 1. 記錄當(dāng)前行為(score 和 member 都用時(shí)間戳)
    red:zadd(key, now, now)

    -- 2. 移除窗口之前的行為記錄
    red:zremrangebyscore(key, 0, now - period * 1000)

    -- 3. 獲取窗口內(nèi)的行為數(shù)量
    local count = red:zcard(key)

    -- 4. 設(shè)置過期時(shí)間,避免冷用戶持續(xù)占用內(nèi)存
    red:expire(key, period + 1)

    return count <= max_count
end

流程圖:

時(shí)間軸:[--窗口period--|---未來---]
                       ↑now
                       
ZSET 存儲(chǔ):score=時(shí)間戳, member=時(shí)間戳
ZREMRANGEBYSCORE:刪除 score < now-period 的舊記錄
ZCARD:統(tǒng)計(jì)剩余元素?cái)?shù)量,即窗口內(nèi)請(qǐng)求數(shù)

4.3 為什么用 ZSET 而非 LIST

數(shù)據(jù)結(jié)構(gòu)適用場(chǎng)景
ZSET支持按時(shí)間范圍刪除,適合滑動(dòng)窗口
LIST只能按索引刪除,無(wú)法按時(shí)間范圍清理

五、漏斗限流(Redis-Cell)

5.1 什么是漏斗限流

漏斗限流的核心是容量固定 + 速率固定,能精確控制元素的容量和速率:

漏斗模型:
       [入口] -> (容量固定) -> [出口]
         ↓
      速率恒定
  • 漏斗容量:最多能容納多少請(qǐng)求
  • 漏斗速率:?jiǎn)挝粫r(shí)間內(nèi)能處理多少請(qǐng)求

5.2 Redis-Cell 模塊安裝

Redis-Cell 是 Redis 的第三方模塊,采用 Rust 編寫,需要單獨(dú)安裝:

# 下載并編譯
git clone https://github.com/brandur/redis-cell
cd redis-cell
cargo build --release
cp target/release/libredis_cell.so /path/to/modules/
# 啟動(dòng) Redis 加載模塊
redis-server --loadmodule /path/to/modules/libredis_cell.so

5.3 CL.THROTTLE 命令詳解

CL.THROTTLE key capacity operations seconds [quota]

參數(shù)說明:

參數(shù)含義示例
key漏斗容器名稱user:123:login
capacity漏斗容量(最大容納請(qǐng)求數(shù))10
operations單位時(shí)間內(nèi)的操作次數(shù)5
seconds單位時(shí)間(秒)60
quota單次行為消耗的令牌數(shù)(可選,默認(rèn)1)1

示例:每 60 秒最多 5 次請(qǐng)求,漏斗容量 10

CL.THROTTLE user:123:login 10 5 60

返回結(jié)果:

1) (integer) 0  # 是否被限流(0=允許,1=拒絕)
2) (integer) 7  # 漏斗剩余容量
3) (integer) 7  # 如果被拒絕,還需要等多久(秒)
4) (integer) -1  # 預(yù)留字段
5) (integer) 60  # 下次請(qǐng)求的間隔時(shí)間

5.4 流速計(jì)算

流速 = operations / seconds = 5 / 60 ≈ 0.083 請(qǐng)求/秒

這意味著每秒只能處理約 0.083 個(gè)請(qǐng)求,即約 12 秒處理 1 個(gè)請(qǐng)求。

六、令牌桶限流

6.1 核心思想

令牌桶的核心是令牌以固定速率放入桶中

令牌桶:
         -> [桶容量] -> 請(qǐng)求消耗令牌 -> 通過
         ↑
      固定速率放入令牌
  • 桶容量:最大令牌數(shù)
  • 令牌添加速率:每秒添加多少令牌
  • 請(qǐng)求消耗:每個(gè)請(qǐng)求消耗 1 個(gè)令牌

6.2 特點(diǎn)

特點(diǎn)說明
支持突發(fā)流量桶滿時(shí)可一次性處理多個(gè)請(qǐng)求
令牌非即時(shí)補(bǔ)充需要等待令牌生成

6.3 與漏斗限流的區(qū)別

對(duì)比維度漏斗限流令牌桶限流
速率勻速勻速(令牌補(bǔ)充)
突發(fā)能力不支持支持(桶滿時(shí))
實(shí)現(xiàn)難度較簡(jiǎn)單較復(fù)雜

七、四種限流方案對(duì)比

維度固定窗口滑動(dòng)窗口漏斗限流令牌桶
實(shí)現(xiàn)復(fù)雜度
邊界突擊無(wú)無(wú)無(wú)
突發(fā)流量支持不支持不支持不支持支持
精度控制
額外依賴無(wú)無(wú)Redis-Cell無(wú)

八、面試追問 FAQ

問題回答要點(diǎn)
Q: 為什么固定窗口需要 SET + INCR 組合?單獨(dú) INCR + EXPIRE 在進(jìn)程崩潰時(shí)可能丟失數(shù)據(jù),SET+EXPIRE 原子操作保證一致性
Q: 滑動(dòng)窗口為什么要設(shè)置過期時(shí)間為 period+1?避免窗口邊界附近過期導(dǎo)致數(shù)據(jù)丟失,確??绱翱诘恼?qǐng)求仍被統(tǒng)計(jì)
Q: 漏斗限流和令牌桶限流各適用于什么場(chǎng)景?漏斗:需要精確控制速率的 API 限流;令牌桶:允許突發(fā)流量的場(chǎng)景(如秒殺)
Q: Redis-Cell 是原子操作嗎?是,CL.THROTTLE 整個(gè)命令是原子的,無(wú)需擔(dān)心并發(fā)問題
Q: 滑動(dòng)窗口的 ZSET 會(huì)不會(huì)無(wú)限增長(zhǎng)?不會(huì),每次請(qǐng)求都會(huì)清理窗口外的舊數(shù)據(jù),且有 expire 保證清理

總結(jié)

限流方案實(shí)現(xiàn)難度精度突發(fā)流量推薦場(chǎng)景
固定窗口不支持簡(jiǎn)單場(chǎng)景
滑動(dòng)窗口不支持需要精確控制
漏斗限流不支持API 限流
令牌桶支持秒殺/搶購(gòu)

核心結(jié)論: 根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的限流方案,簡(jiǎn)單場(chǎng)景用固定窗口,精確控制用滑動(dòng)窗口或漏斗限流,需要突發(fā)能力用令牌桶。

以上就是Redis實(shí)現(xiàn)限流功能的幾種方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Redis實(shí)現(xiàn)限流功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何向redis中寫入大量的數(shù)據(jù)

    如何向redis中寫入大量的數(shù)據(jù)

    文章介紹了通過Python腳本生成Redis命令并輸出至文件,再用Shell腳本批量執(zhí)行的流程,強(qiáng)調(diào)Pipeline技術(shù)可提升批量寫入效率,并說明如何驗(yàn)證數(shù)據(jù)插入成功
    2025-08-08
  • 淺談Redis緩存雪崩解決方案

    淺談Redis緩存雪崩解決方案

    本文主要介紹了Redis緩存雪崩解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 配置Redis序列化方式不生效問題及解決

    配置Redis序列化方式不生效問題及解決

    這篇文章主要介紹了配置Redis序列化方式不生效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Redis增減庫(kù)存避坑的實(shí)現(xiàn)

    Redis增減庫(kù)存避坑的實(shí)現(xiàn)

    在電商平臺(tái)或者倉(cāng)庫(kù)管理系統(tǒng)中,庫(kù)存的管理是非常重要的一項(xiàng)任務(wù),本文主要介紹了Redis增減庫(kù)存避坑的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 為啥Redis使用pipelining會(huì)更快

    為啥Redis使用pipelining會(huì)更快

    這篇文章主要介紹了為啥Redis使用pipelining會(huì)更快,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 巧用Redis實(shí)現(xiàn)分布式鎖詳細(xì)介紹

    巧用Redis實(shí)現(xiàn)分布式鎖詳細(xì)介紹

    大家好,本篇文章主要講的是巧用Redis實(shí)現(xiàn)分布式鎖詳細(xì)介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 解決Redis運(yùn)行時(shí)突然不能讀取數(shù)據(jù)了的問題處理

    解決Redis運(yùn)行時(shí)突然不能讀取數(shù)據(jù)了的問題處理

    Redis因configured錯(cuò)誤配置導(dǎo)致無(wú)法持久化數(shù)據(jù),因此在寫數(shù)據(jù)時(shí)被禁止,將stopPersist-ononError設(shè)置為no允許寫入但不停持久化,實(shí)際問題在于rdb文件保存路徑權(quán)限不足,檢查并rdb.file文件所在目錄權(quán)限并確保redis能具有寫寫入該權(quán),此問題通過修改目錄權(quán)限解決
    2026-05-05
  • Spring?redis使用報(bào)錯(cuò)Read?timed?out排查及解決過程

    Spring?redis使用報(bào)錯(cuò)Read?timed?out排查及解決過程

    項(xiàng)目使用spring集成redis,偶爾會(huì)出現(xiàn)read timed out的情況,剛開始以為是網(wǎng)絡(luò)不穩(wěn)定引起的,后面發(fā)現(xiàn)影響業(yè)務(wù)測(cè)試的準(zhǔn)確性,這篇文章主要給大家介紹了關(guān)于Spring redis使用報(bào)錯(cuò)Read timed out排查及解決過程的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • Redis反序列化失敗的解決方法

    Redis反序列化失敗的解決方法

    在使用Redis緩存數(shù)據(jù)的過程中,有時(shí)會(huì)遇到反序列化失敗的問題,本文主要介紹了Redis反序列化失敗的解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 詳解Redis 緩存刪除機(jī)制(源碼解析)

    詳解Redis 緩存刪除機(jī)制(源碼解析)

    這篇文章主要介紹了Redis 緩存刪除機(jī)制(源碼解析),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評(píng)論

江油市| 荔波县| 甘谷县| 双鸭山市| 胶州市| 漳浦县| 凤阳县| 巴林左旗| 和顺县| 乳源| 长武县| 察雅县| 汝阳县| 平谷区| 西宁市| 海丰县| 通州区| 寿宁县| 乐都县| 双城市| 天台县| 洛川县| 修武县| 从江县| 壶关县| 南昌市| 丰城市| 象州县| 高州市| 凤山市| 永嘉县| 筠连县| 太保市| 抚远县| 博罗县| 沙坪坝区| 名山县| 璧山县| 凭祥市| 公安县| 武隆县|