1

我有一个巨大的键列表和一个值(所有键都相同),应该写入一个 redis 实例。仅当具有此键的条目已存在时,才会发生这种情况。

有一个MSETNX命令正在做相反的事情:当密钥不存在时输入条目。

当然,我可以通过EXIST之前检查并根据结果设置它,但是我如何确保这个 atomic. 由于这个列表可能非常庞大,我如何基于管道来做到这一点?

我正在使用redis-py作为包装器,并且服务器上没有可用的 Lua 脚本支持。

4

1 回答 1

3

这在没有 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 选择正确的值是流水线因子和并发交互风险之间的权衡。它不应该设置得太高。

于 2012-08-06T13:55:15.077 回答