小编典典

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

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()

阅读 296

收藏
2020-06-20

共1个答案

小编典典

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

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

选中此项以查看如何使用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
2020-06-20