MultiExecCommand.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
  2. <html>
  3. <head>
  4. <link type="text/css" rel="stylesheet" href="style.css" />
  5. </head>
  6. <body>
  7. <div id="page">
  8. <div id='header'>
  9. <a href="index.html">
  10. <img style="border:none" alt="Redis Documentation" src="redis.png">
  11. </a>
  12. </div>
  13. <div id="pagecontent">
  14. <div class="index">
  15. <!-- This is a (PRE) block. Make sure it's left aligned or your toc title will be off. -->
  16. <b>MultiExecCommand: Contents</b><br>&nbsp;&nbsp;<a href="#WATCH key1 key2 ... keyN (Redis &gt;">WATCH key1 key2 ... keyN (Redis &gt;</a><br>&nbsp;&nbsp;<a href="#UNWATCH">UNWATCH</a><br>&nbsp;&nbsp;<a href="#MULTI">MULTI</a><br>&nbsp;&nbsp;<a href="#COMMAND_1 ...">COMMAND_1 ...</a><br>&nbsp;&nbsp;<a href="#COMMAND_2 ...">COMMAND_2 ...</a><br>&nbsp;&nbsp;<a href="#COMMAND_N ...">COMMAND_N ...</a><br>&nbsp;&nbsp;<a href="#EXEC or DISCARD">EXEC or DISCARD</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Usage">Usage</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#The DISCARD command">The DISCARD command</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Check and Set (CAS) transactions using WATCH">Check and Set (CAS) transactions using WATCH</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#WATCH explained">WATCH explained</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#WATCH used to implement ZPOP">WATCH used to implement ZPOP</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a>
  17. </div>
  18. <h1 class="wikiname">MultiExecCommand</h1>
  19. <div class="summary">
  20. </div>
  21. <div class="narrow">
  22. &iuml;&raquo;&iquest;#sidebar <a href="GenericCommandsSidebar.html">GenericCommandsSidebar</a><h1><a name="WATCH key1 key2 ... keyN (Redis &gt;">WATCH key1 key2 ... keyN (Redis &gt;</a></h1> 2.1.0)=
  23. <h1><a name="UNWATCH">UNWATCH</a></h1>
  24. <h1><a name="MULTI">MULTI</a></h1>
  25. <h1><a name="COMMAND_1 ...">COMMAND_1 ...</a></h1>
  26. <h1><a name="COMMAND_2 ...">COMMAND_2 ...</a></h1>
  27. <h1><a name="COMMAND_N ...">COMMAND_N ...</a></h1>
  28. <h1><a name="EXEC or DISCARD">EXEC or DISCARD</a></h1>MULTI, EXEC, DISCARD and WATCH commands are the foundation of Redis Transactions.
  29. A Redis Transaction allows the execution of a group of Redis commands in a single
  30. step, with two important guarantees:<br/><br/><ul><li> All the commands in a transaction are serialized and executed sequentially. It can never happen that a request issued by another client is served <b>in the middle</b> of the execution of a Redis transaction. This guarantees that the commands are executed as a single atomic operation.</li><li> Either all of the commands or none are processed. The EXEC command triggers the execution of all the commands in the transaction, so if a client loses the connection to the server in the context of a transaction before calling the MULTI command none of the operations are performed, instead if the EXEC command is called, all the operations are performed. An exception to this rule is when the Append Only File is enabled: every command that is part of a Redis transaction will log in the AOF as long as the operation is completed, so if the Redis server crashes or is killed by the system administrator in some hard way it is possible that only a partial number of operations are registered.</li></ul>
  31. 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.<h2><a name="Usage">Usage</a></h2>A Redis transaction is entered using the MULTI command. The command always
  32. replies with OK. At this point the user can issue multiple commands. Instead
  33. of executing these commands, Redis will &quot;queue&quot; them. All the commands are
  34. executed once EXEC is called.<br/><br/>Calling DISCARD instead will flush the transaction queue and will exit
  35. the transaction.<br/><br/>The following is an example using the Ruby client:
  36. <pre class="codeblock python" name="code">
  37. ?&gt; r.multi
  38. =&gt; &quot;OK&quot;
  39. &gt;&gt; r.incr &quot;foo&quot;
  40. =&gt; &quot;QUEUED&quot;
  41. &gt;&gt; r.incr &quot;bar&quot;
  42. =&gt; &quot;QUEUED&quot;
  43. &gt;&gt; r.incr &quot;bar&quot;
  44. =&gt; &quot;QUEUED&quot;
  45. &gt;&gt; r.exec
  46. =&gt; [1, 1, 2]
  47. </pre>
  48. As it is possible to see from the session above, MULTI returns an &quot;array&quot; of
  49. replies, where every element is the reply of a single command in the
  50. transaction, in the same order the commands were queued.<br/><br/>When a Redis connection is in the context of a MULTI request, all the commands
  51. will reply with a simple string &quot;QUEUED&quot; if they are correct from the
  52. point of view of the syntax and arity (number of arguments) of the commaand.
  53. Some commands are still allowed to fail during execution time.<br/><br/>This is more clear on the protocol level; In the following example one command
  54. will fail when executed even if the syntax is right:
  55. <pre class="codeblock python python" name="code">
  56. Trying 127.0.0.1...
  57. Connected to localhost.
  58. Escape character is '^]'.
  59. MULTI
  60. +OK
  61. SET a 3
  62. abc
  63. +QUEUED
  64. LPOP a
  65. +QUEUED
  66. EXEC
  67. *2
  68. +OK
  69. -ERR Operation against a key holding the wrong kind of value
  70. </pre>
  71. MULTI returned a two elements bulk reply where one is an +OK
  72. code and one is a -ERR reply. It's up to the client lib to find a sensible
  73. way to provide the error to the user.<br/><br/><blockquote>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.</blockquote>
  74. Another example, again using the write protocol with telnet, shows how
  75. syntax errors are reported ASAP instead:
  76. <pre class="codeblock python python python" name="code">
  77. MULTI
  78. +OK
  79. INCR a b c
  80. -ERR wrong number of arguments for 'incr' command
  81. </pre>
  82. This time due to the syntax error the &quot;bad&quot; INCR command is not queued
  83. at all.<h2><a name="The DISCARD command">The DISCARD command</a></h2>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:
  84. <pre class="codeblock python python python python" name="code">
  85. ?&gt; r.set(&quot;foo&quot;,1)
  86. =&gt; true
  87. &gt;&gt; r.multi
  88. =&gt; &quot;OK&quot;
  89. &gt;&gt; r.incr(&quot;foo&quot;)
  90. =&gt; &quot;QUEUED&quot;
  91. &gt;&gt; r.discard
  92. =&gt; &quot;OK&quot;
  93. &gt;&gt; r.get(&quot;foo&quot;)
  94. =&gt; &quot;1&quot;
  95. </pre><h2><a name="Check and Set (CAS) transactions using WATCH">Check and Set (CAS) transactions using WATCH</a></h2>WATCH is used in order to provide a CAS (Check and Set) behavior to
  96. Redis Transactions.<br/><br/>WATCHed keys are monitored in order to detect changes against this keys.
  97. If at least a watched key will be modified before the EXEC call, the
  98. whole transaction will abort, and EXEC will return a nil object
  99. (A Null Multi Bulk reply) to notify that the transaction failed.<br/><br/>For example imagine we have the need to atomically increment the value
  100. of a key by 1 (I know we have INCR, let's suppose we don't have it).<br/><br/>The first try may be the following:
  101. <pre class="codeblock python python python python python" name="code">
  102. val = GET mykey
  103. val = val + 1
  104. SET mykey $val
  105. </pre>
  106. This will work reliably only if we have a single client performing the operation in a given time.
  107. If multiple clients will try to increment the key about at the same time
  108. there will be a race condition. For instance client A and B will read the
  109. old value, for instance, 10. The value will be incremented to 11 by both
  110. the clients, and finally SET as the value of the key. So the final value
  111. will be &quot;11&quot; instead of &quot;12&quot;.<br/><br/>Thanks to WATCH we are able to model the problem very well:
  112. <pre class="codeblock python python python python python python" name="code">
  113. WATCH mykey
  114. val = GET mykey
  115. val = val + 1
  116. MULTI
  117. SET mykey $val
  118. EXEC
  119. </pre>
  120. Using the above code, if there are race conditions and another client
  121. modified the result of <i>val</i> in the time between our call to WATCH and
  122. our call to EXEC, the transaction will fail.<br/><br/>We'll have just to re-iterate the operation hoping this time we'll not get
  123. a new race. This form of locking is called <b>optimistic locking</b> and is
  124. a very powerful form of locking as in many problems there are multiple
  125. clients accessing a much bigger number of keys, so it's very unlikely that
  126. there are collisions: usually operations don't need to be performed
  127. multiple times.<h2><a name="WATCH explained">WATCH explained</a></h2>So what is WATCH really about? It is a command that will make the EXEC
  128. conditional: we are asking Redis to perform the transaction only if no
  129. other client modified any of the WATCHed keys. Otherwise the transaction is not
  130. entered at all. (Note that if you WATCH a volatile key and Redis expires the key after you WATCHed it, EXEC will still work. <a href="http://code.google.com/p/redis/issues/detail?id=270" target="_blank">More</a>.)<br/><br/>WATCH can be called multiple times. Simply all the WATCH calls will
  131. have the effects to watch for changes starting from the call, up to the
  132. moment EXEC is called.<br/><br/>When EXEC is called, either if it will fail or succeed, all keys are
  133. UNWATCHed. Also when a client connection is closed, everything gets
  134. UNWATCHed.<br/><br/>It is also possible to use the UNWATCH command (without arguments) in order
  135. to flush all the watched keys. Sometimes this is useful as we
  136. optimistically lock a few keys, since possibly we need to perform a transaction
  137. to alter those keys, but after reading the current content of the keys
  138. we don't want to proceed. When this happens we just call UNWATCH so that
  139. the connection can already be used freely for new transactions.<h2><a name="WATCH used to implement ZPOP">WATCH used to implement ZPOP</a></h2>A good example to illustrate how WATCH can be used to create new atomic
  140. operations otherwise not supported by Redis is to implement ZPOP, that is
  141. a command that pops the element with the lower score from a sorted set
  142. in an atomic way. This is the simplest implementation:
  143. <pre class="codeblock python python python python python python python" name="code">
  144. WATCH zset
  145. ele = ZRANGE zset 0 0
  146. MULTI
  147. ZREM zset ele
  148. EXEC
  149. </pre>
  150. If EXEC fails (returns a nil value) we just re-iterate the operation.<h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Multi bulk reply</a>, specifically:<br/><br/><pre class="codeblock python python python python python python python python" name="code">
  151. 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.
  152. </pre>If a MULTI/EXEC transaction is aborted because of WATCH detected modified keys, a <a href="ReplyTypes.html">Null Multi Bulk reply</a> is returned.
  153. </div>
  154. </div>
  155. </div>
  156. </body>
  157. </html>