我有一个巨大的键列表和一个值(所有键都相同),应该写入一个 redis 实例。仅当具有此键的条目已存在时,才会发生这种情况。
有一个MSETNX命令正在做相反的事情:当密钥不存在时输入条目。
当然,我可以通过EXIST之前检查并根据结果设置它,但是我如何确保这个 atomic. 由于这个列表可能非常庞大,我如何基于管道来做到这一点?
我正在使用redis-py作为包装器,并且服务器上没有可用的 Lua 脚本支持。
我有一个巨大的键列表和一个值(所有键都相同),应该写入一个 redis 实例。仅当具有此键的条目已存在时,才会发生这种情况。
有一个MSETNX命令正在做相反的事情:当密钥不存在时输入条目。
当然,我可以通过EXIST之前检查并根据结果设置它,但是我如何确保这个 atomic. 由于这个列表可能非常庞大,我如何基于管道来做到这一点?
我正在使用redis-py作为包装器,并且服务器上没有可用的 Lua 脚本支持。
这在没有 Lua 的情况下不太方便,但仍然可以使用 WATCH/MULTI/EXEC 命令完成。这个想法是将您的巨大键列表划分为 n 个项目的块(例如 n = 20),然后将以下函数应用于每个块:
def process_block( redis_client, block, value ):
with redis_client.pipeline() as pipe:
while True:
try:
pipe.watch( block )
to_set = [ for x in block if pipe.exists(x) ]
if to_set:
pipe.multi()
for x in to_set:
pipe.set( x, value )
pipe.execute()
break
except redis.WatchError:
continue
finally:
pipe.reset()
原子性由 WATCH/MULTI/EXEC 命令保证,您将流水线化 1 个 WATCH、1 个 MULTI、最多 n 个 SET 和 1 个 EXEC 命令。不过,您将支付 EXISTS 往返费用。为 n 选择正确的值是流水线因子和并发交互风险之间的权衡。它不应该设置得太高。