すべてのコマンド(getを含む)は実際には実行時に実行されるため、できません。この状況では、getコマンドは実際の値ではなく、将来のオブジェクトのみを返します。
このようなトランザクションを実装するには、2つの方法があります。
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句を使用するよりもはるかに簡単です。