分布式限流——Redis实现令牌桶算法
令牌桶算法
令牌桶算法(Token Bucket Algorithm)是一种广泛使用的流量控制(流量整形)和速率限制算法。这个算法能够控制网络数据的传输速率,确保数据传输的平滑性,防止网络拥堵,同时也被应用于软件系统中限制请求的速率,如API限流等场景。
工作原理
-
令牌的生成:系统以固定的速率向令牌桶中添加令牌(token),直到桶满为止。桶的容量(即最大令牌数)限制了短时间内可以发送的最大数据量。
-
请求的处理:每个传入的请求需要从桶中取出一定数量的令牌。如果桶中有足够的令牌,请求就被处理,消耗掉相应数量的令牌;如果桶中令牌不足,请求则根据策略(如排队、丢弃或延迟处理)来处理。
-
灵活控制:通过调整令牌的生成速率和桶的容量,可以灵活地控制数据传输的平均速率和允许的突发速率。
漏桶算法
漏桶算法(Leaky Bucket Algorithm)是另一种流量控制算法,用于确保数据传输以稳定的速率进行,减少或消除突发流量。与令牌桶算法相比,漏桶算法提供了一种更为严格的速率限制方式。
漏桶算法的工作原理
- 数据流入:数据(如网络包、API请求等)以任意速率流入漏桶。
- 恒定速率流出:数据以恒定的速率从桶中“漏出”(被处理)。如果桶满了(达到其容量),则新进入的数据会被丢弃或排队等待。
- 稳定输出:无论输入数据的速率如何变化,输出数据的速率保持不变,由漏桶的“漏洞”大小决定。
令牌桶算法与漏桶算法的主要区别
- 速率控制灵活性:令牌桶算法允许一定程度的突发流量,因为如果桶中有足够的令牌,突发的请求可以立即被处理。而漏桶算法则以恒定的速率处理请求,输入速率超过这个恒定值的部分将被限制或丢弃,因此不允许突发流量。
- 应对突发流量:令牌桶算法能够更好地应对突发流量。当桶中有足够令牌时,可以一次性处理较多的请求。漏桶算法则始终以固定的速率处理流入的请求,突发流量只能在桶内等待,直到它们逐渐被处理。
- 应用场景:漏桶算法适用于需要严格控制数据传输速率的场景,确保数据处理的平稳性;令牌桶算法则更适用于需要一定程度突发性处理能力的场景,例如网络带宽控制和API限流。
总结
- 漏桶算法通过以固定的速率“漏出”数据来控制数据的传输速率,适用于对输出速率有严格要求的场景。
- 令牌桶算法允许在桶中累积令牌,从而应对突发流量,适用于需要较大灵活性的速率限制场景。
Redis实现令牌桶算法限流
Redis 实现令牌桶算法限流是一种非常有效的限流策略,适用于分布式系统中的接口限流。令牌桶算法的核心思想是以恒定的速率向桶中添加令牌,每个请求需要消耗一定数量的令牌才能被执行。如果桶中令牌不足,则拒绝服务。
在 Redis 中实现令牌桶算法通常可以通过 Lua 脚本来保证操作的原子性,以下是一个基于 Redis 的令牌桶限流实现示例:
-- Lua 脚本实现令牌桶算法
-- key 为 Redis 中用于存储桶的键
-- rate 为令牌填充速率(每秒填充的令牌数)
-- capacity 为桶的容量
-- now 为当前时间戳
-- permits 为本次请求需要的令牌数local key = KEYS[1]
local rate = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local permits = tonumber(ARGV[4])local bucket = redis.call('hmget', key, 'lastRefillTime', 'tokens')
local lastRefillTime = tonumber(bucket[1])
local tokens = tonumber(bucket[2])if lastRefillTime == nil thenlastRefillTime = nowtokens = capacity
end-- 计算自上次填充以来经过的时间
local delta = math.max(0, now - lastRefillTime)
-- 计算应该填充的令牌数
local refillTokens = math.floor(delta * rate)
tokens = math.min(capacity, tokens + refillTokens)
lastRefillTime = nowlocal enoughTokens = false
if tokens >= permits thenenoughTokens = truetokens = tokens - permits
end-- 更新桶的状态
redis.call('hmset', key, 'lastRefillTime', lastRefillTime, 'tokens', tokens)-- 设置过期时间防止无限增长
redis.call('expire', key, math.ceil(capacity/rate)*2)if enoughTokens thenreturn 1
elsereturn 0
end
具体的 key-value 结构
在这个场景中,hash
的键(key)是用来唯一标识一个令牌桶的,而这个 hash
包含了两个字段(field),分别存储了令牌桶的两个重要属性:
- lastRefillTime:最后一次填充令牌的时间戳。
- tokens:当前桶中的令牌数量。
具体的 key-value
结构如下所示:
- Key:令牌桶的唯一标识符,例如
"my_bucket_key",根据具体业务标识有所不同
。 - Value:是一个
hash
结构,包含以下字段:- lastRefillTime:桶最后一次填充令牌的时间戳,用来计算距离上次填充令牌过去了多少时间,以及这段时间内应该填充多少新的令牌。
- tokens:表示当前桶内剩余的令牌数量。
为什么用Hash
在 Redis 中使用 hash
数据结构来实现令牌桶算法的原因主要包括以下几点:
-
空间效率:使用
hash
可以将与令牌桶相关的多个属性(如lastRefillTime
和tokens
)存储在同一个键下。这比为每个属性分别使用一个键要节省空间,因为 Redis 的每个键都会有额外的内存开销。 -
原子操作:Redis 提供了对
hash
类型的一系列原子操作命令,如HSET
,HGET
,HMSET
,HMGET
等。这意味着可以在一个命令中更新令牌桶的多个属性,而无需担心并发访问导致的数据不一致问题。 -
性能优势:相对于单独存储每个属性,
hash
数据结构减少了存储开销和访问时间。对于频繁更新和查询的令牌桶状态信息,这种优势尤为重要。 -
方便管理:使用
hash
数据结构可以将所有与令牌桶相关的信息组织在一起,这使得管理(如查看、更新和删除等操作)更为方便。 -
扩展性:如果将来需要在令牌桶中添加更多的属性(例如,添加一个
rate
字段来存储令牌填充速率),使用hash
结构可以很容易地进行扩展,而无需改变现有的数据结构或逻辑。 -
利用 Lua 脚本进行复杂操作:通过在 Redis 上运行 Lua 脚本,可以在服务器端直接执行复杂的逻辑(如计算新的令牌数量和更新最后填充时间),而不需要在客户端和服务器之间进行多次通信。
hash
数据结构支持通过一个命令对多个字段进行操作,这与 Lua 脚本的使用非常契合。
相关文章:
分布式限流——Redis实现令牌桶算法
令牌桶算法 令牌桶算法(Token Bucket Algorithm)是一种广泛使用的流量控制(流量整形)和速率限制算法。这个算法能够控制网络数据的传输速率,确保数据传输的平滑性,防止网络拥堵,同时也被应用于…...

