使用GET和INCR在Redis中实现乐观锁定

4 投票
1 回答
1481 浏览
提问于 2025-04-18 06:31

我想要“乐观地锁定”一段代码。 伪代码如下:

revision = GET('lock_key') # default as 0
{
<<block of code>>
}
new_revision = INCR('lock_key')
if new_revision != revision + 1:
    raise Exception # now retry or whatever

我觉得这样做没问题,因为INCR和GET都是原子操作。 你觉得这种方法有什么问题吗?

1 个回答

5

这种方法有几个问题。首先,当工作者数量超过2个时,它的表现就不好了,因为速度快的工作者会让速度慢的工作者“饿肚子”。其次,这个流程缺乏原子性,这可能会导致问题,具体要看你运行的逻辑,但竞争条件是很麻烦的。最后,这里还有一点类似于观察者效应,因为你总是在增加key_lock的值。

一个更好的方法是使用Redis的MULTIEXECWATCH。Redis的事务主题对此进行了很好的讨论,并提供了一个基于你伪代码的示例:

WATCH('lock_key')
revision = GET('lock_key') # default as 0
{
    <<block of code>>
}

MULTI()
new_revision = INCR('lock_key')
if EXEC() is None:
  raise Exception # now retry or whatever

撰写回答