注明:
本文为整理记录笔记,不喜勿喷。有问题请留言。CSDN转载必须有原文链接,有些链接找不到了,原文看到了可以留言私我。
描述:
令牌桶:以一定的速率向一个固定大小的桶里扔令牌,然后每次去桶里取令牌,取的到说明有流量,反之没有
令牌桶算法:min((当前时间-上次更新桶时间) * 速率 + 桶里剩余的令牌数量,桶大小),即min(((currentMills - last_mill_second) / 1000)*rate+current_permits,max_burst)
举例:在秒杀活动中,用户的请求速率是不固定的,这里我们假定为10r/s,令牌按照5个每秒的速率(rate)放入令牌桶,桶中最多存放20个令牌(maxBurst),那系统就只会允许持续的每秒处理5个请求,或者每隔4秒,等桶中20 个令牌攒满后,一次处理20个请求的突发情况,保证系统稳定性。
算法详细介绍参考文章:https://baike.baidu.com/item/%E4%BB%A4%E7%89%8C%E6%A1%B6%E7%AE%97%E6%B3%95/6597000?fr=aladdin
分布式限流一次操作步骤:读数据-判断结果-写数据(更新桶)
分布式限流要解决问题:保证操作的原子性(即上述步骤不可分割)
lua好处:Redis使用同一个Lua解释器去运行所有脚本,并且,Redis也保证脚本会以原子性(atomic)的方式执行:当某个脚本正在运行的时候,不会有其他脚本或Redis命令被执行.这和使用 MULTI/EXEC 包围的事务很类似在其他别的客户端看来,脚本的效果(effect)要么是不可见的(not visible),要么就是已完成的(already completed)。参考文章https://redis.io/commands/eval
lua相关知识
语法参考文章:https://www.runoob.com/lua/lua-tutorial.html
redis里的命令参考文章:https://www.runoob.com/redis/redis-scripting.html
redis里调试lua脚本:类似于前端调试时的console.log进行打印日志调试
redis里调试lua脚本步骤:
1.查看redis的日志级别
2.脚本添加代码(一定要保证二者日志级别一致才能打印成功)
redis.log(redis.LOG_NOTICE, "Hi " .. "holidaylee")
3.查看效果
代码实现
结构:
初始化令牌桶lua脚本rateLimitInit.lua
redis.replicate_commands()
local result = -1
local rate_limit_info = redis.pcall("HMGET", KEYS[1], "last_mill_second", "current_permits", "max_burst", "rate", &