鸿蒙原生应用已超4000个!
鸿蒙原生应用已超4000个! 来自 HarmonyOS 微博近期消息,#鸿蒙千帆起# 重大里程碑!目前已有超4000个应用加入鸿蒙生态。从今年1月18日华为宣布首批200多家应用厂商正在加速开发鸿蒙原生应用,到3月底超4000个应用,短短…...

manga-ocr漫画日文ocr
github 下载 解压 anaconda新建环境 conda create -n manga_ocr python3.8 激活环境 conda activate manga_ocr cd到解压目录 cd /d manga-ocr-master 安装依赖包 pip install -r requirements.txt pip3 install manga-ocr 下载离线model huggingface 123云盘 解压到一个目录…...
STL、Vector和Set的讲解和例题分析
STL STL(Standard Template Library,标准模板库)是C标准库的一部分,它提供了一系列通用的编程组件,包括容器、迭代器、算法和函数对象等。STL是C中实现泛型编程的核心,它允许程序员使用模板编写与数…...
Android 13 aosp hiddenapi config
Android 11 hiddenapi路径 frameworks/base/config/hiddenapi-greylist-packages.txtAndroid 13 hiddenapi路径 frameworks/base/boot/hiddenapi/hiddenapi-unsupported-packages.txt...

数据仓库面试总结
文章目录 1.什么是数据仓库?2.ETL是什么?3.数据仓库和数据库的区别(OLTP和OLAP的区别)4.数据仓库和数据集市的区别5.维度分析5.1 什么是维度?5.2什么是指标? 6.什么是数仓建模?7.事实表7.维度表…...

