分布式限流方案:基于 Redis 的令牌桶算法实现
分布式限流方案:基于 Redis 的令牌桶算法实现
- 前言
- 一、原理介绍:令牌桶算法
- 二、分布式限流的设计思路
- 三、代码实现
- 四、方案优缺点
- 五、 适用场景
- 总结
前言
在分布式场景下,接口限流变得更加复杂。传统的单机限流方式难以满足跨节点的限流需求,因此需要一种分布式限流方案。
这里介绍一种基于 Redis 和 Redisson 实现的令牌桶算法分布式限流方案。
一、原理介绍:令牌桶算法
令牌桶算法是一种用于控制流量的经典算法,其基本原理如下:
-
生成令牌:按照固定的速率向令牌桶中放入令牌。
-
消耗令牌:每个请求到来时需要消耗一个令牌才能执行。
-
桶满时丢弃令牌:如果令牌桶已满,额外生成的令牌会被丢弃。
-
拒绝无令牌请求:当令牌桶为空且有请求到达时,拒绝该请求。
示意图
+--------------------------+| 请求到达 |+--------------------------+|V+----------------------------+| 令牌桶中是否有令牌? |+----------------------------+/ \是 否/ \
+--------------------+ +----------------------+
| 消耗令牌,放行 | | 拒绝请求,限流 |
+--------------------+ +----------------------+
二、分布式限流的设计思路
在分布式环境中,多个节点需要共享限流状态。为了解决这个问题,我们采用 Redis 作为分布式存储,并通过 Redisson 的 RRateLimiter
组件实现分布式的令牌桶限流:
- Redis 统一存储令牌桶状态:
- 使用 Redis 的
RRateLimiter
对象存储令牌桶的容量和剩余令牌数。
- 多节点共享限流状态:
- 各个服务节点通过 Redis 读取和更新令牌桶状态,实现跨节点的流量控制。
- 动态配置更新:
- 支持从 Redis 中动态获取限流配置,实现限流规则的热更新。
- 基于 IP + 接口路径的粒度限流:
- 使用
api_limit:ip:apiPath
作为 Redis 的 Key,针对不同接口和 IP 进行精细化限流。
三、代码实现
-
初始化令牌桶
/*** 获取指定接口的令牌桶(每个接口独立一个)** @param apiKey 接口唯一标识* @param rate 允许的请求数* @param interval 时间窗口(秒)* @return RRateLimiter 令牌桶实例*/ public RRateLimiter getRateLimiter(String apiKey, int rate, int interval) {return rateLimiterCache.compute(apiKey, (key, existingLimiter) -> {String redisKey = String.format("%s:%s", RedisKeyConstant.DOC_RATE_LIMIT_PRE, key);RRateLimiter rateLimiter = redissonClient.getRateLimiter(redisKey);// 获取 Redis 中的当前限流配置List<Integer> config = getRateLimiterConfig(redisKey);Integer currentRate = config.get(0);Integer currentInterval = config.get(1);// 检查是否需要重新初始化if (existingLimiter != null && existingLimiter.isExists()&& Objects.equals(currentRate, rate)&& Objects.equals(currentInterval, interval)) {return existingLimiter;}log.warn("检测到限流配置变化或 RateLimiter 失效,重新初始化令牌桶 [{}]", redisKey);// 重新初始化令牌桶rateLimiter.delete();if (!rateLimiter.trySetRate(RateType.OVERALL, rate, interval, RateIntervalUnit.SECONDS)) {log.error("令牌桶 [{}] 初始化失败", redisKey);return null;}log.info("创建令牌桶 [{}],QPS: {}, 时间窗口: {} 秒", apiKey, rate, interval);return rateLimiter;}); }
-
申请令牌
/*** 申请一个令牌** @param ip 接口唯一标识* @param apiPath 接口唯一标识* @param rate 允许的请求数* @param interval 时间窗口(秒)* @return 是否成功获取令牌*/ public boolean tryAcquire(String ip, String apiPath, int rate, int interval) {String apiKey = "api_limit:" + ip + ":" + apiPath;RRateLimiter rateLimiter = getRateLimiter(apiKey, rate, interval);if (rateLimiter == null) {return false;}boolean acquired = rateLimiter.tryAcquire();// Redis Key 可能被删除,需要重新初始化if (!acquired && !rateLimiter.isExists()) {log.warn("检测到 RateLimiter [{}] 失效,重新初始化", apiKey);rateLimiterCache.remove(apiKey);rateLimiter = getRateLimiter(apiKey, rate, interval);if (rateLimiter != null) {acquired = rateLimiter.tryAcquire();}}if (!acquired) {log.warn("接口 [{}] 触发限流,QPS: {}, 时间窗口: {} 秒", apiKey, rate, interval);}return acquired; }
-
统一限流校验方法
/*** 令牌限流检查(对外暴露的方法)* @param rate 允许的请求数* @param interval 时间窗口(秒)* @throws ServiceException 如果触发限流*/ public void checkRateLimit(int rate, int interval) {String clientIp = WebTool.getRealIpAddress(); // 获取真实 IPString apiPath = WebTool.getApiPath(); // 获取接口路径boolean allowed = tryAcquire(clientIp, apiPath, rate, interval);if (!allowed) {log.warn("ip: {}, 接口 [{}] 触发限流,QPS: {}, 时间窗口: {} 秒", clientIp, apiPath, rate, interval);String msg = String.format("访问过于频繁,请稍后再试。IP: %s", clientIp);throw new ServiceException(msg);} }
✅ 方案解析
1. 分布式环境下的限流
-
使用 Redis 作为中心存储,每个接口的令牌桶都存储在 Redis 中,便于多个节点共享限流状态。
-
使用 Redisson 提供的
RRateLimiter
对象,它基于 Redis 提供了令牌桶算法的封装,自动管理令牌生成和消费的过程。
2. 令牌桶的管理
-
通过
getRateLimiter
方法动态创建和管理令牌桶。 -
使用
rateLimiter.trySetRate()
设置令牌桶的容量和生成速率。 -
每次请求前调用
rateLimiter.tryAcquire()
尝试获取一个令牌,如果成功则执行请求,否则拒绝。
3. 动态配置管理
-
使用 Redis hget 命令读取当前限流配置(
rate
和interval
),确保分布式环境下的限流配置保持一致。 -
如果发现 Redis 中的配置与本地配置不一致或令牌桶失效,则重新初始化令牌桶。
4. IP + 接口路径粒度限流
- 每个接口的限流是基于
api_limit:ip:apiPath
作为 Redis 的 Key,实现了IP + 接口级别的限流,可有效防止单个 IP 的恶意请求。
四、方案优缺点
优点 | 缺点 |
---|---|
支持分布式环境,多节点共享限流状态 | 依赖 Redis,如果 Redis 异常会影响限流功能 |
支持突发流量,平滑处理请求 | 需要额外维护 Redis 的资源占用 |
支持动态限流配置,实时生效 | 需要额外监控 Redis 的健康状态 |
提供接口级和 IP 级别的精细化限流 | 配置不当可能导致限流过于宽松或过于严格 |
五、 适用场景
-
API 网关限流:在 API 网关层通过该方案对外部流量进行限流,保护后端服务。
-
防止恶意攻击:防止某个 IP 针对特定接口的恶意请求。
-
限流突发流量:在秒杀、促销等场景中平滑处理流量峰值。
-
支付接口保护:确保支付接口在高并发情况下依旧可用。
总结
基于 Redis 的分布式令牌桶限流方案是一个可靠且高效的限流策略。它不仅能够有效应对突发流量,还能在分布式环境下保持限流配置一致性。
通过合理的配置和监控,可以保障系统的稳定性,提升用户体验。😊
相关文章:
分布式限流方案:基于 Redis 的令牌桶算法实现
分布式限流方案:基于 Redis 的令牌桶算法实现 前言一、原理介绍:令牌桶算法二、分布式限流的设计思路三、代码实现四、方案优缺点五、 适用场景总结 前言 在分布式场景下,接口限流变得更加复杂。传统的单机限流方式难以满足跨节点的限流需求…...
OpenHarmony子系统开发 - 电池管理(二)
OpenHarmony子系统开发 - 电池管理(二) 五、充电限流限压定制开发指导 概述 简介 OpenHarmony默认提供了充电限流限压的特性。在对终端设备进行充电时,由于环境影响,可能会导致电池温度过高,因此需要对充电电流或电…...
Cocos Creator版本发布时间线
官网找不到,DeepSeek给的答案,这里做个记录。 Cocos Creator 1.x 系列 发布时间:2016 年 - 2018 年 1.0(2016 年 3 月): 首个正式版本,基于 Cocos2d-x 的 2D 游戏开发工具链,集成可…...
修形还是需要再研究一下
最近有不少小伙伴问到修形和蜗杆砂轮的问题,之前虽然研究过一段时间,但是由于时间问题放下了,最近想再捡起来。 之前计算的砂轮齿形是一整段的,但是似乎这种对于有些小伙伴来说不太容易接受,希望按照修形的区域进行分…...
Java面试黄金宝典11
1. 什么是 JMM 内存模型 定义 JMM(Java Memory Model)即 Java 内存模型,它并非真实的物理内存结构,而是一种抽象的概念。其主要作用是规范 Java 虚拟机与计算机主内存(Main Memory)之间的交互方式&#x…...
华为p10 plus 鸿蒙2.0降级emui9.1.0.228
需要用到的工具 HiSuite Proxy V3 华为手机助手11.0.0.530_ove或者11.0.0.630_ove应该都可以。 官方的通道已关闭,所以要用代理,127.0.0.1端口7777 https://www.firmfinder.ml/ https://professorjtj.github.io/v2/ https://hisubway.online/articl…...
高速开源镜像站网址列表2503
高速开源镜像站网址列表 以下是国内常用的高速开源镜像站网址列表,涵盖企业和教育机构的主要站点,适用于快速下载开源软件和系统镜像: 一、企业镜像站 阿里云镜像站 地址:https://mirrors.aliyun.com/ 特点:覆盖广泛…...
Python----计算机视觉处理(Opencv:绘制图像轮廓:寻找轮廓,findContours()函数)
一、轮廓 轮廓是图像中目标物体或区域的外部边界线或边界区域,由一系列相连的像素构成封闭形状,代表了物体的基本外形。与边缘不同,轮廓是连续的,而边缘则不一定是连续的。 轮廓与边缘的区别: 轮廓是一组连续的点或线…...
python --face_recognition(人脸识别,检测,特征提取,绘制鼻子,眼睛,嘴巴,眉毛)/活体检测
dlib 安装方法 之前博文 https://blog.csdn.net/weixin_44634704/article/details/141332644 环境: python==3.8 opencv-python==4.11.0.86 face_recognition==1.3.0 dlib==19.24.6人脸检测 import cv2 import face_recognition# 读取人脸图片 img = cv2.imread(r"C:\U…...
【测试工具】如何使用 burp pro 自定义一个拦截器插件
在 Burp Suite 中,你可以使用 Burp Extender 编写自定义拦截器插件,以拦截并修改 HTTP 请求或响应。Burp Suite 支持 Java 和 Python (Jython) 作为扩展开发语言。以下是一个完整的流程,介绍如何创建一个 Burp 插件来拦截请求并进行自定义处理…...
51单片机和STM32 入门分析
51单片机和STM32是嵌入式开发中两种主流的微控制器,它们在架构、性能、应用场景等方面存在显著差异。以下是两者的对比分析及选择建议: 1. 51单片机与STM32的定义与特点 51单片机 定义:基于Intel 8051内核的8位微控制器,结构简单…...
python暴力破解html表单
import requests import time# 目标URL url "http://192.168.3.101/pikachu/vul/burteforce/bf_form.php" # 请替换为实际的目标URL# 已知的用户名 username "admin"# 密码字典文件路径 password_file "passwords.txt"# 伪造请求头ÿ…...
DeepSeek+RAG局域网部署
已经有很多平台集成RAG模式,dify,cherrystudio等,这里通过AI辅助,用DS的API实现一个简单的RAG部署。框架主要技术栈是Chroma,langchain,streamlit,答案流式输出,并且对答案加上索引。支持doc,docx,pdf,txt。…...
流影---开源网络流量分析平台(一)(小白超详细)
目录 流影介绍 一、技术架构与核心技术 二、核心功能与特性 流影部署 流影介绍 一、技术架构与核心技术 模块化引擎设计 流影采用四层模块化架构:流量探针(数据采集)、网络行为分析引擎(特征提取)、威胁检测引擎&…...
在IDEA中快速注释所有console.log
在IDEA中快速注释所有console.log 在前端IDEA中,快速注释所有console.log语句可以通过以下步骤实现2: 打开要修改的文件。使用快捷键CtrlF打开搜索框。点击打开使用正则搜索的开关或者通过AltR快捷键来打开。在搜索框输入[]*console.log[]*,…...
python全栈-前端
python全栈-前端 文章目录 HTML标签段落p、换行br、水平线hr图片img路径src超文本链接a超链接之锚点href#id文本有序列表ol无序列表ul自定义列表表格table表格属性单元格合并 表单Forminput标签HTML5新增type属性HTML5新增常用属性 实体字符块元素与行内元素/内联元素容器元素d…...
基于PySide6与pycatia的CATIA绘图文本批量处理工具开发实践
引言 在CAD软件二次开发领域,CATIA的自动化处理一直存在开发门槛高、接口复杂等痛点。本文基于Python生态,结合PySide6 GUI框架与pycatia接口库,实现了一套高效的绘图文本批量处理工具。该工具支持背景视图文本批量处理和交互式文本选择处理…...
Jenkins 集成 SonarQube 代码静态检查使用说明
环境准备 Jenkins 服务器 确保 Jenkins 已安装并运行(推荐 LTS 版本)。安装插件: SonarQube Scanner for Jenkins(用于集成 SonarQube 扫描)NodeJS Plugin(可选,用于 JavaScript 项目࿰…...
pytorch构建线性回归模型
仅仅用于自己记录pytorch学习记录 线性回归模型 (1)准备数据集 数据:三个数据x[x1,x2,x3] y[y1,y2,y3] import torch #线性回归,我们使用三组数据,分别是(1,2),(2,4&a…...
本地部署 LangManus
本地部署 LangManus 0. 引言1. 部署 LangManus2. 部署 LangManus Web UI 0. 引言 LangManus 是一个社区驱动的 AI 自动化框架,它建立在开源社区的卓越工作基础之上。我们的目标是将语言模型与专业工具(如网络搜索、爬虫和 Python 代码执行)相…...
skynet网络包库(lua-netpack.c)的作用解析
目录 网络包库(lua-netpack.c)的作用解析1. 数据包的分片与重组2. 网络事件处理3. 内存管理4. 数据打包与解包 动态库(.so)在 Lua 中的使用1. 编译为动态库2. Lua 中加载与调用(1) 加载模块(2) 核心方法(3) 使用示例 3. 注意事项 …...
XXL-Job 二次分片是怎么做的?有什么问题?怎么去优化的?
XXL-JOB二次分片机制及优化策略 二次分片实现原理 XXL-JOB的二次分片是在分片广播策略的基础上,由开发者自行实现的更细粒度数据拆分。核心流程如下: 初次分片:调度中心根据执行器实例数量(总分片数n)分配分片索引i&…...
零基础本地部署 ComfyUI+Flux.1 模型!5 分钟搭建远程 AI 绘图服务器(保姆级教程)
文章目录 前言1. 本地部署ComfyUI2. 下载 Flux.1 模型3. 下载CLIP模型4. 下载 VAE 模型5. 演示文生图6. 公网使用 Flux.1 大模型6.1 创建远程连接公网地址 7. 固定远程访问公网地址 前言 在如今这 AI 技术一路火花带闪电、疯狂往前冲的时代,图像生成模型那可不再是…...
ABC398题解
A 算法标签: 模拟 #include <iostream> #include <algorithm> #include <cstring>using namespace std;const int N 110;int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int n;cin >> n;string res;if (n % 2) {int mid n / 2;f…...
数据通信——计算机基础
通信系统的组成 通信系统是指从一个地方向另外一个地方传递和交换信息,实现信息传递所需的一切技术设备和传输媒体的总和。通信系统一般由信源、发送设备、信道、接收设备、信宿以及噪声源组成,以下是各部分的具体介绍: 信源 信源是产生各…...
量子计算与人工智能的融合:下一代算力革命
1. 引言:算力需求的飞速增长与量子计算的潜力 在信息技术飞速发展的今天,人工智能(AI)已经渗透到我们生活的方方面面,从智能助手到自动驾驶,再到医疗诊断,AI 的应用场景日益广泛。然而…...
神经网络解决非线性二分类
这份 Python 代码实现了一个简单的神经网络,用于解决复杂的非线性二分类问题。具体步骤包含生成数据集、定义神经网络模型、训练模型、测试模型以及可视化决策边界。 依赖库说明 python import numpy as np import matplotlib.pyplot as plt from sklearn.datase…...
nuxt3网站文章分享微信 ,QQ功能
1.安装 npm install qrcode --save-dev 2.组件使用 <div class"share"><div style"line-height: 69px; color: #fff;width: 100px;"><p style"text-align: center;">分享:</p></div><div click"shareToMi…...
深入理解Spring框架:核心概念与组成剖析
引言 在Java企业级开发领域,Spring框架无疑是当之无愧的王者。自2003年首次发布以来,Spring凭借其强大的功能、高度的灵活性和卓越的扩展性,已成为构建大型企业应用程序的首选框架。本文将深入探讨Spring框架的核心概念与多样组成部分&#…...
Ubuntu22.04美化MacOS主题
安装Tweaks 参考Ubuntu 22.04 桌面美化成Mac风格这篇更好点 sudo apt install gnome-tweaks gnome-shell-extensions -y安装macos主题 git clone https://github.com/vinceliuice/WhiteSur-gtk-theme.git # 进到文件目录 ./install.sh -t all -N glassy sudo ./tweaks.sh -g…...
MySQL: 创建两个关联的表,用联表sql创建一个新表
MySQL: 创建两个关联的表 建表思路 USERS 表:包含用户的基本信息,像 ID、NAME、EMAIL 等。v_card 表:存有虚拟卡的相关信息,如 type 和 amount。关联字段:USERS 表的 V_CARD 字段和 v_card 表的 v_card 字段用于建立…...
JavaScript 中for...in和for...of循环的原理区别,在遍历对象和数组时分别如何使用
大白话JavaScript 中for…in和for…of循环的原理区别,在遍历对象和数组时分别如何使用 嘿,朋友!咱来唠唠 JavaScript 里 for...in 和 for...of 这两种循环的事儿。它们就像是两个不同的小帮手,能帮你在对象和数组里溜达溜达&…...
图解AUTOSAR_SWS_WatchdogInterface
AUTOSAR Watchdog Interface (WdgIf) 详解 AUTOSAR经典平台看门狗接口模块技术详解 目录 1. 概述 1.1 WdgIf模块的作用1.2 WdgIf在AUTOSAR中的位置2. 架构设计 2.1 WdgIf架构概览2.2 接口设计2.3 序列设计3. 配置详解 3.1 配置参数3.2 配置结构3.3 配置类型4. 总结 4.1 主要特点…...
快速搭建yolo测试环境,超简明的神经网络训练说明书
1 快速搭建yolo测试环境 相对于更早的版本,v5是比较舒服的,直接把仓库拉下来就行,不用单独搞测试脚本和权重文件 $ git clone https://github.com/ultralytics/yolov5.git然后就是切到目录下安装依赖的第三方库: $ cd yolov5 $…...
如何在IDEA中借助深度思考模型 QwQ 提高编码效率?
通义灵码上新模型选择功能,不仅引入了 DeepSeek 满血版 V3 和 R1 这两大 “新星”,Qwen2.5-Max 和 QWQ 也强势登场,正式加入通义灵码的 “豪华阵容”。开发者只需在通义灵码智能问答窗口的输入框中,单击模型选择的下拉菜单&#x…...
探索 Ollama:开源大语言模型平台的无限可能
在人工智能的快速发展进程中,大语言模型扮演着至关重要的角色。Ollama 作为一个开源的大语言模型平台,正逐渐崭露头角,为广大开发者和爱好者带来了全新的体验。它允许用户在本地环境中轻松地运行、创建和共享大型语言模型,极大地降…...
clickhouse多条件查询
安装包 infi.clickhouse-orm 2.1.3建表 create table test.test (name String,age UInt32,birthday Date32,sex UInt8 ) engineMergeTree() order by (name,sex)insert into test.testvalues (aa,34,1991-01-19,1), (cc,30,1994-01-19,0), (haha,31,1994-02-19,0);多条件查询…...
信息的度量
系列文章目录 文章目录 系列文章目录一、离散消息的信息量1.自信息的引入2.自信息定义 二、离散信源的平均信息量---信息熵1.信息熵定义 一、离散消息的信息量 1.自信息的引入 通信的本质是传递信息,为了定量表征信息的度量,引入自信息量的概念。事件包…...
ffmpeg+QOpenGLWidget显示视频
一个基于 FFmpeg 4.x 和 QOpenGLWidget的简单视频播放器代码示例,实现视频解码和渲染到 Qt 窗口的功能。 1)ffmpeg库界面,视频解码支持软解和硬解方式。 硬解后,硬件解码完成需要将数据从GPU复制到CPU。优先采用av_hwf…...
从零开始实现 C++ TinyWebServer 项目总览
文章目录 引言Web Server 概念如何实现高性能 WebServer?基础网络通信I/O 多路复用技术并发处理事件处理模式其他优化策略(未实现) 主要功能模块BufferLogSqlConnectPoolHttpRequestHttpResponseHttpConnectHeapTimerWebServer 引言 TinyWeb…...
opencv无法读取的图像,利用pil和numpy进行修复
代码总结 这段代码的功能是遍历指定文件夹下的所有图像文件,并修复可能存在的格式问题,然后覆盖原图像。 代码解析 设置输入文件夹路径(input_folder)。遍历文件夹中的所有文件,筛选出 .jpg、.jpeg、.png、.webp 格式…...
Redis分布式寻址算法
分布式寻址算法是分布式系统中用于确定数据应该存储在哪个节点的算法。这些算法对于实现高效的数据存取、负载均衡和系统扩展性至关重要。以下是几种常见的分布式寻址算法的解释: 1. Hash 算法 原理:通过哈希函数将数据的键(Key)…...
CUDA 学习(1)——GPU 架构
典型 CPU 架构与 GPU 架构对比: 上图中绿色部分是计算单元,GPU 有更多的计算核心,计算能力更强。黄色部分是控制单元,CPU 中有大量的控制单元,现代 CPU 的晶体管越来越复杂,除了计算,还要实现乱…...
5个视角、5等级及10档次:《数字化转型领域 参考架构》国家标准正式出台
近日,国家标准GB/T 45341-2025《数字化转型管理 参考架构》正式出台。这是我国研制的首个数字化转型领域基础架构类国家标准,对数字化转型领域标准化建设具有重大意义。 关注WeChat Subscription Account【智慧城市指北】,回复关键字“20250…...
2.4 隐函数及由参数方程确定的函数求导
1.隐函数求导 1.1 例题 2. 参数方程确定的函数求导...
PROE 与 STL 格式转换:开启 3D 打印及多元应用的大门
在 3D 设计与制造的复杂生态中,将 PROE 格式转换为 STL 格式绝非无端之举,而是有着深厚且多元的现实需求作为支撑。 一、文件格式介绍 (一)PROE 格式 PROE 作为一款参数化设计软件,采用基于特征的参数化建模技术…...
【Bug记录】node-sass安装失败解决方案
【Bug记录】node-sass 安装失败解决办法 前言 很多小伙伴在安装 node-sass 的时候都失败了,主要的原因是 node 版本和项目依赖的 node-sass 版本不匹配。 解决方案 解决方案:把项目中的 node-sass 替换为 sass,其实 node-sass 已被官方弃…...
三、Python高级特性
Python中的高级数据结构:队列、栈、双端队列、堆与优先队列 在Python编程中,高级数据结构为我们提供了强大而灵活的工具来处理各种复杂的数据存储和操作需求。本文将详细介绍队列、栈、双端队列、堆与优先队列这几种常见的高级数据结构及其在Python中的…...
使用 OpenCV 拼接进行图像处理对比:以形态学操作为例
图像处理在计算机视觉中起着至关重要的作用,而 OpenCV 作为一个强大的图像处理库,提供了丰富的函数来实现各类图像处理任务。形态学操作(Morphological Operations)是其中常用的技术,尤其适用于二值图像的处理。常见的…...
OPENCV数字识别(非手写数字/采用模板匹配)
这篇文章的重点在于 模板匹配 的使用。模板匹配是计算机视觉中的一项基本技术,它通过比对输入图像与模板图像的相似度,来进行目标识别。对于数字识别,特别是标准数字的识别,模板匹配非常有效。 请看效果: 文章结构 …...