分布式令牌桶限流原理

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 分布式令牌桶限流通过Lua+Java结合完成,首先在Lua脚本中完成限流的计算,然后在Java代码中进行组织和调用。

分布式令牌桶限流Lua脚本
分布式令牌桶限流Lua脚本的核心逻辑和Java令牌桶的执行逻辑类似,只是限流计算相关的统计和时间数据存放于Redis中。

限流的脚本命名为rate_limiter.lua,该脚本既使用Redis存储令牌桶信息,自身又执行于Redis中。它的代码如下:

---方法:申请令牌
----1:failed
---1:success
---@param key:key限流关键字
---@param apply:申请的令牌数量
local function acquire(key, apply)
 local times = redis.call('TIME');
 --times[1] 秒数 --times[2] 微秒数
 local curr_mill_second = times[1] *1000000 + times[2];
 curr_mill_second = curr_mill_second / 1000;
 local cacheInfo = redis.pcall("HMGET", key, "last_mill_second", "curr_permits", "max_permits", "rate")
 ---局部变量:上次申请的时间
 local last_mill_second = cacheInfo[1];
 ---局部变量:之前的令牌数
 local curr_permits = tonumber(cacheInfo[2]);
 ---局部变量:桶的容量
 local max_permits = tonumber(cacheInfo[3]);
 ---局部变量:令牌的发放速率
 local rate = cacheInfo[4];
 ---局部变量:本次的令牌数
 local local_curr_permits = max_permits;
 if (type(last_mill_second) ~= 'boolean' and last_mill_second ~= nil) then
 --计算时间段内的令牌数
 local reverse_permits = math.floor(((curr_mill_second - last_mill_second) / 1000) *rate);
 --令牌总数
 local expect_curr_permits = reverse_permits + curr_permits;
 --可以申请的令牌总数
 local_curr_permits = math.min(expect_curr_permits, max_permits);
 else
 --第一次获取令牌
 redis.pcall("HSET", key, "last_mill_second", curr_mill_second)
 end
 local result = -1;
 --有足够的令牌可以申请
 if (local_curr_permits - apply >= 0) then
 --保存剩余的令牌
 redis.pcall("HSET", key, "curr_permits", local_curr_permits - apply);
 --保存时间,下次令牌获取时使用
 redis.pcall("HSET", key, "last_mill_second", curr_mill_second)
 --返回令牌获取成功
 result = 1;
 else
 --保存令牌总数
 redis.pcall("HSET", key, "curr_permits", local_curr_permits);
 --返回令牌获取失败
 result = -1;
 end
 return result
end
---方法:初始化限流器
---1 success
---@param key key
---@param max_permits 桶的容量
---@param rate 令牌的发放速率
local function init(key, max_permits, rate)
 local rate_limit_info = redis.pcall("HMGET", key, "last_mill_second", "curr_permits", "max_permits", "rate")
 local org_max_permits = tonumber(rate_limit_info[3])
 local org_rate = rate_limit_info[4]
 if (org_max_permits == nil) or (rate ~= org_rate or max_permits ~= org_max_permits) then
 redis.pcall("HMSET", key, "max_permits", max_permits, "rate", rate, "curr_permits", max_permits)
 end
 return 1;
end
---方法:删除限流Key
local function delete(key)
 redis.pcall("DEL", key) return 1;
end
local key = KEYS[1]
local method = ARGV[1]
if method == 'acquire' then
 return acquire(key, ARGV[2], ARGV[3])
elseif method == 'init' then
 return init(key, ARGV[2], ARGV[3])
elseif method == 'delete' then
 return delete(key)
else
 --ignore
end

该脚本有3个方法,其中两个方法比较重要,分别说明如下:

(1)限流器初始化方法init(key,max_permits,rate),此方法在限流开始时被调用。

(2)限流检测的方法acquire(key,apply),此方法在请求到来时被调用。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
5月前
|
存储 分布式计算 Hadoop
Hadoop【基础知识 01】【分布式文件系统HDFS设计原理+特点+存储原理】(部分图片来源于网络)
【4月更文挑战第3天】Hadoop【基础知识 01】【分布式文件系统HDFS设计原理+特点+存储原理】(部分图片来源于网络)
204 3
|
11天前
|
网络协议 安全 Java
分布式(基础)-RMI的原理
分布式(基础)-RMI的原理
|
2月前
|
存储 NoSQL 算法
Go 分布式令牌桶限流 + 兜底保障
Go 分布式令牌桶限流 + 兜底保障
|
5月前
|
存储 分布式计算 监控
Hadoop【基础知识 01+02】【分布式文件系统HDFS设计原理+特点+存储原理】(部分图片来源于网络)【分布式计算框架MapReduce核心概念+编程模型+combiner&partitioner+词频统计案例解析与进阶+作业的生命周期】(图片来源于网络)
【4月更文挑战第3天】【分布式文件系统HDFS设计原理+特点+存储原理】(部分图片来源于网络)【分布式计算框架MapReduce核心概念+编程模型+combiner&partitioner+词频统计案例解析与进阶+作业的生命周期】(图片来源于网络)
274 2
|
3月前
|
存储 缓存 NoSQL
高并发架构设计三大利器:缓存、限流和降级问题之Redis用于搭建分布式缓存集群问题如何解决
高并发架构设计三大利器:缓存、限流和降级问题之Redis用于搭建分布式缓存集群问题如何解决
|
3月前
|
NoSQL Redis 数据库
|
5月前
|
存储 缓存 算法
【专栏】探讨分布式限流所面临的挑战以及目前业界常用的解决方案
【4月更文挑战第27天】在互联网时代,分布式限流是应对高并发、保护系统稳定的关键。它面临数据一致性、算法准确性和系统可扩展性的挑战。常见限流算法有令牌桶、漏桶和滑动窗口。解决方案包括使用分布式存储同步状态、结合多种算法及动态调整阈值。定期压力测试确保策略有效性。随着系统规模增长,限流技术将持续发展,理解并应用限流原理对保障服务质量至关重要。
131 3
|
5月前
|
存储 NoSQL 分布式数据库
【Flink】Flink分布式快照的原理是什么?
【4月更文挑战第21天】【Flink】Flink分布式快照的原理是什么?
|
5月前
|
存储 运维 分布式计算
面经:HDFS分布式文件系统原理与故障排查
【4月更文挑战第10天】本文深入剖析了HDFS的底层原理和面试重点,包括HDFS的架构(NameNode、DataNode、Secondary NameNode)、文件读写流程、高级特性(快照、Erasure Coding、Federation、High Availability)以及故障排查方法。通过HDFS Shell命令示例,加强理解,并对比了HDFS与其他分布式文件系统的优缺点。掌握这些知识将有助于求职者在面试中脱颖而出,应对HDFS相关技术考察。
254 3
|
5月前
|
消息中间件 存储 监控
解析RocketMQ:高性能分布式消息队列的原理与应用
RocketMQ是阿里开源的高性能分布式消息队列,具备低延迟、高吞吐和高可靠性,广泛应用于电商、金融等领域。其核心概念包括Topic、Producer、Consumer、Message和Name Server/Broker。RocketMQ支持异步通信、系统解耦、异步处理和流量削峰。关键特性有分布式架构、顺序消息、高可用性设计和消息事务。提供发布/订阅和点对点模型,以及消息过滤功能。通过集群模式、存储方式、发送和消费方式的选择进行性能优化。RocketMQ易于部署,可与Spring集成,并与Kafka等系统对比各有优势,拥有丰富的生态系统。
725 4
下一篇
无影云桌面