高并發場景下限流算法實踐與性能優化指南

限流指南封面

高并發場景下限流算法實踐與性能優化指南

在大規模并發訪問環境中,合理的限流策略能保護后端服務穩定運行,避免系統因瞬時高并發導致資源耗盡或崩潰。本文將從原理出發,深入解析幾種主流限流算法,并結合Java和Redis給出完整可運行的代碼示例,最后分享在生產環境中的性能優化建議。


一、技術背景與應用場景

隨著業務流量激增,API網關、微服務接口等處于高并發流量的第一線。常見場景包括:

  • 短期秒級爆發流量,如秒殺、搶購場景
  • 持續大規模監控上報、日志埋點
  • 第三方系統突發調用

此時若無限流保護,系統可能出現線程池耗盡、數據庫連接池耗盡、Redis阻塞等問題,導致服務異常甚至宕機。

二、核心原理深入分析

1. 固定窗口計數(Fixed Window)

思路:將時間切分為大小相同的固定窗口(如1秒),記錄窗口內的請求計數,超過閾值拒絕。

優點:實現簡單,計數開銷低。

缺點:臨界點易出現短時間內雙倍閾值的突發量。

2. 滑動窗口計數(Sliding Window Counter)

思路:利用兩個固定窗口,以及當前窗口的權重,平滑地計算限流。

實現:

  • 記錄上一個窗口的計數 count_prev 和當前窗口的計數 count_cur
  • 按時間比例計算:total = count_prev * (1 - t/T) + count_cur

3. 滑動窗口日志(Sliding Window Log)

思路:記錄每次請求的時間戳,通過檢查日志中有效時間段的請求數判斷是否超過閾值。

優點:精確;缺點:存儲和遍歷開銷大,不適合超高頻場景。

4. 令牌桶(Token Bucket)

思路:以固定速率往桶中添加令牌,請求到來先嘗試取令牌,若有則放行,否則拒絕或等待。

優點:支持突發流量,可平滑輸出。

5. 漏桶(Leaky Bucket)

思路:將請求排入“漏桶”隊列,以固定速率處理隊列中的請求;隊列滿則拒絕新請求。

與令牌桶的區別在于:漏桶保證輸出速率固定,而令牌桶更靈活。


三、關鍵源碼解讀與示例

1. Guava RateLimiter(令牌桶實現)

import com.google.common.util.concurrent.RateLimiter;public class GuavaLimiterDemo {// 創建每秒產生 100 個令牌的令牌桶private static final RateLimiter limiter = RateLimiter.create(100);public boolean tryAcquire() {// 非阻塞立即獲取令牌,返回是否獲取成功return limiter.tryAcquire();}public static void main(String[] args) {GuavaLimiterDemo demo = new GuavaLimiterDemo();if (demo.tryAcquire()) {// 業務處理System.out.println("請求通過");} else {System.out.println("限流處理");}}
}

2. Redis 滑動窗口計數(Lua 原子操作)

文件:scripts/sliding_window.lua

-- KEYS[1] 主鍵,ARGV[1]=當前時間戳毫秒,ARGV[2]=窗口大小(毫秒),ARGV[3]=閾值
local key = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])-- 移除過期記錄
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
-- 統計當前窗口請求數
local count = redis.call('ZCARD', key)
if count < limit then-- 記錄本次請求redis.call('ZADD', key, now, now)-- 設置過期防止持久化redis.call('PEXPIRE', key, window)return 1
end
return 0

Java 調用示例:

public class RedisSlidingWindowLimiter {private final JedisPool jedisPool;private final String scriptSha1;public RedisSlidingWindowLimiter(JedisPool pool) {this.jedisPool = pool;try (Jedis jedis = jedisPool.getResource()) {scriptSha1 = jedis.scriptLoad(new String(Files.readAllBytes(Paths.get("scripts/sliding_window.lua"))));}}public boolean tryAcquire(String key, long windowMs, long limit) {try (Jedis jedis = jedisPool.getResource()) {Object res = jedis.evalsha(scriptSha1,Collections.singletonList(key),Arrays.asList(String.valueOf(System.currentTimeMillis()), String.valueOf(windowMs), String.valueOf(limit)));return Integer.valueOf(1).equals(res);}}
}

3. Spring Cloud Gateway 全局限流過濾器

@Configuration
public class GatewayRateLimiterConfig {@Beanpublic GlobalFilter rateLimiterFilter(RedisSlidingWindowLimiter limiter) {return (exchange, chain) -> {String requestKey = "gateway:" + exchange.getRequest().getPath();boolean pass = limiter.tryAcquire(requestKey, 1000, 200); // 1秒200次if (!pass) {exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);return exchange.getResponse().setComplete();}return chain.filter(exchange);};}
}

項目結構示例:

src/
├─ main/
│  ├─ java/
│  │  └─ com.example.limiter/
│  │     ├─ GuavaLimiterDemo.java
│  │     ├─ RedisSlidingWindowLimiter.java
│  │     └─ GatewayRateLimiterConfig.java
│  └─ resources/
│     └─ scripts/
│        └─ sliding_window.lua

四、實際應用示例

在電商秒殺場景,采用 Redis 滑動窗口限流:

