首页 > 数据库 >redis限流

redis限流

时间:2024-06-04 18:35:05浏览次数:27  
标签:capacity lastTs redis ARGV 限流 tonumber local

前提

redis+lua

 

滑动窗口

-- 滑动窗口
local key = KEYS[1]
local maxSize = ARGV[1]
local currentTime = ARGV[2]
local startTime = ARGV[3]
local uuid = ARGV[4]
local currentCount = redis.call('zcount',key,startTime,currentTime)
if (currentCount and tonumber(currentCount)>=tonumber(maxSize)) then
    return 0
end
-- 防止zset添加同一时间添加元素覆盖,添加后缀uuid
redis.call('zadd',key,currentTime,currentTime..uuid)
redis.call('expire',key,60*60*24)
-- 删除过期时间区间
redis.call('zremrangebyscore',key,0,startTime-10000)
return 1

 

漏桶

-- 漏桶
-- capacity:容量,passRate:漏水速率,addWater:每次请求加水量(默认为1),water:当前水量,lastTs:时间戳
local limitInfo = redis.call('hmget',KEYS[1],'capacity','passRate','water','lastTs')
local capacity = limitInfo[1]
local passRate = limitInfo[2]
local water = limitInfo[3]
local lastTs = limitInfo[4]
local addWater = 1
-- 初始化漏桶
if capacity == false or passRate==false then
    capacity = tonumber(ARGV[1])
    passRate = tonumber(ARGV[2])
    water = addWater
    lastTs = ARGV[3]
    redis.call('hmset',KEYS[1],'capacity',capacity,'passRate',passRate,'addWater',addWater,'water',water,'lastTs',lastTs)
    return 1
else
    local nowTs = ARGV[3]
    -- 当前距离上一次漏水量
    local waterPass = tonumber((tonumber(nowTs)-tonumber(lastTs))*tonumber(passRate)/1000)
    water = math.max(0,tonumber(water-waterPass))
    lastTs = nowTs
    if capacity-water>=addWater then
        water = water+addWater
        capacity = tonumber(ARGV[1])
        passRate = tonumber(ARGV[2])
        redis.call('hmset',KEYS[1],'capacity',capacity,'passRate',passRate,'water',water,'lastTs',lastTs)
        redis.call('expire',KEYS[1],60*60*24)
        return 1
    end
    return 0
end

 

令牌桶

-- 令牌桶
-- capacity:容量,rate:令牌生成速率,leftTokenNum:剩余令牌数,lastTs:时间戳
local limitInfo = redis.call('hmget',KEYS[1],'capacity','rate','leftTokenNum','lastTs')
local capacity = limitInfo[1]
local rate = limitInfo[2]
local leftTokenNum = limitInfo[3]
local lastTs = limitInfo[4]
-- 本次需要的令牌数
local need = 1
if capacity==false or rate==false or leftTokenNum==false then
    capacity = tonumber(ARGV[1])
    rate = tonumber(ARGV[2])
    lastTs = ARGV[3]
    leftTokenNum = capacity-need
    redis.call('hmset',KEYS[1],'capacity',capacity,'rate',rate,'leftTokenNum',leftTokenNum,'lastTs',lastTs)
    return 1
else
    local nowTs = ARGV[3]
    -- 距离上次产生的令牌数
    local createTokenNum = tonumber((tonumber(nowTs)-tonumber(lastTs))*tonumber(rate)/1000)
    -- 剩余的令牌数
    leftTokenNum = math.min(capacity,createTokenNum+leftTokenNum)
    lastTs = nowTs
    -- 判断是否还有令牌
    if leftTokenNum>=need then
        -- 减去需要的令牌
        leftTokenNum = leftTokenNum - need
        -- 更新
        capacity = tonumber(ARGV[1])
        rate = tonumber(ARGV[2])
        redis.call('hmset',KEYS[1],'capacity',capacity,'rate',rate,'leftTokenNum',leftTokenNum,'lastTs',lastTs)
        redis.call('expire',KEYS[1],60*60*24)
        return 1
    end
    return 0
end

 

标签:capacity,lastTs,redis,ARGV,限流,tonumber,local
From: https://www.cnblogs.com/tangs1/p/18231145

相关文章

  • 12- Redis 中的 链表 数据结构
    Redis的List对象的底层实现之一就是链表。C语言本身没有链表这个数据结构,所以Redis自己设计了一个链表数据结构。1.链表节点结构设计先来看看【链表节点】结构的样子:typedefstructlistNode{  //前置节点  structlistNode*prev;  //后置节点 ......
  • CentOS-7.9 安装redis7.0.5步骤
     下载Redis7.0.5的源代码wgethttp://download.redis.io/releases/redis-7.0.5.tar.gz解压并进入源代码目录tarzxfredis-7.0.5.tar.gzcdredis-7.0.5编译和安装,并指定安装目录,并复制Redis配置文件makesudomakePREFIX=/usr/local/redisinstallcpredis.conf......
  • CSRedis用于Redis哨兵模式,NetCore
    十年河东,十年河西,莫欺少年穷学无止境,精益求精上一节通过两台windowsServer服务器部署了Redis的哨兵模式,详情参考:两台windowserver服务器配置Redis哨兵集群----一主二从redis通过主从复制来实现高可用,但是发生故障时需要人工进行主从切换,效率低下。哨兵机制实现了redis主从的自......
  • Conts7 安装Redis教程
    1.添加软件安装源yuminstalleple-release2.安装Redisyuminstallredis-y3.启动redissystemctlstartredis4.允许开机启动systemctlenableredis5.修改redis配置文件vim/ect/redis.conf修改2处文件(虚拟机)6.重启redissystemctlrestartredis7.登陆redis数......
  • redis - [03] 配置&命令
    题记部分 一、配置(Config)  二、命令(Command)(1)启动redis服务:redis-server.exeredis.windows.conf(2)连接redis-server:redis-cli-hhost-pport-apassword(3)查看key是否存在:existsmyKey(4)查看key的值:getmyKey(5)序列化给定key,返回序列化的值(不会改变key的值):dumpmy......
  • Redis之set
    SetRedis的Set是String类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。(无序不重复)集合对象的编码可以是intset或者hashtable。Redis中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。案例127.0.0.1:6379>SADDmysethe......
  • Redis之list
    Redis列表(List)Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含2^32-1个元素(4294967295,每个列表超过40亿个元素)。list可以定义一些规则,使它作为栈、队列或双端队列。案例LPUSH&RPUSH127.......
  • 面试必会->Redis篇
    01-你们项目中哪里用到了Redis?在我们的项目中很多地方都用到了Redis,Redis在我们的项目中主要有三个作用:使用Redis做热点数据缓存/接口数据缓存使用Redis存储一些业务数据,例如:验证码,用户信息,用户行为数据,数据计算结果,排行榜数据等使用Redis实现分布......
  • 数据治理--企业数据服务 数据连接注册成API并且通过网关去限流 数据同步
      不直接开发hive的API访问速度慢,开放内存Presto的API去hive库查这样快 第一种不安全, 第二种公司内部用比较安全,结构文件落到对方ftp服务器 第三种一般跨网络同步 数据同步任务创建和执行监控          证券案例 ......
  • [redis 源码走读] - 跳跃表(skiplist)
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......