为什么Redis会返回部分完成的事务



watch中使用multi的redis事务如下:

redis.watch('my-hash', 'my-normal-key', () => {
redis
.multi()
.hset('my-hash', 'hash-key-1', 1)
.hset('my-hash', 'hash-key-2', 2)
.set('my-normal-key', 'test', NX)
.exec((err, res) => {
// err is null
// res is an array with the results of the operations but only the set operation has a null res!
})
});

然后,我与运行上述命令的多个客户端进行高并发运行。我注意到,有时,当在另一个客户端中更改my-hashmy-normal-key时,exec命令中的res就是null。这是完全正确的,我能理解。

当事务成功执行时,res是以下形式的数组:

res = [
[null, 0],     // [err, res] for hset('my-hash', 'hash-key-1', 1)
[null, 0],     // [err, res] for hset('my-hash', 'hash-key-2', 2)
[null, 'OK'],  // [err, res] for set('my-normal-key', 'test', NX)
]

然而,在某些时候,res会返回一些看起来像部分故障的东西,比如:

res = [
[null, 0],
[null, 0],
[null, 0],
[null, null],   // the result of the set operation is null!
]

set操作的结果返回null,我认为这意味着另一个客户端已经进行了更改。但我无法模拟如何以这种方式返回结果。我在Redis的最终数据中看到,这确实完成了除了set操作之外的所有hset操作,这让我想知道一个事务怎么可能是部分的?

是什么原因导致了部分交易,它是如何发生的?有没有办法防止这种部分交易的发生?

我不认为这是部分事务问题。来自setnull结果意味着在事务开始时密钥已经存在并且没有被设置(因为NX标志(。

来自redis文档:

如果由于用户指定了NX或XX选项而未执行SET操作,但条件不满足,则返回Null批量回复

最新更新