作者热门文章
- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我在 MULTI 事务中封装了一组复杂的 Redis 命令,但事务中的逻辑取决于 Redis 中已有的值。但是事务中的所有读取似乎都返回 nil
这是一个演示问题的示例:
[Dev]> $redis.set("foo", "bar")
=> "OK"
[Dev]> $redis.multi{ $redis.set("foo", "baz") if $redis.get("foo") == "bar" }
=> ["bar"]
[Dev]> $redis.get("foo")
=> "bar"
显然,我希望最后的返回值是 'baz'
– 我该如何实现?
最佳答案
你不能,因为所有命令(包括 get)实际上都是在执行时执行的。在这种情况下,get 命令只返回一个 future 的对象,而不是实际值。
有两种方法可以实现这种交易。
使用 WATCH 子句
watch 子句用于防止并发更新。如果变量的值在 watch 和 multi 子句之间更新,则不会应用 multi block 中的命令。由客户再次尝试交易。
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
这里的脚本有点复杂,因为 block 的内容可以为空,所以没有简单的方法可以知道交易是否已被取消,或者是否根本没有发生。当多 block 在所有情况下返回结果时通常更容易,除非交易被取消。
使用 Lua 服务器端脚本
使用 Redis 2.6 或更高版本,Lua scripts can be executed on the server .整个脚本的执行是原子的。它可以很容易地用 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 子句简单得多。
关于ruby - 如何从 Ruby 中的 MULTI block 中的 Redis 读取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11300958/
我是一名优秀的程序员,十分优秀!