我正在使用Redis创建一个算法来声明某个范围内未使用的整数。我的解决方案基于我对this这样的问题的答案。
此解决方案使用BITPOS
和BITSET
,为了避免出现竞争情况,我还使用了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,即使在观察的时间内肯定由另一个进程修改了密钥。
问题:
WATCH
?WATCH
应该使EXEC
失败各自创建自己的连接的流程似乎符合该要求?WATCH
和MULTI
实际上提供了什么吗? BITSET
返回该位的先前值,因此不应仅通过以下伪代码算法来保证原子性: while (true) {
number = BITPOS mykey, 0
if (number > maxNumber) THROW ERROR
wasUsed = SETBIT mykey, number, 1
if (!wasUsed) {
return number
}
}
答案 0 :(得分:1)
没有文档表明WATCH
不支持位设置命令。
您的代码对我来说似乎很正确,因此很难说为什么它不起作用。为了进一步研究它,您必须提供MCVE而不是伪代码。但是...
是的,这里不需要事务,此算法应保证原子性。