Nemůžete, protože všechny příkazy (včetně get) jsou ve skutečnosti prováděny v době provádění. V této situaci vrací příkaz get pouze budoucí objekt, nikoli skutečnou hodnotu.
Existují dva způsoby, jak takovou transakci implementovat.
Použití klauzule WATCH
Klauzule sledování se používá k ochraně před souběžnými aktualizacemi. Pokud je hodnota proměnné aktualizována mezi klauzulí watch a multi, příkazy v bloku multi se nepoužijí. Je na klientovi, zda se o transakci pokusí jindy.
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
Zde je skript trochu složitý, protože obsah bloku může být prázdný, takže není jednoduchý způsob, jak zjistit, zda byla transakce zrušena, nebo zda vůbec neproběhla. Obecně je jednodušší, když multiblok vrací výsledky ve všech případech kromě případů, kdy je transakce zrušena.
Použití skriptování na straně serveru Lua
S Redis 2.6 nebo lepším lze na serveru spouštět skripty Lua. Provedení celého scénáře je atomické. Lze jej snadno implementovat v 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"
To je obvykle mnohem jednodušší než použití klauzulí WATCH.