  1. 用戶請求進入API網關,先通過限流過濾器;
  2. 限流通過后,執行業務邏輯下單;
  3. 請求高峰時可動態調整閾值,或采用多級限流(API 網關、微服務內部雙層)策略。

五、性能特點與優化建議

  1. 單機 vs 分布式:Guava 限流僅適用于單實例,多實例需借助 Redis 或 ZooKeeper 實現全局限流。
  2. 數據清理:滑動窗口日志方式需定期清理過期數據,否則內存/Redis 會堆積。
  3. Lua 原子性:使用 Redis + Lua 能保證高并發下的限流原子操作。
  4. 批量令牌:令牌桶算法可一次性發放一定數量令牌,減少系統調用開銷。
  5. 閾值動態調整:結合監控(Prometheus)動態調整限流策略,避免過嚴或過松。
  6. 多級限流:前端網關 + 后端服務雙層限流方案能增強系統魯棒性。

總結與最佳實踐

限流是高并發系統的核心防護手段。本文從固定窗口、滑動窗口到令牌桶、漏桶算法,結合 Java/Redis 和 Spring Cloud Gateway 給出了完整實現示例,并提出了多級限流、動態閾值、性能優化等實戰建議。希望對構建穩定、高可用的后端限流體系有所幫助。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/96625.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/96625.shtml
英文地址,請注明出處:http://en.pswp.cn/web/96625.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue3應用執行流程詳解

精確化的完整執行流程 (以 Vite Vue3 SPA 為例)整個過程可以分為兩部分&#xff1a;首次訪問的“冷啟動”和后續的Vue應用接管。第一部分&#xff1a;首次訪問與頁面加載客戶端&#xff1a;發送請求用戶打開瀏覽器&#xff0c;輸入 URL&#xff08;如 http://localhost:5173&a…

Redis 持久化與高可用實踐(RDB / AOF / Sentinel / Cluster 全解析)

這篇是我把幾套生產環境踩坑與復盤整理成的一份“從 0 到 1 長期可維護”的實踐文。目標是&#xff1a;明確策略、給出默認可用的配置模板、把常見坑一次講透。 適用場景&#xff1a;新項目選型、老項目穩定性加固、從單機遷移到 HA/Cluster、應對數據安全與故障切換要求。目錄…

Linux內核的PER_CPU機制

參考書《Linux內核模塊開發技術指南》 1.原理 在多核CPU的情況下&#xff0c;為了提高CPU并發執行的效率&#xff0c;對于某些不是必須要在核間進行同步訪問的資源&#xff0c;可以為每一個CPU創建一個副本&#xff0c;讓每個CPU都訪問自身的數據副本&#xff0c;而不是通過加鎖…

VSCode 的百度 AI編程插件

VSCode 的百度 AI編程插件主要是 Baidu Comate&#xff08;文心快碼&#xff09;&#xff0c;這是一款基于文心大模型的新一代編碼輔助工具&#xff0c;旨在提升開發者的編碼效率&#xff0c;讓寫代碼變得更簡單。以下是關于 Baidu Comate 的詳細介紹&#xff1a; 一、功能特點…

阿里云監控使用

阿里云的云監控服務&#xff08;CloudMonitor&#xff09;是一款簡單易用、功能強大的監控工具&#xff0c;主要用來幫助用戶實時監控阿里云上的各種資源&#xff08;比如服務器、數據庫、網絡等&#xff09;&#xff0c;并在出現問題時及時發出警報&#xff0c;確保業務穩定運…

嵌入式C語言-關鍵字typedef

定義和作用 typedef是C/C中的一個關鍵字&#xff0c;作用是為現有的數據類型&#xff08;int 、char 、flaot等&#xff09;創建新的別名&#xff0c;其目的是為了方便閱讀和理解代碼。 用法 typedef 原有類型名 新類型名;基本類型創建別名 typedef unsigned char uint8_t; typ…

【混合開發】【大前端++】Vue節點優化Dome之單節點輪播圖片播放視頻二

動圖更精彩 背景 Vue作為大前端開發頁面交互&#xff0c;在數字屏&#xff0c;智慧大屏等大屏幕開發過程中&#xff0c;輪播效果作為豐富的展示組件經常作為首選。但也因為這個組件的交互體驗很好&#xff0c;于是各種單點組件增加到輪播效果里。經過業務的擴展&#xff0c;人…

前端開發核心技術與工具全解析:從構建工具到實時通信

覺得主包文章可以的,可以點個小愛心喲&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 主頁:一位搞嵌入式的 genius-CSDN博客 系列文章專欄: https://blog.csdn.net/m0_73589512/category_13028539.html 前端開發核心技術與工具全解…

GPT 系列論文 gpt3-4 175B參數 + few-shot + 多模態輸入 + RLHF + system

GPT&#xff0c;GPT-2&#xff0c;GPT-3 論文精讀【論文精讀】 GPT-4論文精讀 從1750億參數的文本預言家&#xff0c;到多模態的通用天才&#xff0c;OpenAI用兩次震撼世界的發布&#xff0c;重新定義了人工智能的可能性邊界。這份筆記將帶你深入GPT-3和GPT-4的核心突破&#…

.gitignore文件的作用及用法

目錄 ??.gitignore 文件的作用?? ??.gitignore 的基本語法?? ??Python 項目的 .gitignore 示例?? ??如何使用 .gitignore?? ??1. 創建 .gitignore 文件?? ??2. 編輯 .gitignore?? ??3. 檢查 Git 狀態?? ??常見問題?? ??Q1&#xff…

QEMU環境準備

QEMU環境準備 下載 qemu # qemu sudo apt install qemu-system-arm # gdb sudo apt install gdb-multiarchsudo apt-get update sudo apt-get install build-essential zlib1g-dev pkg-config libglib2.0-dev \libpixman-1-dev libfdt-dev ninja-build下載并自行編譯 qemu(可…

003 cargo使用

cargo是什么 cargo 是 Rust 的構建系統和包管理器。Rust 開發者常用 cargo 來管理 Rust 工程和獲取工程所依賴的庫。 在上一篇文章中我們已經使用cargo new命令創建了一個名叫hello_rust的項目。也使用cargo run來運行項目。 cargo常用命令 cargo 除了創建工程以外還具備構建&a…

跨省跨國監控難題破解:多層級運維的“中國解法”

在全球化的商業浪潮中&#xff0c;集團型客戶的業務布局日益廣泛&#xff0c;涉及跨省甚至跨國的多個分支機構和業務節點。這種跨域管理的模式給企業的運維監控帶來了前所未有的挑戰。多個分支機構和業務節點運維調整首先&#xff0c;不同地區的網絡環境差異巨大。從國內不同省…

pandas讀取復合列名列頭及數據和處理

pandas讀取復合列名列頭及數據和處理1. 效果圖2. 源代碼1. 效果圖 原始excel&#xff1a; 讀取1&#xff0c;2行為復合表頭&#xff1a; 讀取序號為1003一整行的數據&#xff0c;以及獲取序號為1002行及1003行的C列復合表頭列的值&#xff1a; 2. 源代碼 import pandas …

制作一個簡單的vscode插件

當前環境情況 操作系統&#xff1a;Windows 項目類型&#xff1a;VS Code 插件&#xff08;TypeScript 編寫&#xff09; Node.js 版本&#xff1a;20.18.1 yarn 版本&#xff1a;1.22.22 npm 版本&#xff1a;10.8.2 npm registry&#xff1a;huawei ------- https://repo.hua…

分布式專題——10.2 ShardingSphere-JDBC分庫分表實戰與講解

1 分庫分表案例 下面實現一個分庫分表案例&#xff0c;將一批課程信息分別拆分到兩個庫&#xff0c;四個表中&#xff1a; 需提前準備一個 MySQL 數據庫&#xff0c;并在其中創建 Course 表。Course 表的建表語句如下&#xff1a; CREATE TABLE course (cid bigint(0) NOT N…

Digital Clock 4,一款免費的個性化桌面數字時鐘

Digital Clock 4&#xff0c;一款免費的個性化桌面數字時鐘 ** 功能 ** &#xff1a;一款免費的桌面數字時鐘工具&#xff0c;支持多種皮膚、透明度調節和字體樣式自定義&#xff0c;時鐘可自由拖動&#xff0c;支持設置鬧鐘、定時關機、顯示自定義消息等功能&#xff0c;適合想…

學習Python是一個循序漸進的過程,結合系統學習、持續實踐和項目驅動,

學習Python是一個循序漸進的過程&#xff0c;結合系統學習、持續實踐和項目驅動&#xff0c;你會掌握得更好。下面我為你梳理了一個分階段的學習路線和實用建議&#xff0c;希望能幫你高效入門并逐步提升。 &#x1f40d; Python學習指南&#xff1a;從入門到精通 &#x1f5…

vcpkg:面向C/C++的跨平臺庫管理工具軟件配置筆記經驗教程

1、什么是vcpkg 對于使用過Python進行程序設計的開發者們&#xff0c;大多都會對Python的各種庫和依賴&#xff0c;僅僅通過幾條簡單命令行就完成配置的操作感到驚嘆&#xff0c;非常的省事省力。反倒是C/C開發時&#xff0c;要是每個庫都要自己下載源碼編譯或者對環境進行配置…

【Docker】常用幫忙、鏡像、容器、其他命令合集(2)

【Docker】常用幫忙、鏡像、容器、其他命令合集&#xff08;2&#xff09;博主有話說容器命令新建容器并啟動列出所有的運行的容器退出容器docker run -it centos:7.0.1406 /bin/bash指令解析docker exec -it ... bash 、docker run -it ... bash、docker attach [容器] 的exit…