Redis 有序集上的 ZREM

ZREM on Redis Sorted Set

如果 2 个 worker 同时对有序集合的同一个元素调用 ZREM 会发生什么?对于实际删除元素的工人来说 return 是真的,而对另一个工人来说是假的,表明它不存在,还是对两者都是 return 真的?换句话说,ZREM 在内部是原子的吗?

Redis(大部分)是单线程的,所以它的所有操作都是原子的,ZREM 也不例外。但是,您的问题实际上是关于以原子方式执行 "ZPOP",因此有两种可能的方法可以做到这一点。

选项 1:WATCH/MULTI/EXEC

在伪代码中,这是乐观交易的样子:

:start
WATCH somekey
member = ZREVRANGE somekey 0 0
MULTI
ZREM somekey member
if not EXEC goto :start // or quit trying

选项 2:Lua 脚本

zpop.lua:

local member = redis.call('ZREVRANGE', KEYS[1], 0, 0)
return redis.call('ZREM', KEYS[1], member)

redis-cli --eval zpop.lua somekey

注意 - 原子性的重要性 如果您决定不使用这些确保原子性的机制,您 运行 会比您想象的更快陷入问题。这是一种可能的情况:

Process A                Redis Server            Process B
ZREVRANGE ------------>
          <------------- foo
                                      <--------- ZADD +inf bar
                                   OK --------->
ZREM foo -------------->
         <-------------- 1

在上面的示例中,在 A 获取 foo 之后,B 以高得离谱的分数插入 bar,因此它成为集合中的顶部元素。但是,A 将继续并删除以前位于顶部的 foo。