Redis BITSET 和 WATCH
Redis BITSET and WATCH
我正在使用 Redis 创建一个算法,用于从一个范围内声明未使用的整数。我的解决方案基于我对 SO 问题的回答。
此解决方案使用 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 个不同的进程中为 N = 1..10
调用 SETBIT mykey, N, 1
的循环。
我发现 EXEC
从未返回 null,即使在监视的时间段内密钥肯定被另一个进程修改了。
问题:
WATCH
是否根本不支持基于 BIT 的 Redis 命令?
- 如果支持,为什么在这种情况下没有触发?我 testing/provoking 是不是写错了?据我了解,
WATCH
应该使 EXEC
失败,如果密钥已被修改 被另一个 client/connection 在观看的时间段内,并调用这来自 10 个不同的 Linux 进程,每个进程都创建自己的连接,似乎符合该要求?
- 在这种特殊情况下,
WATCH
和 MULTI
真的能提供什么吗? BITSET
returns 该位的先前值,因此不应该仅通过以下伪代码算法来保证原子性:
while (true) {
number = BITPOS mykey, 0
if (number > maxNumber) THROW ERROR
wasUsed = SETBIT mykey, number, 1
if (!wasUsed) {
return number
}
}
没有文档表明WATCH
不支持位设置命令。
你的代码在我看来是正确的,所以很难说为什么它不起作用。要进一步调查它,您必须提供 MCVE 而不是伪代码。然而...
你说的对,这里不需要事务,这个算法应该保证原子性。
我正在使用 Redis 创建一个算法,用于从一个范围内声明未使用的整数。我的解决方案基于我对
此解决方案使用 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 个不同的进程中为 N = 1..10
调用 SETBIT mykey, N, 1
的循环。
我发现 EXEC
从未返回 null,即使在监视的时间段内密钥肯定被另一个进程修改了。
问题:
WATCH
是否根本不支持基于 BIT 的 Redis 命令?- 如果支持,为什么在这种情况下没有触发?我 testing/provoking 是不是写错了?据我了解,
WATCH
应该使EXEC
失败,如果密钥已被修改 被另一个 client/connection 在观看的时间段内,并调用这来自 10 个不同的 Linux 进程,每个进程都创建自己的连接,似乎符合该要求? - 在这种特殊情况下,
WATCH
和MULTI
真的能提供什么吗?BITSET
returns 该位的先前值,因此不应该仅通过以下伪代码算法来保证原子性:
while (true) {
number = BITPOS mykey, 0
if (number > maxNumber) THROW ERROR
wasUsed = SETBIT mykey, number, 1
if (!wasUsed) {
return number
}
}
没有文档表明
WATCH
不支持位设置命令。你的代码在我看来是正确的,所以很难说为什么它不起作用。要进一步调查它,您必须提供 MCVE 而不是伪代码。然而...
你说的对,这里不需要事务,这个算法应该保证原子性。