使用 Redis,我想执行命令的原子序列,即我需要保证在执行序列时没有其他客户端将在数据库中执行更改。
如果我只使用write命令,我可以使用MULTI
andEXEC
语句来确保使用事务的原子性。但是,我也想在我的事务中使用读取命令。因此我不能使用MULTI
,因为读取命令也在排队!
基本上,以原子方式,我需要执行以下操作:
x
从数据库中读取,- 基于
x
,存储f(x)
到数据库。
1. 和 2. 都应该是单个原子事务的一部分。
有没有简单的方法可以做到这一点?
使用 Redis,我想执行命令的原子序列,即我需要保证在执行序列时没有其他客户端将在数据库中执行更改。
如果我只使用write命令,我可以使用MULTI
andEXEC
语句来确保使用事务的原子性。但是,我也想在我的事务中使用读取命令。因此我不能使用MULTI
,因为读取命令也在排队!
基本上,以原子方式,我需要执行以下操作:
x
从数据库中读取,x
,存储f(x)
到数据库。1. 和 2. 都应该是单个原子事务的一部分。
有没有简单的方法可以做到这一点?
您的问题有两个很好的解决方案。
选项1:
您需要WATCH
在正在读取的密钥上发出 a 。您的交易将如下所示:
WATCH x
x = GET x
MULTI
SET y, f(x)
EXEC
在这个例子中,multi 块内的写命令将被原子地执行,但前提是key 的值在被调用后x
没有改变。WATCH
这称为乐观锁。如果 的值x
确实发生了变化,您的应用程序将出现错误,并且需要决定下一步该做什么,这可能会使用 的新值再次尝试x
。
选项 2:
Redis 现在支持 lua 脚本,lua 脚本是原子执行的。如果您可以将您的逻辑封装到一个 lua 脚本中,您就可以读取您的密钥、运行您的f(x)
逻辑并存储结果,所有这些都是原子的。根据您正在执行的逻辑,这可能很棘手,甚至是不可选择的。您甚至可能不得不通过将值直接硬编码到您希望 redis 执行的脚本中来进行丑陋的 hack,例如将值传递给 lua。也就是说,如果你让它工作,这个方法应该是可靠和高性能的,你不必处理处理EXEC
失败。