我正在使用python包(redis-py)来操作redis数据库。我有一堆客户端在redis中设置哈希的键和值。我希望他们只在哈希存在时才设置键和值。如果哈希不存在,设置键和值将创建哈希,这不是我想要做的。
在redis-py页面(https://github.com/andymccurdy/redis-py)中,作者提出了一种在客户端进行原子操作的方法。所以我写了一个类似的功能:
with r.pipeline() as pipe:
while True:
try:
pipe.watch("a_hash")
if pipe.exists("a_hash"):
pipe.hset("a_hash", "key", "value")
break
except redis.WatchError:
continue
finally:
pipe.reset()
然而,这似乎不起作用。在我从另一个客户端删除哈希之后,这个哈希仍然是由这段代码创建的,所以我猜这段代码不是原子操作。有人可以帮我识别这段代码的问题吗?或者有更好的目标吗?
感谢您的帮助!
答案 0 :(得分:4)
我建议阅读Redis documentation中解释的WATCH / MULTI / EXEC块的定义。
在这样的块中,只有MULTI和EXEC之间的命令实际上是以原子方式处理的(并且有条件地根据手表使用全有或全无语义)。
在您的示例中,EXISTS和HSET命令不是以原子方式执行的。实际上,你不需要这种原子性:你想要的是条件执行。
这应该更好:
with r.pipeline() as pipe:
while True:
try:
pipe.watch("a_hash")
if pipe.exists("a_hash"):
pipe.multi()
pipe.hset("a_hash", "key", "value")
pipe.execute()
break
except redis.WatchError:
continue
finally:
pipe.reset()
如果在EXISTS之后但在MULTI之前删除了密钥,由于手表,HSET将不会被执行。
使用Redis 2.6,Lua server-side script可能更容易编写,效率更高。