X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/46b614edf7522e2bf8d3512fab347a9c9d4a1d70..12ebe2ac17a26ecf263f90b2acdf03db29b00223:/doc/MultiExecCommand.html diff --git a/doc/MultiExecCommand.html b/doc/MultiExecCommand.html index e0a41983..65ec67a0 100644 --- a/doc/MultiExecCommand.html +++ b/doc/MultiExecCommand.html @@ -16,7 +16,7 @@
-MultiExecCommand: Contents
  MULTI
  COMMAND_1 ...
  COMMAND_2 ...
  COMMAND_N ...
  EXEC or DISCARD
    Usage
    The DISCARD command
    Return value +MultiExecCommand: Contents
  WATCH key1 key2 ... keyN (Redis >
  UNWATCH
  MULTI
  COMMAND_1 ...
  COMMAND_2 ...
  COMMAND_N ...
  EXEC or DISCARD
    Usage
    The DISCARD command
    Check and Set (CAS) transactions using WATCH
    WATCH explained
    WATCH used to implement ZPOP
    Return value

MultiExecCommand

@@ -26,15 +26,21 @@
- #sidebar GenericCommandsSidebar

MULTI

+ #sidebar GenericCommandsSidebar

WATCH key1 key2 ... keyN (Redis >

2.1.0)= +

UNWATCH

+

MULTI

COMMAND_1 ...

COMMAND_2 ...

COMMAND_N ...

-

EXEC or DISCARD

MULTI, EXEC and DISCARD commands are the fundation of Redis Transactions.A Redis Transaction allows to execute a group of Redis commands in a singlestep, with two important guarantees:
- -

Usage

A Redis transaction is entered using the MULTI command. The command alwaysreplies with OK. At this point the user can issue multiple commands. Insteadto execute this commands Redis will "queue" them. All the commands areexecuted once EXEC is called.
-
Calling DISCARD instead will flush the transaction queue and will exitthe transaction.
-
The following is an example using the Ruby client:
+

EXEC or DISCARD

MULTI, EXEC, DISCARD and WATCH commands are the fundation of Redis Transactions. +A Redis Transaction allows the execution of a group of Redis commands in a single +step, with two important guarantees:

+Since Redis 2.1.0, it's also possible to add a further guarantee to the above two, in the form of optimistic locking of a set of keys in a way very similar to a CAS (check and set) operation. This is documented later in this manual page.

Usage

A Redis transaction is entered using the MULTI command. The command always +replies with OK. At this point the user can issue multiple commands. Instead +to execute this commands Redis will "queue" them. All the commands are +executed once EXEC is called.

Calling DISCARD instead will flush the transaction queue and will exit +the transaction.

The following is an example using the Ruby client: +
 ?> r.multi
 => "OK"
 >> r.incr "foo"
@@ -46,9 +52,14 @@
 >> r.exec
 => [1, 1, 2]
 
-
As it is possible to see from the session above, MULTI returns an "array" ofreplies, where every element is the reply of a single command in thetransaction, in the same order the commands were queued.
-
When a Redis connection is in the context of a MULTI request, all the commandswill reply with a simple string "QUEUED" if they are correct from thepoint of view of the syntax and arity (number of arguments) of the commaand.Some command is still allowed to fail during execution time.
-
This is more clear if at protocol level: in the following example one commandwill fail when executed even if the syntax is right:
+As it is possible to see from the session above, MULTI returns an "array" of
+replies, where every element is the reply of a single command in the
+transaction, in the same order the commands were queued.

When a Redis connection is in the context of a MULTI request, all the commands +will reply with a simple string "QUEUED" if they are correct from the +point of view of the syntax and arity (number of arguments) of the commaand. +Some command is still allowed to fail during execution time.

This is more clear if at protocol level: in the following example one command +will fail when executed even if the syntax is right: +
 Trying 127.0.0.1...
 Connected to localhost.
 Escape character is '^]'.
@@ -64,16 +75,21 @@ EXEC
 +OK
 -ERR Operation against a key holding the wrong kind of value
 
-
MULTI returned a two elements bulk reply in witch one of this is a +OKcode and one is a -ERR reply. It's up to the client lib to find a sensibleway to provide the error to the user.
-
IMPORTANT: even when a command will raise an error, all the other commandsin the queue will be processed. Redis will NOT stop the processing ofcommands once an error is found.
-
Another example, again using the write protocol with telnet, shows howsyntax errors are reported ASAP instead:
+MULTI returned a two elements bulk reply in witch one of this is a +OK
+code and one is a -ERR reply. It's up to the client lib to find a sensible
+way to provide the error to the user.

IMPORTANT: even when a command will raise an error, all the other commandsin the queue will be processed. Redis will NOT stop the processing ofcommands once an error is found.
+Another example, again using the write protocol with telnet, shows how +syntax errors are reported ASAP instead: +
 MULTI
 +OK
 INCR a b c
 -ERR wrong number of arguments for 'incr' command
 
-
This time due to the syntax error the "bad" INCR command is not queuedat all.
-

The DISCARD command

DISCARD can be used in order to abort a transaction. No command will beexecuted, and the state of the client is again the normal one, outsideof a transaction. Example using the Ruby client:
+This time due to the syntax error the "bad" INCR command is not queued
+at all.

The DISCARD command

DISCARD can be used in order to abort a transaction. No command will be +executed, and the state of the client is again the normal one, outside +
of a transaction. Example using the Ruby client:
 ?> r.set("foo",1)
 => true
 >> r.multi
@@ -84,9 +100,64 @@ INCR a b c
 => "OK"
 >> r.get("foo")
 => "1"
-

Return value

Multi bulk reply, specifically:

-The result of a MULTI/EXEC command is a multi bulk reply where every element is the return value of every command in the atomic transaction.
+

Check and Set (CAS) transactions using WATCH

WATCH is used in order to provide a CAS (Check and Set) behavior to +Redis Transactions.

WATCHed keys are monitored in order to detect changes against this keys. +If at least a watched key will be modified before the EXEC call, the +whole transaction will abort, and EXEC will return a nil object +(A Null Multi Bulk reply) to notify that the transaction failed.

For example imagine we have the need to atomically increment the value +of a key by 1 (I know we have INCR, let's suppose we don't have it).

The first try may be the following: +
+val = GET mykey
+val = val + 1
+SET mykey $val
+
+This will work reliably only if we have a single client performing the operation in a given time. +If multiple clients will try to increment the key about at the same time +there will be a race condition. For instance client A and B will read the +old value, for instance, 10. The value will be incremented to 11 by both +the clients, and finally SET as the value of the key. So the final value +will be "11" instead of "12".

Thanks to WATCH we are able to model the problem very well: +
+WATCH mykey
+val = GET mykey
+val = val + 1
+MULTI
+SET mykey $val
+EXEC
 
+Using the above code, if there are race conditions and another client +modified the result of val in the time between our call to WATCH and +our call to EXEC, the transaction will fail.

We'll have just to re-iterate the operation hoping this time we'll not get +a new race. This form of locking is called optimistic locking and is +a very powerful form of locking as in many problems there are multiple +clients accessing a much bigger number of keys, so it's very unlikely that +there are collisions: usually operations don't need to be performed +multiple times.

WATCH explained

So what is WATCH really about? It is a command that will make the EXEC +conditional: we are asking Redis to perform the transaction only if no +other client modified any of the WATCHed keys. Otherwise the transaction is not +entered at all. (Note that if you WATCH a volatile key and Redis expires the key after you WATCHed it, EXEC will still work. More.)

WATCH can be called multiple times. Simply all the WATCH calls will +have the effects to watch for changes starting from the call, up to the +moment EXEC is called.

When EXEC is called, either if it will fail or succeed, all keys are +UNWATCHed. Also when a client connection is closed, everything gets +UNWATCHed.

It is also possible to use the UNWATCH command (without arguments) in order +to flush all the watched keys. Sometimes this is useful as we +optimistically lock a few keys, since possibly we need to perform a transaction +to alter those keys, but after reading the current content of the keys +we don't want to proceed. When this happens we just call UNWATCH so that +the connection can already be used freely for new transactions.

WATCH used to implement ZPOP

A good example to illustrate how WATCH can be used to create new atomic +operations otherwise not supported by Redis is to implement ZPOP, that is +a command that pops the element with the lower score from a sorted set +in an atomic way. This is the simplest implementation: +
+WATCH zset
+ele = ZRANGE zset 0 0
+MULTI
+ZREM zset ele
+EXEC
+
+If EXEC fails (returns a nil value) we just re-iterate the operation.

Return value

Multi bulk reply, specifically:

+The result of a MULTI/EXEC command is a multi bulk reply where every element is the return value of every command in the atomic transaction.
+
If a MULTI/EXEC transaction is aborted because of WATCH detected modified keys, a Null Multi Bulk reply is returned.