使用redis命令'setex'设置过期时间在OpenResty中出现永久键

在OpenResty中使用lua脚本时,使用redis命令设置过期时间会出现永久键。 这是lua脚本:

local function ip_frequency(ip,red)
    local limit_num=50
    local key = "limit:frequency:"..ip
    local resp, err = red:get(key)
    if resp==nil then
        local ok,err=red:setex(key,2,1)
        if not ok then
            return false;
        end
    end

    if type(resp) == "string" then
        if tonumber(resp) > limit_num then
            return false
        end
    end

    ok, err = red:incr(key)
    if not ok then
        return false
    end
    return true
end

当OpenResty程序运行一段时间后,redis中会出现一些永久键。从这个函数可以看出,我没有设置永久时间的键,但它就是发生了。为什么,请帮我解答这个问题。谢谢!

软件版本如下:

  • OpenResty:1.17.8.2
  • Redis:6.0+
  • CentOS:8.0+
点赞
用户12918181
用户12918181

Openresty连接到redis数据库并使用其功能。在lua或其他语言中使用redis函数是不原子的。对于redis服务器而言,意思是: [redis:get,暂停,redis:setex] 或 [redis:get,暂停,redis:incr]。在暂停期间可能会发生很多事情,即使只有1毫秒,例如清理“死”键。

以下是您的代码可能遇到的情况:

  • local resp, err = red:get(key)
  • 您获得小于limit_num的有效键值
  • ok, err = red:incr(key)
  • Redis检查键是否有效,并在达到ttl时删除它
  • Redis检查是否没有这样的键,因此创建键,值为0并递增键值

因此,在这一点上,您拥有永久键。如果要避免永久键,请像这样使用:red:setex(key,2,tonumber(res)+1)而不是red:incr(key)

2020-11-20 11:41:31