qkh*_*hly 5 python atomic redis
我正在使用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()
Run Code Online (Sandbox Code Playgroud)
然而,这似乎不起作用。当我从另一个客户端删除哈希后,该哈希仍然是由这段代码创建的,所以我猜这段代码不是原子操作。有人可以帮我确定这段代码有什么问题吗?或者有没有更好的方法来达到这个目的?
感谢你的帮助!
我建议阅读Redis 文档中解释的 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()
Run Code Online (Sandbox Code Playgroud)
如果在 EXISTS 之后但在 MULTI 之前删除该键,则 HSET 将不会被执行,这要归功于手表。
使用 Redis 2.6,Lua 服务器端脚本可能更容易编写,而且效率更高。