您不能,因为所有命令(包括 get)实际上都是在 exec 时执行的。在这种情况下,get 命令只返回一个未来对象,而不是实际值。
有两种方法可以实现这种交易。
使用 WATCH 子句
watch 子句用于防止并发更新。如果变量的值在 watch 和 multi 子句之间更新,则不会应用 multi 块中的命令。由客户决定再次尝试交易。
loop do
$redis.watch "foo"
val = $redis.get("foo")
if val == "bar" then
res = $redis.multi do |r|
r.set("foo", "baz")
end
break if res
else
$redis.unwatch "foo"
break
end
end
这里的脚本有点复杂,因为块的内容可以是空的,所以没有简单的方法可以知道交易是否被取消,或者它是否根本没有发生。当多块在所有情况下返回结果时通常更容易,除非事务被取消。
使用 Lua 服务器端脚本
使用 Redis 2.6 或更高版本,可以在服务器上执行 Lua 脚本。整个脚本的执行是原子的。它可以在 Ruby 中轻松实现:
cmd = <<EOF
if redis.call('get',KEYS[1]) == ARGV[1] then
redis.call('set',KEYS[1],ARGV[2] )
end
EOF
$redis.eval cmd, 1, "foo", "bar", "baz"
这通常比使用 WATCH 子句简单得多。