我正在使用Redis创建一种算法来声明某个范围内未使用的整数。
此解决方案使用BITPOS和BITSET,并且为了避免出现竞争情况,我也使用WATCH/ MULTI/ EXEC。为了测试并发方面,我创建了一个bash脚本,该脚本同时尝试并行查找10个空闲数字,以调查EXEC命令的可能结果。
BITPOS
BITSET
WATCH
MULTI
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 }
也是一个循环调用SETBIT mykey, N, 1的N = 1..10,在10个不同的进程。
SETBIT mykey, N, 1
N = 1..10
我发现EXEC,即使在监视的时间内肯定由另一个进程修改了密钥,也永远不会返回null。
问题:
while (true) { number = BITPOS mykey, 0 if (number > maxNumber) THROW ERROR wasUsed = SETBIT mykey, number, 1 if (!wasUsed) { return number } }
没有文档表明WATCH不支持位设置命令。
您的代码对我来说看起来很正确,因此很难说出为什么它不起作用。为了进一步研究它,您必须提供MCVE而不是伪代码。然而…
是的,这里不需要事务,此算法应保证原子性。