使用Redis,我想执行一个原子序列的命令,即我需要保证在执行序列时没有其他客户端会在数据库中执行更改。
如果我只使用编写命令,我可以使用MULTI
和EXEC
语句来确保使用事务的原子性。但是,我还想在我的交易中使用读取命令。因此我不能使用MULTI
,因为读命令也在排队!
基本上,以原子方式,我需要做以下事情:
x
x
,将f(x)
存储到数据库中。1.和2.应该是单个原子事务的一部分。
有一种简单的方法可以做到吗?
答案 0 :(得分:10)
您的问题有两个很好的解决方案。
选项1:
您需要在正在阅读的密钥上发出WATCH
。您的交易看起来像这样:
WATCH x
x = GET x
MULTI
SET y, f(x)
EXEC
在此示例中,多块内的写命令将以原子方式执行,但如果自调用x
后键WATCH
的值未发生更改,则仅。这称为乐观锁。如果x
的值确实发生了变化,那么您的应用程序将会出现错误,需要决定下一步该做什么,这可能会使用x
的新值重新尝试。
选项2:
Redis现在支持lua脚本,lua脚本以原子方式执行。如果您可以将逻辑封装到lua脚本中,则可以读取密钥,运行f(x)
逻辑,并以原子方式存储结果。根据您正在执行的逻辑,这可能很棘手甚至是非选项。您甚至可能必须通过将它们直接硬编码到您希望redis执行的脚本中来执行丑陋的黑客操作,例如将值传递给lua。也就是说,如果你使用它,这个方法应该是可靠和高效的,而且你不必处理EXEC
失败的处理。