git Failed to connect to 你的网址 port 8282: Timed out
git Failed to connect to 你的网址 port 8282: Timed out 出现这个问题的原因是:原来的仓库换了网址,原版网址不可用了。 解决方法如下: 方法一:查看git用户配置是否有如下配置 http.proxyhttp://xxx https.proxyhttp://xxx如果…...
[C++][算法基础]堆排序(堆)
输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。 输入格式 第一行包含整数 n 和 m。 第二行包含 n 个整数,表示整数数列。 输出格式 共一行,包含 m 个整数,表示整数数列中前 m 小的数。 数据范围 1≤m≤n≤&#x…...

备考ICA----Istio实验15---开启 mTLS 自动双向认证实验
备考ICA----Istio实验15—开启mTLS自动双向认证实验 在某些生成环境下,我们希望微服务和微服务之间使用加密通讯方式来确保不被中间人代理. 默认情况下Istio 使用 PERMISSIVE模式配置目标工作负载,PERMISSIVE模式时,服务可以使用明文通讯.为了只允许双向 TLS 流量,…...
Hive SchemaTool 命令详解
Hive schematool 是 hive 自带的管理 schema 的相关工具。 列出详细说明 schematool -help直接输入 schematool 或者schematool -help 输出结果如下: usage: schemaTool-alterCatalog <arg> Alter a catalog, requires--catalogLocation an…...

51单片机入门_江协科技_17~18_OB记录的笔记
17. 定时器 17.1. 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成,无需占用CPU外围IO接口; 定时器作用: (1)用于计时系统,可实现软件计时&…...

xss.pwnfunction-Ah That‘s Hawt
<svg/onloadalert%26%2340%3B1%26%2341%3B> <svg/>是一个自闭合形式 ,当页面或元素加载完成时,onload 事件会被触发,从而可以执行相应的 JavaScript 函数...
Python学习从0开始——005数据结构
Python学习从0开始——005数据结构 一、列表list二、元组和序列三、集合四、字典五、循环技巧六、条件控制七、序列和其它类型的比较 一、列表list 不是所有数据都可以排序或比较。例如,[None, ‘hello’, 10] 就不可排序,因为整数不能与字符串对比&…...

力扣每日一题:LCR112--矩阵中的最长递增路径
题目 给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。 对于每个单元格,你可以往上,下,左,右四个方向移动。 不能 在 对角线 方向上移动或移动到 边界外(即不允许环绕)。 示例…...

树莓派部署yolov5实现目标检测(ubuntu22.04.3)
最近两天搞了一下树莓派部署yolov5,有点难搞(这个东西有点老,版本冲突有些包废弃了等等) 最后换到ubuntu系统弄了,下面是我的整体步骤(建议先使能一下ssh(最下面有),结合…...

2024 年最新使用 Wechaty 开源框架搭建部署微信机器人(微信群智能客服案例)
读取联系人信息 获取当前机器人账号全部联系人信息 bot.on(ready, async () > {console.log("机器人准备完毕!!!")let contactList await bot.Contact.findAll()for (let index 0; index < contactList.length; index) {…...

Redis从入门到精通(九)Redis实战(六)基于Redis队列实现异步秒杀下单
↑↑↑请在文章开头处下载测试项目源代码↑↑↑ 文章目录 前言4.5 分布式锁-Redisson4.5.4 Redission锁重试4.5.5 WatchDog机制4.5.5 MutiLock原理 4.6 秒杀优化4.6.1 优化方案4.6.2 完成秒杀优化 4.7 Redis消息队列4.7.1 基于List实现消息队列4.7.2 基于PubSub的消息队列4.7.…...

什么是多路复用器滤波器
本章将更深入地介绍多路复用器滤波器,以及它们如何用于各种应用中。您将了解到多路复用器如何帮助设计人员创造出更复杂的无线产品。 了解多路复用器 多路复用器是一组射频(RF)滤波器,它们组合在一起,但不会彼此加载,可以在输出之…...

Severt和tomcat的使用(补充)
打包程序 在pom.xml中添加上述代码之后打包时会生成war包并且包的名称是test 默认情况打的是jar包.jar里量但是tomcat要求的是war包. war包Tomcat专属的压缩包. war里面不光有.class还有一些tomcat要求的配置文件(web.xml等)还有前端的一些代码(html, css, js) 点击其右边的m…...

JavaEE初阶——多线程(一)
T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 小比特 大梦想 此篇文章与大家分享多线程的第一部分:引入线程以及创建多线程的几种方式 此文章是建立在前一篇文章进程的基础上的 如果有不足的或者错误的请您指出! 1.认识线程 我们知道现代的cpu大多都是多核心…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...