Redis
 sql >> Database >  >> NoSQL >> Redis

Come posso leggere da Redis all'interno di un blocco MULTI in Ruby?

Non è possibile, poiché tutti i comandi (incluso get) vengono effettivamente eseguiti in fase di esecuzione. In questa situazione, il comando get restituisce solo un oggetto futuro, non il valore effettivo.

Esistono due modi per implementare tale transazione.

Utilizzo di una clausola WATCH

La clausola di controllo viene utilizzata per la protezione dagli aggiornamenti simultanei. Se il valore della variabile viene aggiornato tra la clausola watch e multi, i comandi nel blocco multi non vengono applicati. Spetta al cliente tentare la transazione un'altra volta.

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

Qui lo script è un po' complesso perché il contenuto del blocco può essere vuoto, quindi non c'è un modo semplice per sapere se la transazione è stata annullata o se non è avvenuta affatto. In genere è più facile quando i risultati del multiblocco restituiscono in tutti i casi tranne se la transazione viene annullata.

Utilizzo degli script Lua lato server

Con Redis 2.6 o superiore, gli script Lua possono essere eseguiti sul server. L'esecuzione dell'intero script è atomica. Può essere facilmente implementato in 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"

Questo è in genere molto più semplice rispetto all'utilizzo delle clausole WATCH.