如何根据密钥的存在性在Redis中设置哈希密钥过期

时间:2018-06-27 10:16:38

标签: python redis

我想设置一些哈希键的过期时间,如果是第一次设置该键,我希望设置一个过期时间,否则,我宁愿保留第一次设置的过期时间

由于有大量的哈希键,所以我更喜欢在管道中进行操作,但是下面的功能不能很好地工作。

pipe.exists(hkey)行返回管道的obj,该对象始终为True,因此,无论是否存在哈希键,if子句总是只包含一部分。

我的问题是:是否有一种方法可以根据带有管道的哈希密钥的存在来设置哈希密钥的到期时间?

def test1(hkey, v):
    with r.pipeline() as pipe:
        # tmp = pipe.exists(hkey)
        # pipe.exists(hkey) is a pipe obj, which is always True, 
        # this line not work as expected and the two lines below it will never be excuted.
        if not pipe.exists(hkey):
            pipe.hset(hkey, v, v)
            pipe.expire(hkey, 3600)
        else:
            # no matter whether the hash key is exist or not, the if else statment always goes to this line.
            pipe.hset(hkey, v, v)
        pipe.execute()

1 个答案:

答案 0 :(得分:2)

您无法使用管道实现这一目标,因为直到执行完整个管道后,您才知道密钥是否存在。相反,您可以使用Lua scripting来完成这项工作:

local key = KEYS[1]
local field = ARGV[1]
local value = ARGV[2]
local ttl = ARGV[3]

local exist = redis.call('exists', key)

redis.call('hset', key, field, value)

if exist == 0 then
    redis.call('expire', key, ttl)
end

选中this,了解如何使用redis-py运行Lua脚本。然后使用管道运行脚本以减少RTT

更新

如果您坚持使用WATCH来完成这项工作,则可以尝试以下代码:

with r.pipeline() as pipe:
    while 1:
        try:
            pipe.watch(hkey)

            exist = pipe.exists(hkey)

            pipe.multi()

            if not exist:
                pipe.hset(hkey, v, v)
                pipe.expire(hkey, 3600)
            else:
                pipe.hset(hkey, v, v)

            pipe.execute()
            break;
        except WatchError:
            continue