基于redis lua的一种限流算法
一、构造lua脚本
二、执行、传参,keys参数为List,其它后面的参数组成一个数组。
三、解释
keys是数组,KEYS[2]是第2个参数(下标从1开始)。
ARGV[1]当前时间,ARGV[2]限制时间 即,ARGV[1]-ARGV[2] 当前时间-限制时间,即1分钟(限制时间)以前的以limit_result_nums为key的值都删除。
ZREMRANGEBYSCORE key min max 删除key下的得分为min到max之间的值
ZCARD 获取有序集合的成员数
如果成员数小于限制数(limitSize),则增加(ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数),KEYS[2]是key(limit_result_nums),keys[1]是uuid即member,ARGV[1]是date即当前值score。
最后,返回成员数(添加前的)。
如果返回成员数小于限制数,则返回uuid,否则返回空。空就是获取令牌失败,非空则成功。
拿到令牌,才回传结果,以避免回传并发大,让服务器压力过大。
四、复述,总结
窗口为限制时间内,如果限制时间内监测点成员过多,限流。控制参数有两种时间窗口与窗口内成员数量。
要调小并发数,那么增加时间窗口(相当于在线终端变多,更容易达到限制数量)或者减小数量都行。
要调大并发数,那么减小时间窗口(相当于在线终端变小,更难达到限制数量)或者减大数量都行。
文/程忠 浏览次数:0次 2023-11-23 17:03:43
public String buildLuaScript() { StringBuilder lua = new StringBuilder(); lua.append("local c"); lua.append("\n redis.call('ZREMRANGEBYSCORE', KEYS[2], 0, ARGV[1] - ARGV[2])"); lua.append("\n c = redis.call('ZCARD', KEYS[2])"); lua.append("\n if tonumber(c) < tonumber(ARGV[3]) then"); lua.append("\n redis.call('zadd', KEYS[2], ARGV[1], KEYS[1])"); lua.append("\n end"); lua.append("\n return c;"); return lua.toString(); }
二、执行、传参,keys参数为List,其它后面的参数组成一个数组。
String luaScript = buildLuaScript(); RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class); Long date = System.currentTimeMillis() / SEC; ArrayList<String> keys = new ArrayList<>(); String uuid = UUID.randomUUID().toString().replaceAll("-", ""); keys.add(uuid); keys.add("limit_result_nums"); Number execute = redisTemplateString.execute(redisScript, keys, date, limitExpire, limitSize); if (execute.longValue() < limitSize) { return uuid; } return null;
三、解释
keys是数组,KEYS[2]是第2个参数(下标从1开始)。
ARGV[1]当前时间,ARGV[2]限制时间 即,ARGV[1]-ARGV[2] 当前时间-限制时间,即1分钟(限制时间)以前的以limit_result_nums为key的值都删除。
ZREMRANGEBYSCORE key min max 删除key下的得分为min到max之间的值
ZCARD 获取有序集合的成员数
如果成员数小于限制数(limitSize),则增加(ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数),KEYS[2]是key(limit_result_nums),keys[1]是uuid即member,ARGV[1]是date即当前值score。
最后,返回成员数(添加前的)。
如果返回成员数小于限制数,则返回uuid,否则返回空。空就是获取令牌失败,非空则成功。
拿到令牌,才回传结果,以避免回传并发大,让服务器压力过大。
四、复述,总结
窗口为限制时间内,如果限制时间内监测点成员过多,限流。控制参数有两种时间窗口与窗口内成员数量。
要调小并发数,那么增加时间窗口(相当于在线终端变多,更容易达到限制数量)或者减小数量都行。
要调大并发数,那么减小时间窗口(相当于在线终端变小,更难达到限制数量)或者减大数量都行。
相关阅读
评论:
↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