redis使用lua脚本限制用户1分钟内访问次数为10次

1、实现逻辑

记录用户每次的访问时间,因此对于每个用户,用列表类型的键记录他最近100次访问的时间。
如果键中的元素超过100个,就判断时间最早的元素距离现在的时间是否小于1分钟,如果是,则表示用户最近1分钟的访问次数超过100次,如果不是就将当前时间加入列表中,同时把最早的元素删除

2、LUA脚本

使用lua脚本实现,保证多个操作的“原子性”
参数说明:

  1. KEYS[1] 传入表示用户唯一标识的键
  2. ARGV[1] 传入限制的访问次数

lua脚本如下:

local len = redis.call('llen',KEYS[1]);
redis.replicate_commands(); -- 防止随机写入
local now = redis.call('TIME')[1]; -- 当前系统时间,单位是秒
if len < tonumber(ARGV[1]) then
   redis.call('lpush',KEYS[1],now);
   return 0;
else
    local lasttime = redis.call('lindex',KEYS[1],-1); -- 取最后一个元素
if now - lasttime < 60 then  -- 访问频率超过限制 ,这里的60是指60秒
   return -1; 
else -- 访问频率未超出限制
  redis.call('lpush',KEYS[1],now);
  redis.call('ltrim',KEYS[1],0,tonumber(ARGV[1])-1); -- 删除索引在[0,访问次数-1]以外的元素
  return 0;
 end;
end;

3、代码实现(java)

    /**
     * 执行lua脚本
     *
     * @param luaScript  lua脚本
     * @param keyParams  lua脚本中KEYS参数 key
     * @param argvParams lua脚本中ARGV参数 10
     */
Long result = redisTemplate.execute(
    RedisScript.of(luaScript, Long.class),
    Collections.singletonList(keyParams), 
    argvParams);
    //返回0表示未超过限制的条数 可继续发送
if(result == 0) {
    return true;
}
# redis  

评论

企鹅群:39438021

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×