分布式令牌桶限流原理

简介: 分布式令牌桶限流通过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),此方法在请求到来时被调用。

相关文章
|
NoSQL 算法 安全
分布式锁—1.原理算法和使用建议
本文主要探讨了Redis分布式锁的八大问题,包括非原子操作、忘记释放锁、释放其他线程的锁、加锁失败处理、锁重入问题、锁竞争问题、锁超时失效及主从复制问题,并提供了相应的优化措施。接着分析了Redis的RedLock算法,讨论其优缺点以及分布式专家Martin对其的质疑。此外,文章对比了基于Redis和Zookeeper(zk)的分布式锁实现原理,包括获取与释放锁的具体流程。最后总结了两种分布式锁的适用场景及使用建议,指出Redis分布式锁虽有性能优势但模型不够健壮,而zk分布式锁更稳定但部署成本较高。实际应用中需根据业务需求权衡选择。
|
运维 NoSQL 算法
【📕分布式锁通关指南 04】redis分布式锁的细节问题以及RedLock算法原理
本文深入探讨了基于Redis实现分布式锁时遇到的细节问题及解决方案。首先,针对锁续期问题,提出了通过独立服务、获取锁进程自己续期和异步线程三种方式,并详细介绍了如何利用Lua脚本和守护线程实现自动续期。接着,解决了锁阻塞问题,引入了带超时时间的`tryLock`机制,确保在高并发场景下不会无限等待锁。最后,作为知识扩展,讲解了RedLock算法原理及其在实际业务中的局限性。文章强调,在并发量不高的场景中手写分布式锁可行,但推荐使用更成熟的Redisson框架来实现分布式锁,以保证系统的稳定性和可靠性。
1062 0
【📕分布式锁通关指南 04】redis分布式锁的细节问题以及RedLock算法原理
|
设计模式 存储 算法
分布式系统架构5:限流设计模式
本文是小卷关于分布式系统架构学习的第5篇,重点介绍限流器及4种常见的限流设计模式:流量计数器、滑动窗口、漏桶和令牌桶。限流旨在保护系统免受超额流量冲击,确保资源合理分配。流量计数器简单但存在边界问题;滑动窗口更精细地控制流量;漏桶平滑流量但配置复杂;令牌桶允许突发流量。此外,还简要介绍了分布式限流的概念及实现方式,强调了限流的代价与收益权衡。
812 12
|
存储 Dubbo Java
分布式 RPC 底层原理详解,看这篇就够了!
本文详解分布式RPC的底层原理与系统设计,大厂面试高频,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
分布式 RPC 底层原理详解,看这篇就够了!
|
机器学习/深度学习 存储 运维
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
892 4
|
分布式计算 Hadoop 网络安全
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
275 1
|
存储 机器学习/深度学习 缓存
Hadoop-07-HDFS集群 基础知识 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
Hadoop-07-HDFS集群 基础知识 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
464 1
|
存储 NoSQL 算法
Go 分布式令牌桶限流 + 兜底保障
Go 分布式令牌桶限流 + 兜底保障
|
存储 缓存 数据处理
深度解析:Hologres分布式存储引擎设计原理及其优化策略
【10月更文挑战第9天】在大数据时代,数据的规模和复杂性不断增加,这对数据库系统提出了更高的要求。传统的单机数据库难以应对海量数据处理的需求,而分布式数据库通过水平扩展提供了更好的解决方案。阿里云推出的Hologres是一个实时交互式分析服务,它结合了OLAP(在线分析处理)与OLTP(在线事务处理)的优势,能够在大规模数据集上提供低延迟的数据查询能力。本文将深入探讨Hologres分布式存储引擎的设计原理,并介绍一些关键的优化策略。
917 0