Redis BITSET和WATCH

时间:2019-02-07 08:01:08

标签: concurrency redis watch bitset

我正在使用Redis创建一个算法来声明某个范围内未使用的整数。我的解决方案基于我对this这样的问题的答案。

此解决方案使用BITPOSBITSET,为了避免出现竞争情况,我还使用了WATCH / MULTI / EXEC。为了测试并发方面,我创建了一个bash脚本,该脚本同时尝试并行查找10个空闲数字,以调查EXEC命令的可能结果。

我发现EXEC从未返回null,即使监视的密钥已被另一个客户端修改也是如此。我添加了一些延迟,以便有足够的时间来激发应该触发监视机制的并发修改,以使EXEC失败,但是并没有。

所以基本上我有这段代码:

while (true) {
  WATCH mykey
  number = BITPOS mykey, 0
  if (number > maxNumber) THROW ERROR

  (deliberate delay)

  MULTI
  SETBIT mykey, number, 1
  if EXEC != null return number
}

,还有一个循环,它在10个不同的进程中为SETBIT mykey, N, 1调用N = 1..10

我发现EXEC从未返回null,即使在观察的时间内肯定由另一个进程修改了密钥。

问题:

  1. 基于BIT的Redis命令是否仅不支持WATCH
  2. 如果支持,为什么在这种情况下不触发它?我是否在错误地测试/挑衅?据我了解,如果密钥在观看的时间内已被另一个客户端/连接修改,并从10个不同的Linux调用,WATCH应该使EXEC失败各自创建自己的连接的流程似乎符合该要求?
  3. 在这种情况下,WATCHMULTI实际上提供了什么吗? BITSET返回该位的先前值,因此不应仅通过以下伪代码算法来保证原子性:
    while (true) {
      number = BITPOS mykey, 0
      if (number > maxNumber) THROW ERROR

      wasUsed = SETBIT mykey, number, 1

      if (!wasUsed) {
        return number
      }
    }

1 个答案:

答案 0 :(得分:1)

  1. 没有文档表明WATCH不支持位设置命令。

  2. 您的代码对我来说似乎很正确,因此很难说为什么它不起作用。为了进一步研究它,您必须提供MCVE而不是伪代码。但是...

  3. 是的,这里不需要事务,此算法应保证原子性。