使用 GET 和 INCR 对 redis 进行乐观锁定

Posted

技术标签:

【中文标题】使用 GET 和 INCR 对 redis 进行乐观锁定【英文标题】:Optimistic locking with redis using GET and INCR 【发布时间】:2014-07-02 10:19:36 【问题描述】:

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

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】:

这种方法存在一些问题。首先,它不会远远超过 2 名工人,因为速度越快的工人会饿死越慢。流程也缺乏原子性,这可能是也可能不是问题,具体取决于您正在运行的逻辑,但竞争条件很糟糕。最后,这里有一点 observer effect 的作用,因为你总是在 INCRing key_lock。

更好的方法是使用 Redis 的 MULTI、EXEC 和 WATCH。 Redis 的transactions topic 非常巧妙地讨论了这一点,并根据您的伪代码提供了以下示例:

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

【讨论】:

&lt;&lt;block of code&gt;&gt;不应该在MULTIEXEC之间,WATCHMULTI之间不应该什么都没有吗? 不,OP没有说明block里面有Redis操作

以上是关于使用 GET 和 INCR 对 redis 进行乐观锁定的主要内容,如果未能解决你的问题,请参考以下文章

Python操作Redis

Redis各种数据类型的应用场景

redis支持哪些数据类型?redis命令大全

Redis通过getset和incr实现复位操作计数器

redis加锁

redis 实现锁