【问题标题】:How to set hash key expiration in redis according to the existance of the keyredis中如何根据key的存在设置hash key过期时间
【发布时间】:2018-12-06 04:46:00
【问题描述】:

我想设置一些hash key的过期时间,如果是第一次hset key,我希望设置一个过期时间,否则我宁愿保留第一次设置的过期时间.

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

pipe.exists(hkey)这行返回一个管道的obj,它总是True,所以if子句总是去一个部分,不管hash key是否存在。

我的问题是:有没有一种方法可以通过管道的哈希键的存在来设置哈希键的到期?

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

【问题讨论】:

    标签: python redis


    【解决方案1】:

    您无法通过管道实现这一点,因为在整个管道执行之前您永远不知道密钥是否存在。相反,您可以使用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
    

    【讨论】:

    • 您好,感谢您的帮助,但我还有 2 个问题,您能否分享更多建议? 1. Lua 在并发的时候能很好地工作吗?我得到一些信息,当 Lua 的脚本正在使用时,没有其他东西可以同时运行,对吗? 2.使用watch()怎么样?我的意思是, pipe.watch(hkey); pipe.exists(hkey);管道.unwatch();然后,其他部分。我在笔记本电脑上对其进行了测试,它可以工作,但坏消息是使用 WATCH 时,每个 pipe.exists() 都需要花费时间来连接并从 redis 服务器获取结果。所以,我的问题是:以这种方式使用 WATCH 是否有风险,而不是在交易中?
    • 1. Lua 脚本的工作方式与其他命令相同。 Redis 以原子方式运行它们。 2. AFAIK,您的WATCH 解决方案无法正常工作。它和管道有同样的问题:在管道或事务完成之前,你永远不知道存在的结果。
    • 嗨,for_stack,非常感谢您的回复,还有一个问题,我从here 找到了一个示例,并且有一种方法可以在使用 WATCH 的管道期间获得结果,它似乎可以在管道期间获取值,因为 WATCH 将管道置于立即执行模式?
    • 对不起,我弄错了。您可以使用WATCH 来完成这项工作。请查看我的答案的更新。
    • 没有。 WATCHMULTI 一起使用。否则,您将获得比赛条件。比如说,你观察一把钥匙,并测试它的存在。如果密钥已经存在,则尝试HSET 哈希而不设置过期时间。但是,在您这样做之前,密钥已被其他客户端删除或刚刚过期。然后您将设置密钥没有任何过期,并且密钥永远存在。
    猜你喜欢
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2020-11-28
    • 2021-04-12
    相关资源
    最近更新 更多