How to set hash key expiration in redis according

2019-08-23 07:37发布

问题:

I would like to set the expiration of some hash keys, and if it is the first time to hset the key, I wish to set an expiration, other wise, I prefer to keep the expiration that is set at the first time.

Since there are huge of hash keys, I prefer to do it in pipeline, however the function below not works well.

The line pipe.exists(hkey) return an obj of pipe, which is always True, so the if clause always go to one part regardless of the existence of the hash key.

And my question is: is there a method to set the expiration of a hash key according to the existence of the hash key with pipeline?

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:

You CANNOT achieve that with pipeline, since you never know whether the key is existed until the whole pipeline has been executed. Instead, you can use Lua scripting to do the job:

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

Check this to see how to run Lua script with redis-py. Then run the script with pipeline to reduce the RTT.

UPDATE

If you insist on using WATCH to do the job, you can try the following code:

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


标签: python redis