Redis中的事务与读操作

8
使用Redis,我想执行一系列原子命令,即在执行该序列期间,我需要确保没有其他客户端对数据库进行更改。
如果我只使用写入命令,我可以使用MULTI和EXEC语句使用事务来确保原子性。但是,我还想在我的事务中使用读取命令。因此,我不能使用MULTI,因为读取命令也在排队!
基本上,在原子方式下,我需要执行以下操作:
1.从数据库中读取x,
2.根据x,将f(x)存储到数据库中。
1和2都应该是单个原子事务的一部分。
有没有简单的方法来做到这一点?

你可以尝试使用Lua脚本:http://redis.io/commands/eval - OZ_
1个回答

16

你的问题有两个好的解决方案。

选项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执行的脚本中那样进行丑陋的黑客攻击。话虽如此,如果您使其正常工作,此方法应该是可靠和高效的,而且您无需处理EXEC失败。

选项1非常适合我的需求,因为迭代重试操作似乎是一个合理的解决方案。目前,我的应用程序逻辑与我提供的示例相比要复杂得多,但我一定会看看Lua。非常感谢! - Tregoreg
如果读操作基于先前写操作的结果,例如rpush返回列表长度,如果长度大于某个阈值,则需要从另一个键中读取,然后再进行一些写操作...所有这些操作都在一个事务内部。 - pplorins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接