Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Wie kann ich in Ruby aus Redis in einem MULTI-Block lesen?

Sie können dies nicht, da alle Befehle (einschließlich get) tatsächlich zur Ausführungszeit ausgeführt werden. In dieser Situation gibt der get-Befehl nur ein zukünftiges Objekt zurück, nicht den tatsächlichen Wert.

Es gibt zwei Möglichkeiten, eine solche Transaktion zu implementieren.

Eine WATCH-Klausel verwenden

Die Überwachungsklausel dient zum Schutz vor gleichzeitigen Aktualisierungen. Wenn der Wert der Variablen zwischen der Überwachungs- und der Multi-Klausel aktualisiert wird, werden die Befehle im Multi-Block nicht angewendet. Es obliegt dem Client, die Transaktion ein weiteres Mal zu versuchen.

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

Hier ist das Skript etwas komplex, da der Inhalt des Blocks leer sein kann, sodass es keine einfache Möglichkeit gibt, festzustellen, ob die Transaktion abgebrochen wurde oder ob sie überhaupt nicht stattgefunden hat. Im Allgemeinen ist es einfacher, wenn der Multiblock in allen Fällen Ergebnisse zurückgibt, außer wenn die Transaktion abgebrochen wird.

Serverseitiges Lua-Scripting verwenden

Ab Redis 2.6 können Lua-Skripte auf dem Server ausgeführt werden. Die Ausführung des gesamten Skripts ist atomar. Es kann einfach in Ruby implementiert werden:

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"

Dies ist normalerweise viel einfacher als die Verwendung von WATCH-Klauseln.