【问题标题】:Redis BITSET and WATCHRedis BITSET 和 WATCH
【发布时间】:2019-02-07 21:14:24
【问题描述】:

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

这个解决方案使用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 个不同进程中为 N = 1..10 调用 SETBIT mykey, N, 1 的循环。

我发现EXEC 从未返回 null,即使在监视的时间段内该密钥确实被另一个进程修改了。

问题:

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

      wasUsed = SETBIT mykey, number, 1

      if (!wasUsed) {
        return number
      }
    }

【问题讨论】:

    标签: concurrency redis watch bitset


    【解决方案1】:
    1. 没有文档表明WATCH 不支持位设置命令。

    2. 您的代码在我看来是正确的,所以很难说它为什么不起作用。要进一步调查它,您必须提供 MCVE 而不是伪代码。不过……

    3. 你说得对,这里不需要事务,这个算法应该保证原子性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-26
      • 2021-02-17
      • 1970-01-01
      • 2018-11-15
      • 2012-12-11
      • 2013-03-24
      • 2021-12-08
      • 1970-01-01
      相关资源
      最近更新 更多