]> git.saurik.com Git - redis.git/commitdiff
HTML doc updated
authorantirez <antirez@gmail.com>
Wed, 15 Dec 2010 14:49:29 +0000 (15:49 +0100)
committerantirez <antirez@gmail.com>
Wed, 15 Dec 2010 14:49:29 +0000 (15:49 +0100)
17 files changed:
doc/AppendOnlyFileHowto.html
doc/CommandReference.html
doc/ExpireCommand.html
doc/HdelCommand.html
doc/HgetallCommand.html
doc/IntroductionToRedisDataTypes.html
doc/ListCommandsSidebar.html
doc/MultiExecCommand.html
doc/ProtocolSpecification.html
doc/PublishSubscribe.html
doc/StringCommandsSidebar.html
doc/Strings.html
doc/SubstrCommand.html
doc/VirtualMemoryUserGuide.html
doc/ZrankCommand.html
doc/index.html
doc/redis.png

index 1a0e468ac4364a90e140cd91a738000ac67405d6..295e75484282eef0b3bef84183be9f5d3a3b9b6d 100644 (file)
@@ -16,7 +16,7 @@
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
-<b>AppendOnlyFileHowto: Contents</b><br>&nbsp;&nbsp;<a href="#Append Only File HOWTO">Append Only File HOWTO</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#General Information">General Information</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Log rewriting">Log rewriting</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Wait... but how does this work?">Wait... but how does this work?</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#How durable is the append only file?">How durable is the append only file?</a>
+<b>AppendOnlyFileHowto: Contents</b><br>&nbsp;&nbsp;<a href="#Append Only File HOWTO">Append Only File HOWTO</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#General Information">General Information</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Log rewriting">Log rewriting</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Wait... but how does this work?">Wait... but how does this work?</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#How durable is the append only file?">How durable is the append only file?</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#What should I do if my Append Only File gets corrupted?">What should I do if my Append Only File gets corrupted?</a>
                 </div>
                 
                 <h1 class="wikiname">AppendOnlyFileHowto</h1>
                 </div>
                 
                 <h1 class="wikiname">AppendOnlyFileHowto</h1>
@@ -31,8 +31,7 @@
 What is the solution? To use append only file as alternative to snapshotting. How it works?<br/><br/><ul><li> It is an 1.1 only feature.</li><li> You have to turn it on editing the configuration file. Just make sure you have &quot;appendonly yes&quot; somewhere.</li><li> Append only files work this way: every time Redis receive a command that changes the dataset (for instance a SET or LPUSH command) it appends this command in the append only file. When you restart Redis it will first <b>re-play</b> the append only file to rebuild the state.</li></ul>
 <h2><a name="Log rewriting">Log rewriting</a></h2>As you can guess... the append log file gets bigger and bigger, every time there is a new operation changing the dataset. Even if you set always the same key &quot;mykey&quot; to the values of &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, ... up to 10000000000 in the end you'll have just a single key in the dataset, just a few bytes! but how big will be the append log file? Very very big.<br/><br/>So Redis supports an interesting feature: it is able to rebuild the append log file, in background, without to stop processing client commands. The key is the command <a href="BGREWRITEAOF.html">BGREWRITEAOF</a>. This command basically is able to use the dataset in memory in order to rewrite the shortest sequence of commands able to rebuild the exact dataset that is currently in memory.<br/><br/>So from time to time when the log gets too big, try this command. It's safe as if it fails you will not lost your old log (but you can make a backup copy given that currently 1.1 is still in beta!).<h2><a name="Wait... but how does this work?">Wait... but how does this work?</a></h2>Basically it uses the same fork() copy-on-write trick that snapshotting already uses. This is how the algorithm works:<br/><br/><ul><li> Redis forks, so now we have a child and a parent.</li><li> The child starts writing the new append log file in a temporary file.</li><li> The parent accumulates all the new changes in an in-memory buffer (but at the same time it writes the new changes in the <b>old</b> append only file, so if the rewriting fails, we are safe).</li><li> When the child finished to rewrite the file, the parent gets a signal, and append the in-memory buffer at the end of the file generated by the child.</li><li> Profit! Now Redis atomically renames the old file into the new one, and starts appending new data into the new file.</li></ul>
 <h2><a name="How durable is the append only file?">How durable is the append only file?</a></h2>Check redis.conf, you can configure how many times Redis will fsync() data on disk. There are three options:<br/><br/><ul><li> Fsync() every time a new command is appended to the append log file. Very very slow, very safe.</li><li> Fsync() one time every second. Fast enough, and you can lose 1 second of data if there is a disaster.</li><li> Never fsync(), just put your data in the hands of the Operating System. The faster and unsafer method.</li></ul>
 What is the solution? To use append only file as alternative to snapshotting. How it works?<br/><br/><ul><li> It is an 1.1 only feature.</li><li> You have to turn it on editing the configuration file. Just make sure you have &quot;appendonly yes&quot; somewhere.</li><li> Append only files work this way: every time Redis receive a command that changes the dataset (for instance a SET or LPUSH command) it appends this command in the append only file. When you restart Redis it will first <b>re-play</b> the append only file to rebuild the state.</li></ul>
 <h2><a name="Log rewriting">Log rewriting</a></h2>As you can guess... the append log file gets bigger and bigger, every time there is a new operation changing the dataset. Even if you set always the same key &quot;mykey&quot; to the values of &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, ... up to 10000000000 in the end you'll have just a single key in the dataset, just a few bytes! but how big will be the append log file? Very very big.<br/><br/>So Redis supports an interesting feature: it is able to rebuild the append log file, in background, without to stop processing client commands. The key is the command <a href="BGREWRITEAOF.html">BGREWRITEAOF</a>. This command basically is able to use the dataset in memory in order to rewrite the shortest sequence of commands able to rebuild the exact dataset that is currently in memory.<br/><br/>So from time to time when the log gets too big, try this command. It's safe as if it fails you will not lost your old log (but you can make a backup copy given that currently 1.1 is still in beta!).<h2><a name="Wait... but how does this work?">Wait... but how does this work?</a></h2>Basically it uses the same fork() copy-on-write trick that snapshotting already uses. This is how the algorithm works:<br/><br/><ul><li> Redis forks, so now we have a child and a parent.</li><li> The child starts writing the new append log file in a temporary file.</li><li> The parent accumulates all the new changes in an in-memory buffer (but at the same time it writes the new changes in the <b>old</b> append only file, so if the rewriting fails, we are safe).</li><li> When the child finished to rewrite the file, the parent gets a signal, and append the in-memory buffer at the end of the file generated by the child.</li><li> Profit! Now Redis atomically renames the old file into the new one, and starts appending new data into the new file.</li></ul>
 <h2><a name="How durable is the append only file?">How durable is the append only file?</a></h2>Check redis.conf, you can configure how many times Redis will fsync() data on disk. There are three options:<br/><br/><ul><li> Fsync() every time a new command is appended to the append log file. Very very slow, very safe.</li><li> Fsync() one time every second. Fast enough, and you can lose 1 second of data if there is a disaster.</li><li> Never fsync(), just put your data in the hands of the Operating System. The faster and unsafer method.</li></ul>
-Warning: by default Redis will fsync() after <b>every command</b>! This is because the Redis authors want to ship a default configuration that is the safest pick. But the best compromise for most datasets is to fsync() one time every second.
-
+The suggested (and default) policy is &quot;everysec&quot;. It is both very fast and pretty safe. The &quot;always&quot; policy is very slow in practice, even if it was improved in Redis 2.0.0 there is no way to make fsync() faster than it is.<h2><a name="What should I do if my Append Only File gets corrupted?">What should I do if my Append Only File gets corrupted?</a></h2>It is possible that the server crashes while writing the AOF file (this still should never lead to inconsistencies) corrupting the file in a way that is no longer loadable by Redis. When this happens you can fix this problem using the following procedure:<br/><br/><ul><li> Make a backup copy of your AOF file.</li><li> Fix the original file with: ./redis-check-aof --fix <code name="code" class="python">&lt;filename&gt;</code></li><li> Optionally use diff -u to check what is the difference between two files.</li><li> Restart the server with the fixed file.</li></ul>
                 </div>
         
             </div>
                 </div>
         
             </div>
index 7021bd7e4725bd458d2a5466016c7ae3df14b4aa..143b23b5e59f6b73b0fb1c919d4296beedeb79ea 100644 (file)
@@ -28,8 +28,8 @@
                 <div class="narrow">
                     &iuml;&raquo;&iquest;= Redis Command Reference =<br/><br/>Every command name links to a specific wiki page describing the behavior of the command.<h2><a name="Categorized Command List">Categorized Command List</a></h2><h2><a name="Connection handling">Connection handling</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="QuitCommand.html">QUIT</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  close the connection </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="AuthCommand.html">AUTH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>password</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  simple password authentication if enabled  </td></tr></table>
 <h2><a name="Commands operating on all value types">Commands operating on all value types</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ExistsCommand.html">EXISTS</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  test if a key exists  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="DelCommand.html">DEL</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  delete a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="TypeCommand.html">TYPE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  return the type of the value stored at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="KeysCommand.html">KEYS</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>pattern</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  return all the keys matching a given pattern  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RandomkeyCommand.html">RANDOMKEY</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  return a random key from the key space  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RenameCommand.html">RENAME</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>oldname</i> <i>newname</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  rename the old key in the new one, destroying the newname key if it already exists  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RenamenxCommand.html">RENAMENX</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>oldname</i> <i>newname</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  rename the <i>oldname</i> key to <i>newname</i>, if the <i>newname</i> key does not already exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="DbsizeCommand.html">DBSIZE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  return the number of keys in the current db  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ExpireCommand.html">EXPIRE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  set a time to live in seconds on a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ExpireCommand.html">PERSIST</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  remove the expire from a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="TtlCommand.html">TTL</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  get the time to live in seconds of a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SelectCommand.html">SELECT</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>index</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Select the DB with the specified index  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MoveCommand.html">MOVE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>dbindex</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Move the key from the currently selected DB to the <i>dbindex</i> DB   </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="FlushdbCommand.html">FLUSHDB</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the keys from the currently selected DB  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="FlushallCommand.html">FLUSHALL</a></td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the keys from all the databases  </td></tr></table>
                 <div class="narrow">
                     &iuml;&raquo;&iquest;= Redis Command Reference =<br/><br/>Every command name links to a specific wiki page describing the behavior of the command.<h2><a name="Categorized Command List">Categorized Command List</a></h2><h2><a name="Connection handling">Connection handling</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="QuitCommand.html">QUIT</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  close the connection </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="AuthCommand.html">AUTH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>password</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  simple password authentication if enabled  </td></tr></table>
 <h2><a name="Commands operating on all value types">Commands operating on all value types</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ExistsCommand.html">EXISTS</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  test if a key exists  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="DelCommand.html">DEL</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  delete a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="TypeCommand.html">TYPE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  return the type of the value stored at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="KeysCommand.html">KEYS</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>pattern</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  return all the keys matching a given pattern  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RandomkeyCommand.html">RANDOMKEY</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  return a random key from the key space  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RenameCommand.html">RENAME</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>oldname</i> <i>newname</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  rename the old key in the new one, destroying the newname key if it already exists  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RenamenxCommand.html">RENAMENX</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>oldname</i> <i>newname</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  rename the <i>oldname</i> key to <i>newname</i>, if the <i>newname</i> key does not already exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="DbsizeCommand.html">DBSIZE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  return the number of keys in the current db  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ExpireCommand.html">EXPIRE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  set a time to live in seconds on a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ExpireCommand.html">PERSIST</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  remove the expire from a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="TtlCommand.html">TTL</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  get the time to live in seconds of a key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SelectCommand.html">SELECT</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>index</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Select the DB with the specified index  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MoveCommand.html">MOVE</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>dbindex</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Move the key from the currently selected DB to the <i>dbindex</i> DB   </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="FlushdbCommand.html">FLUSHDB</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the keys from the currently selected DB  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="FlushallCommand.html">FLUSHALL</a></td><td style="border: 1px solid #aaa; padding: 5px;"> - </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the keys from all the databases  </td></tr></table>
-<h2><a name="Commands operating on string values">Commands operating on string values</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetCommand.html">SET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a <i>key</i> to a string <i>value</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="GetCommand.html">GET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the string value of the <i>key</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="GetsetCommand.html">GETSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a key to a string returning the old value of the key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MgetCommand.html">MGET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Multi-get, return the strings values of the keys  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetnxCommand.html">SETNX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a key to a string value if the key does not exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetexCommand.html">SETEX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>time</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set+Expire combo command  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MsetCommand.html">MSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>value1</i> <i>key2</i> <i>value2</i> ... <i>keyN</i> <i>valueN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set multiple keys to multiple values in a single atomic operation   </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MsetCommand.html">MSETNX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>value1</i> <i>key2</i> <i>value2</i> ... <i>keyN</i> <i>valueN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set multiple keys to multiple values in a single atomic operation if none of the keys already exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">INCR</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Increment the integer value of key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">INCRBY</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>integer</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Increment the integer value of <i>key</i> by <i>integer</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">DECR</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Decrement the integer value of key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">DECRBY</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>integer</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Decrement the integer value of <i>key</i> by <i>integer</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="AppendCommand.html">APPEND</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Append the specified string to the string stored at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SubstrCommand.html">SUBSTR</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a substring of a larger string  </td></tr></table>
-<h2><a name="Commands operating on lists">Commands operating on lists</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RpushCommand.html">RPUSH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Append an element to the tail of the List value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RpushCommand.html">LPUSH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Append an element to the head of the List value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LlenCommand.html">LLEN</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the length of the List value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LrangeCommand.html">LRANGE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a range of elements from the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LtrimCommand.html">LTRIM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Trim the list at key to the specified range of elements  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LindexCommand.html">LINDEX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>index</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the element at index position from the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LsetCommand.html">LSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>index</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a new value as the element at index position of the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LremCommand.html">LREM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>count</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the first-N, last-N, or all the elements matching value from the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LpopCommand.html">LPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return and remove (atomically) the first element of the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LpopCommand.html">RPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return and remove (atomically) the last element of the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="BlpopCommand.html">BLPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i> <i>timeout</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Blocking LPOP  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="BlpopCommand.html">BRPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i> <i>timeout</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Blocking RPOP  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RpoplpushCommand.html">RPOPLPUSH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>srckey</i> <i>dstkey</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return and remove (atomically) the last element of the source List stored at <i>srckey</i> and push the same element to the destination List stored at <i>dstkey</i>  </td></tr></table>
+<h2><a name="Commands operating on string values">Commands operating on string values</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetCommand.html">SET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a <i>key</i> to a string <i>value</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="GetCommand.html">GET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the string value of the <i>key</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="GetsetCommand.html">GETSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a key to a string returning the old value of the key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetnxCommand.html">SETNX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a key to a string value if the key does not exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetexCommand.html">SETEX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>time</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set+Expire combo command  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SetbitCommand.html">SETBIT</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>offset</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set bit at <i>offset</i> to <i>value</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="GetbitCommand.html">GETBIT</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>offset</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Return bit value at <i>offset</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MsetCommand.html">MSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>value1</i> <i>key2</i> <i>value2</i> ... <i>keyN</i> <i>valueN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set multiple keys to multiple values in a single atomic operation   </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MsetCommand.html">MSETNX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>value1</i> <i>key2</i> <i>value2</i> ... <i>keyN</i> <i>valueN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set multiple keys to multiple values in a single atomic operation if none of the keys already exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="MgetCommand.html">MGET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Multi-get, return the strings values of the keys  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">INCR</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Increment the integer value of key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">INCRBY</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>integer</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Increment the integer value of <i>key</i> by <i>integer</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">DECR</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Decrement the integer value of key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="IncrCommand.html">DECRBY</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>integer</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Decrement the integer value of <i>key</i> by <i>integer</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="AppendCommand.html">APPEND</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Append the specified string to the string stored at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SubstrCommand.html">SUBSTR</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a substring of a larger string  </td></tr></table>
+<h2><a name="Commands operating on lists">Commands operating on lists</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RpushCommand.html">RPUSH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Append an element to the tail of the List value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RpushCommand.html">LPUSH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Append an element to the head of the List value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LlenCommand.html">LLEN</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the length of the List value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LrangeCommand.html">LRANGE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a range of elements from the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LtrimCommand.html">LTRIM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Trim the list at key to the specified range of elements  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LindexCommand.html">LINDEX</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>index</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the element at index position from the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LsetCommand.html">LSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>index</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set a new value as the element at index position of the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LremCommand.html">LREM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>count</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the first-N, last-N, or all the elements matching value from the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LpopCommand.html">LPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return and remove (atomically) the first element of the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="LpopCommand.html">RPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return and remove (atomically) the last element of the List at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="BlpopCommand.html">BLPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i> <i>timeout</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Blocking LPOP  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="BlpopCommand.html">BRPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i> <i>timeout</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Blocking RPOP  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="RpoplpushCommand.html">RPOPLPUSH</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>srckey</i> <i>dstkey</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return and remove (atomically) the last element of the source List stored at <i>srckey</i> and push the same element to the destination List stored at <i>dstkey</i>  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="BrpoplpushCommand.html">BRPOPLPUSH</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>srckey</i> <i>dstkey</i> </td><td style="border: 1px solid #aaa; padding: 5px;"> Like RPOPLPUSH but blocking of source key is empty </td></tr></table>
 <h2><a name="Commands operating on sets">Commands operating on sets</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SaddCommand.html">SADD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Add the specified member to the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SremCommand.html">SREM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the specified member from the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SpopCommand.html">SPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove and return (pop) a random element from the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SmoveCommand.html">SMOVE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>srckey</i> <i>dstkey</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Move the specified member from one Set to another atomically  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ScardCommand.html">SCARD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the number of elements (the cardinality) of the Set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SismemberCommand.html">SISMEMBER</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Test if the specified value is a member of the Set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SinterCommand.html">SINTER</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the intersection between the Sets stored at key1, key2, ..., keyN  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SinterstoreCommand.html">SINTERSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Compute the intersection between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SunionCommand.html">SUNION</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the union between the Sets stored at key1, key2, ..., keyN  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SunionstoreCommand.html">SUNIONSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Compute the union between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SdiffCommand.html">SDIFF</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SdiffstoreCommand.html">SDIFFSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Compute the difference between the Set key1 and all the Sets key2, ..., keyN, and store the resulting Set at dstkey  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SmembersCommand.html">SMEMBERS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return all the members of the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SrandmemberCommand.html">SRANDMEMBER</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a random member of the Set value at key  </td></tr></table>
 <h2><a name="Commands operating on sorted zsets (sorted sets)">Commands operating on sorted zsets (sorted sets)</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZaddCommand.html">ZADD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>score</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Add the specified member to the Sorted Set value at key or update the score if it already exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZremCommand.html">ZREM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the specified member from the Sorted Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZincrbyCommand.html">ZINCRBY</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>increment</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  If the member already exists increment its score by <i>increment</i>, otherwise add the member setting <i>increment</i> as score  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrankCommand.html">ZRANK</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the rank (or index) or <i>member</i> in the sorted set at <i>key</i>, with scores being ordered from low to high  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrankCommand.html">ZREVRANK</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the rank (or index) or <i>member</i> in the sorted set at <i>key</i>, with scores being ordered from high to low  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangeCommand.html">ZRANGE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a range of elements from the sorted set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangeCommand.html">ZREVRANGE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a range of elements from the sorted set at key, exactly like ZRANGE, but the sorted set is ordered in traversed in reverse order, from the greatest to the smallest score  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return all the elements with score &gt;= min and score &lt;= max (a range query) from the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangebyscoreCommand.html">ZCOUNT</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the number of elements with score &gt;= min and score &lt;= max in the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZcardCommand.html">ZCARD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the cardinality (number of elements) of the sorted set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZscoreCommand.html">ZSCORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>element</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the score associated with the specified element of the sorted set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZremrangebyrankCommand.html">ZREMRANGEBYRANK</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the elements with rank &gt;= min and rank &lt;= max from the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the elements with score &gt;= min and score &lt;= max from the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZunionstoreCommand.html">ZUNIONSTORE / ZINTERSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>N</i> <i>key1</i> ... <i>keyN</i> WEIGHTS <i>w1</i> ... <i>wN</i> AGGREGATE SUM|MIN|MAX  </td><td style="border: 1px solid #aaa; padding: 5px;">  Perform a union or intersection over a number of sorted sets with optional weight and aggregate  </td></tr></table>
 <h2><a name="Commands operating on hashes">Commands operating on hashes</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HsetCommand.html">HSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set the hash field to the specified value. Creates the hash if needed.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetCommand.html">HGET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Retrieve the value of the specified hash field.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HmgetCommand.html">HMGET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field1</i> ... <i>fieldN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Get the hash values associated to the specified fields.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HmsetCommand.html">HMSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field1</i> <i>value1</i> ... <i>fieldN</i> <i>valueN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set the hash fields to their respective values.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HincrbyCommand.html">HINCRBY</a> </td><td style="border: 1px solid #aaa; padding: 5px;">  <i>key</i> <i>field</i> <i>integer</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Increment the integer value of the hash at <i>key</i> on <i>field</i> with <i>integer</i>.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HexistsCommand.html">HEXISTS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Test for existence of a specified field in a hash  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HdelCommand.html">HDEL</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the specified field from a hash  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HlenCommand.html">HLEN</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">   Return the number of items in a hash.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetallCommand.html">HKEYS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Return all the fields in a hash.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetallCommand.html">HVALS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;"> Return all the values in a hash.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetallCommand.html">HGETALL</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;"> Return all the fields and associated values in a hash.  </td></tr></table>
 <h2><a name="Commands operating on sets">Commands operating on sets</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SaddCommand.html">SADD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Add the specified member to the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SremCommand.html">SREM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the specified member from the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SpopCommand.html">SPOP</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove and return (pop) a random element from the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SmoveCommand.html">SMOVE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>srckey</i> <i>dstkey</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Move the specified member from one Set to another atomically  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ScardCommand.html">SCARD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the number of elements (the cardinality) of the Set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SismemberCommand.html">SISMEMBER</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Test if the specified value is a member of the Set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SinterCommand.html">SINTER</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the intersection between the Sets stored at key1, key2, ..., keyN  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SinterstoreCommand.html">SINTERSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Compute the intersection between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SunionCommand.html">SUNION</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the union between the Sets stored at key1, key2, ..., keyN  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SunionstoreCommand.html">SUNIONSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Compute the union between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SdiffCommand.html">SDIFF</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SdiffstoreCommand.html">SDIFFSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Compute the difference between the Set key1 and all the Sets key2, ..., keyN, and store the resulting Set at dstkey  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SmembersCommand.html">SMEMBERS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return all the members of the Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="SrandmemberCommand.html">SRANDMEMBER</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a random member of the Set value at key  </td></tr></table>
 <h2><a name="Commands operating on sorted zsets (sorted sets)">Commands operating on sorted zsets (sorted sets)</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZaddCommand.html">ZADD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>score</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Add the specified member to the Sorted Set value at key or update the score if it already exist  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZremCommand.html">ZREM</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the specified member from the Sorted Set value at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZincrbyCommand.html">ZINCRBY</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>increment</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  If the member already exists increment its score by <i>increment</i>, otherwise add the member setting <i>increment</i> as score  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrankCommand.html">ZRANK</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the rank (or index) or <i>member</i> in the sorted set at <i>key</i>, with scores being ordered from low to high  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrankCommand.html">ZREVRANK</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>member</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the rank (or index) or <i>member</i> in the sorted set at <i>key</i>, with scores being ordered from high to low  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangeCommand.html">ZRANGE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a range of elements from the sorted set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangeCommand.html">ZREVRANGE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>start</i> <i>end</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return a range of elements from the sorted set at key, exactly like ZRANGE, but the sorted set is ordered in traversed in reverse order, from the greatest to the smallest score  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return all the elements with score &gt;= min and score &lt;= max (a range query) from the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZrangebyscoreCommand.html">ZCOUNT</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the number of elements with score &gt;= min and score &lt;= max in the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZcardCommand.html">ZCARD</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the cardinality (number of elements) of the sorted set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZscoreCommand.html">ZSCORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>element</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Return the score associated with the specified element of the sorted set at key  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZremrangebyrankCommand.html">ZREMRANGEBYRANK</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the elements with rank &gt;= min and rank &lt;= max from the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>min</i> <i>max</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove all the elements with score &gt;= min and score &lt;= max from the sorted set  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="ZunionstoreCommand.html">ZUNIONSTORE / ZINTERSTORE</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>dstkey</i> <i>N</i> <i>key1</i> ... <i>keyN</i> WEIGHTS <i>w1</i> ... <i>wN</i> AGGREGATE SUM|MIN|MAX  </td><td style="border: 1px solid #aaa; padding: 5px;">  Perform a union or intersection over a number of sorted sets with optional weight and aggregate  </td></tr></table>
 <h2><a name="Commands operating on hashes">Commands operating on hashes</a></h2><table><tr><td style="border: 1px solid #aaa; padding: 5px;"> <b>Command</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Parameters</b> </td><td style="border: 1px solid #aaa; padding: 5px;"> <b>Description</b> </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HsetCommand.html">HSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i> <i>value</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set the hash field to the specified value. Creates the hash if needed.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetCommand.html">HGET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Retrieve the value of the specified hash field.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HmgetCommand.html">HMGET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field1</i> ... <i>fieldN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Get the hash values associated to the specified fields.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HmsetCommand.html">HMSET</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field1</i> <i>value1</i> ... <i>fieldN</i> <i>valueN</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Set the hash fields to their respective values.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HincrbyCommand.html">HINCRBY</a> </td><td style="border: 1px solid #aaa; padding: 5px;">  <i>key</i> <i>field</i> <i>integer</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Increment the integer value of the hash at <i>key</i> on <i>field</i> with <i>integer</i>.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HexistsCommand.html">HEXISTS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Test for existence of a specified field in a hash  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HdelCommand.html">HDEL</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> <i>field</i>  </td><td style="border: 1px solid #aaa; padding: 5px;">  Remove the specified field from a hash  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HlenCommand.html">HLEN</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">   Return the number of items in a hash.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetallCommand.html">HKEYS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i> </td><td style="border: 1px solid #aaa; padding: 5px;">  Return all the fields in a hash.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetallCommand.html">HVALS</a>  </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;"> Return all the values in a hash.  </td></tr><tr><td style="border: 1px solid #aaa; padding: 5px;"> <a href="HgetallCommand.html">HGETALL</a> </td><td style="border: 1px solid #aaa; padding: 5px;"> <i>key</i>  </td><td style="border: 1px solid #aaa; padding: 5px;"> Return all the fields and associated values in a hash.  </td></tr></table>
index cebac8b8eceabd934d4bfa48d1f662e445c3006d..736d951a34abb3bd096420a5e6fa96de3e8fdc4d 100644 (file)
@@ -16,7 +16,7 @@
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
-<b>ExpireCommand: Contents</b><br>&nbsp;&nbsp;<a href="#EXPIRE _key_ _seconds_">EXPIRE _key_ _seconds_</a><br>&nbsp;&nbsp;<a href="#EXPIREAT _key_ _unixtime_ (Redis &gt;">EXPIREAT _key_ _unixtime_ (Redis &gt;</a><br>&nbsp;&nbsp;<a href="#PERSIST _key_">PERSIST _key_</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#How the expire is removed from a key">How the expire is removed from a key</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Restrictions with write operations against volatile keys">Restrictions with write operations against volatile keys</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Restrictions for write operations with volatile keys as sources">Restrictions for write operations with volatile keys as sources</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Setting the timeout again on already volatile keys">Setting the timeout again on already volatile keys</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Enhanced Lazy Expiration algorithm">Enhanced Lazy Expiration algorithm</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Version 1.0">Version 1.0</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Version 1.1">Version 1.1</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FAQ: Can you explain better why Redis &lt; 2.1.3 deletes keys with an EXPIRE on write operations?">FAQ: Can you explain better why Redis &lt; 2.1.3 deletes keys with an EXPIRE on write operations?</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?">FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?</a>
+<b>ExpireCommand: Contents</b><br>&nbsp;&nbsp;<a href="#EXPIRE _key_ _seconds_">EXPIRE _key_ _seconds_</a><br>&nbsp;&nbsp;<a href="#EXPIREAT _key_ _unixtime_ (Redis &gt;">EXPIREAT _key_ _unixtime_ (Redis &gt;</a><br>&nbsp;&nbsp;<a href="#PERSIST _key_ (Redis &gt;">PERSIST _key_ (Redis &gt;</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#How the expire is removed from a key">How the expire is removed from a key</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Restrictions with write operations against volatile keys">Restrictions with write operations against volatile keys</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Restrictions for write operations with volatile keys as sources">Restrictions for write operations with volatile keys as sources</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Setting the timeout again on already volatile keys">Setting the timeout again on already volatile keys</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Enhanced Lazy Expiration algorithm">Enhanced Lazy Expiration algorithm</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Version 1.0">Version 1.0</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Version 1.1">Version 1.1</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FAQ: Can you explain better why Redis &lt; 2.1.3 deletes keys with an EXPIRE on write operations?">FAQ: Can you explain better why Redis &lt; 2.1.3 deletes keys with an EXPIRE on write operations?</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?">FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?</a>
                 </div>
                 
                 <h1 class="wikiname">ExpireCommand</h1>
                 </div>
                 
                 <h1 class="wikiname">ExpireCommand</h1>
@@ -28,8 +28,8 @@
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="GenericCommandsSidebar.html">GenericCommandsSidebar</a><h1><a name="EXPIRE _key_ _seconds_">EXPIRE _key_ _seconds_</a></h1>
 <h1><a name="EXPIREAT _key_ _unixtime_ (Redis &gt;">EXPIREAT _key_ _unixtime_ (Redis &gt;</a></h1> 1.1)=
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="GenericCommandsSidebar.html">GenericCommandsSidebar</a><h1><a name="EXPIRE _key_ _seconds_">EXPIRE _key_ _seconds_</a></h1>
 <h1><a name="EXPIREAT _key_ _unixtime_ (Redis &gt;">EXPIREAT _key_ _unixtime_ (Redis &gt;</a></h1> 1.1)=
-<h1><a name="PERSIST _key_">PERSIST _key_</a></h1>
-<i>Time complexity: O(1)</i><blockquote>Set a timeout on the specified key. After the timeout the key will beautomatically delete by the server. A key with an associated timeout issaid to be <i>volatile</i> in Redis terminology.</blockquote>
+<h1><a name="PERSIST _key_ (Redis &gt;">PERSIST _key_ (Redis &gt;</a></h1> 2.1.3) =
+<i>Time complexity: O(1)</i><blockquote>Set a timeout on the specified key. After the timeout the key will beautomatically deleted by the server. A key with an associated timeout issaid to be <i>volatile</i> in Redis terminology.</blockquote>
 <blockquote>Voltile keys are stored on disk like the other keys, the timeout is persistenttoo like all the other aspects of the dataset. Saving a dataset containingexpires and stopping the server does not stop the flow of time as Redisstores on disk the time when the key will no longer be available as Unixtime, and not the remaining seconds.</blockquote>
 <blockquote>EXPIREAT works exctly like EXPIRE but instead to get the number of secondsrepresenting the Time To Live of the key as a second argument (that is arelative way of specifing the TTL), it takes an absolute one in the form ofa UNIX timestamp (Number of seconds elapsed since 1 Gen 1970).</blockquote>
 <blockquote>EXPIREAT was introduced in order to implement <a href="AppendOnlyFileHowto.html">the Append Only File persistence mode</a>so that EXPIRE commands are automatically translated into EXPIREAT commands for the append only file. Of course EXPIREAT can alsoused by programmers that need a way to simply specify that a given key should expire at a given time in the future.</blockquote>
 <blockquote>Voltile keys are stored on disk like the other keys, the timeout is persistenttoo like all the other aspects of the dataset. Saving a dataset containingexpires and stopping the server does not stop the flow of time as Redisstores on disk the time when the key will no longer be available as Unixtime, and not the remaining seconds.</blockquote>
 <blockquote>EXPIREAT works exctly like EXPIRE but instead to get the number of secondsrepresenting the Time To Live of the key as a second argument (that is arelative way of specifing the TTL), it takes an absolute one in the form ofa UNIX timestamp (Number of seconds elapsed since 1 Gen 1970).</blockquote>
 <blockquote>EXPIREAT was introduced in order to implement <a href="AppendOnlyFileHowto.html">the Append Only File persistence mode</a>so that EXPIRE commands are automatically translated into EXPIREAT commands for the append only file. Of course EXPIREAT can alsoused by programmers that need a way to simply specify that a given key should expire at a given time in the future.</blockquote>
@@ -78,7 +78,7 @@ redis&gt; incr a
 (integer) 1
 </pre>
 I set a key to the value of 100, then set an expire of 360 seconds, and then incremented the key (before the 360 timeout expired of course). The obvious result would be: 101, instead the key is set to the value of 1. Why?
 (integer) 1
 </pre>
 I set a key to the value of 100, then set an expire of 360 seconds, and then incremented the key (before the 360 timeout expired of course). The obvious result would be: 101, instead the key is set to the value of 1. Why?
-There is a very important reason involving the Append Only File and Replication. Let's rework a bit hour example adding the notion of time to the mix:
+There is a very important reason involving the Append Only File and Replication. Let's rework a bit our example adding the notion of time to the mix:
 <pre class="codeblock python python python python" name="code">
 SET a 100
 EXPIRE a 5
 <pre class="codeblock python python python python" name="code">
 SET a 100
 EXPIRE a 5
@@ -87,7 +87,6 @@ INCR a
 </pre>
 Imagine a Redis version that does not implement the &quot;Delete keys with an expire set on write operation&quot; semantic.
 Running the above example with the 10 seconds pause will lead to 'a' being set to the value of 1, as it no longer exists when INCR is called 10 seconds later.<br/><br/>Instead if we drop the 10 seconds pause, the result is that 'a' is set to 101.<br/><br/>And in the practice timing changes! For instance the client may wait 10 seconds before INCR, but the sequence written in the Append Only File (and later replayed-back as fast as possible when Redis is restarted) will not have the pause. Even if we add a timestamp in the AOF, when the time difference is smaller than our timer resolution, we have a race condition.<br/><br/>The same happens with master-slave replication. Again, consider the example above: the client will use the same sequence of commands without the 10 seconds pause, but the replication link will slow down for a few seconds due to a network problem. Result? The master will contain 'a' set to 101, the slave 'a' set to 1.<br/><br/>The only way to avoid this but at the same time have reliable non time dependent timeouts on keys is to destroy volatile keys when a write operation is attempted against it.<br/><br/>After all Redis is one of the rare fully persistent databases that will give you EXPIRE. This comes to a cost :)<h2><a name="FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?">FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?</a></h2>Since Redis 2.1.3 there are no longer restrictions in the use you can do of write commands against volatile keys, still the replication and AOF file are guaranteed to be fully consistent.<br/><br/>In order to obtain a correct behavior without sacrificing consistency now when a key expires, a DEL operation is synthesized in both the AOF file and against all the attached slaves. This way the expiration process is centralized in the master instance, and there is no longer a chance of consistency errors.<br/><br/>However while the slaves while connected to a master will not expire keys independently, they'll still take the full state of the expires existing in the dataset, so when a slave is elected to a master it will be able to expire the keys independently, fully acting as a master.
 </pre>
 Imagine a Redis version that does not implement the &quot;Delete keys with an expire set on write operation&quot; semantic.
 Running the above example with the 10 seconds pause will lead to 'a' being set to the value of 1, as it no longer exists when INCR is called 10 seconds later.<br/><br/>Instead if we drop the 10 seconds pause, the result is that 'a' is set to 101.<br/><br/>And in the practice timing changes! For instance the client may wait 10 seconds before INCR, but the sequence written in the Append Only File (and later replayed-back as fast as possible when Redis is restarted) will not have the pause. Even if we add a timestamp in the AOF, when the time difference is smaller than our timer resolution, we have a race condition.<br/><br/>The same happens with master-slave replication. Again, consider the example above: the client will use the same sequence of commands without the 10 seconds pause, but the replication link will slow down for a few seconds due to a network problem. Result? The master will contain 'a' set to 101, the slave 'a' set to 1.<br/><br/>The only way to avoid this but at the same time have reliable non time dependent timeouts on keys is to destroy volatile keys when a write operation is attempted against it.<br/><br/>After all Redis is one of the rare fully persistent databases that will give you EXPIRE. This comes to a cost :)<h2><a name="FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?">FAQ: How this limitations were solved in Redis versions &gt; 2.1.3?</a></h2>Since Redis 2.1.3 there are no longer restrictions in the use you can do of write commands against volatile keys, still the replication and AOF file are guaranteed to be fully consistent.<br/><br/>In order to obtain a correct behavior without sacrificing consistency now when a key expires, a DEL operation is synthesized in both the AOF file and against all the attached slaves. This way the expiration process is centralized in the master instance, and there is no longer a chance of consistency errors.<br/><br/>However while the slaves while connected to a master will not expire keys independently, they'll still take the full state of the expires existing in the dataset, so when a slave is elected to a master it will be able to expire the keys independently, fully acting as a master.
-
                 </div>
         
             </div>
                 </div>
         
             </div>
index 7afdb9355f2ef97612941224ec2bf34c92693779..2ecb209848d3ac6333562057d67acc38117d6445 100644 (file)
@@ -28,7 +28,7 @@
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="HashCommandsSidebar.html">HashCommandsSidebar</a><h1><a name="HDEL _key_ _field_ (Redis &gt;">HDEL _key_ _field_ (Redis &gt;</a></h1> 1.3.10)=
 <i>Time complexity: O(1)</i><blockquote>Remove the specified <i>field</i> from an hash stored at <i>key</i>.</blockquote>
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="HashCommandsSidebar.html">HashCommandsSidebar</a><h1><a name="HDEL _key_ _field_ (Redis &gt;">HDEL _key_ _field_ (Redis &gt;</a></h1> 1.3.10)=
 <i>Time complexity: O(1)</i><blockquote>Remove the specified <i>field</i> from an hash stored at <i>key</i>.</blockquote>
-<blockquote>If the <i>field</i> was present in the hash it is returned and 1 is returned, otherwise 0 is returned and no operation is performed.</blockquote>
+<blockquote>If the <i>field</i> was present in the hash it is deleted and 1 is returned, otherwise 0 is returned and no operation is performed.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Integer reply</a>
                 </div>
         
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Integer reply</a>
                 </div>
         
index 7d85c4156f7f4b6e2bced1ac22156349196409cd..bfc6c4f8b59da043a0b87dbf349be7f2c89def80 100644 (file)
@@ -29,7 +29,7 @@
                     &iuml;&raquo;&iquest;#sidebar <a href="HashCommandsSidebar.html">HashCommandsSidebar</a><h1><a name="HKEYS _key_ (Redis &gt;">HKEYS _key_ (Redis &gt;</a></h1> 1.3.10)=
 <h1><a name="HVALS _key_ (Redis &gt;">HVALS _key_ (Redis &gt;</a></h1> 1.3.10)=
 <h1><a name="HGETALL _key_ (Redis &gt;">HGETALL _key_ (Redis &gt;</a></h1> 1.3.10)=
                     &iuml;&raquo;&iquest;#sidebar <a href="HashCommandsSidebar.html">HashCommandsSidebar</a><h1><a name="HKEYS _key_ (Redis &gt;">HKEYS _key_ (Redis &gt;</a></h1> 1.3.10)=
 <h1><a name="HVALS _key_ (Redis &gt;">HVALS _key_ (Redis &gt;</a></h1> 1.3.10)=
 <h1><a name="HGETALL _key_ (Redis &gt;">HGETALL _key_ (Redis &gt;</a></h1> 1.3.10)=
-<i>Time complexity: O(N), where N is the total number of entries</i><blockquote>HKEYS returns all the fields names contained into a hash, HVALS all the associated values, while HGETALL returns both the fields and values in the form of <i>field1</i>, <i>value1</i>, <i>field2</i>, <i>value2</i>, ..., <i>fieldN</i>, <i>valueN</i>.</blockquote>
+<i>Time complexity: O(N), where N is the total number of fields in the hash</i><blockquote>HKEYS returns all the fields names contained into a hash, HVALS all the associated values, while HGETALL returns both the fields and values in the form of <i>field1</i>, <i>value1</i>, <i>field2</i>, <i>value2</i>, ..., <i>fieldN</i>, <i>valueN</i>.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Multi Bulk Reply</a>
                 </div>
         
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Multi Bulk Reply</a>
                 </div>
         
index 26b2ba19f23c07ee4483968e8c871571d07f1cb6..82078aebaa54d3c5994c620f94514265e4ff0fcd 100644 (file)
@@ -79,7 +79,7 @@ $ ./redis-cli sismember myset 3
 (integer) 1
 $ ./redis-cli sismember myset 30
 (integer) 0
 (integer) 1
 $ ./redis-cli sismember myset 30
 (integer) 0
-</pre>&quot;3&quot; is a member of the set, while &quot;30&quot; is not. Sets are very good in order to express relations between objects. For instance we can easily Redis Sets in order to implement tags.<br/><br/>A simple way to model this is to have, for every object you want to tag, a Set with all the IDs of the tags associated with the object, and for every tag that exists, a Set of of all the objects tagged with this tag.<br/><br/>For instance if our news ID 1000 is tagged with tag 1,2,5 and 77, we can specify the following two Sets:<br/><br/><pre class="codeblock python python python python python python python" name="code">
+</pre>&quot;3&quot; is a member of the set, while &quot;30&quot; is not. Sets are very good in order to express relations between objects. For instance we can easily use Redis Sets in order to implement tags.<br/><br/>A simple way to model this is to have, for every object you want to tag, a Set with all the IDs of the tags associated with the object, and for every tag that exists, a Set of of all the objects tagged with this tag.<br/><br/>For instance if our news ID 1000 is tagged with tag 1,2,5 and 77, we can specify the following two Sets:<br/><br/><pre class="codeblock python python python python python python python" name="code">
 $ ./redis-cli sadd news:1000:tags 1
 (integer) 1
 $ ./redis-cli sadd news:1000:tags 2
 $ ./redis-cli sadd news:1000:tags 1
 (integer) 1
 $ ./redis-cli sadd news:1000:tags 2
@@ -143,7 +143,6 @@ $ ./redis-cli zrangebyscore hackers -inf 1950
 $ ./redis-cli zremrangebyscore hackers 1940 1960
 (integer) 2
 </pre><a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a> is not the best command name, but it can be very useful, and returns the number of removed elements.<h3><a name="Back to the reddit example">Back to the reddit example</a></h3>For the last time, back to the Reddit example. Now we have a decent plan to populate a sorted set in order to generate the home page. A sorted set can contain all the news that are not older than a few days (we remove old entries from time to time using ZREMRANGEBYSCORE). A background job gets all the elements from this sorted set, get the user votes and the time of the news, and compute the score to populate the <b>reddit.home.page</b> sorted set with the news IDs and associated scores. To show the home page we have just to perform a blazingly fast call to ZRANGE.<br/><br/>From time to time we'll remove too old news from the <b>reddit.home.page</b> sorted set as well in order for our system to work always against a limited set of news.<h3><a name="Updating the scores of a sorted set">Updating the scores of a sorted set</a></h3>Just a final note before to finish this tutorial. Sorted sets scores can be updated at any time. Just calling again ZADD against an element already included in the sorted set will update its score (and position) in O(log(N)), so sorted sets are suitable even when there are tons of updates.<br/><br/>This tutorial is in no way complete, this is just the basics to get started with Redis, read the <a href="CommandReference.html">Command Reference</a> to discover a lot more.<br/><br/>Thanks for reading. Salvatore.
 $ ./redis-cli zremrangebyscore hackers 1940 1960
 (integer) 2
 </pre><a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a> is not the best command name, but it can be very useful, and returns the number of removed elements.<h3><a name="Back to the reddit example">Back to the reddit example</a></h3>For the last time, back to the Reddit example. Now we have a decent plan to populate a sorted set in order to generate the home page. A sorted set can contain all the news that are not older than a few days (we remove old entries from time to time using ZREMRANGEBYSCORE). A background job gets all the elements from this sorted set, get the user votes and the time of the news, and compute the score to populate the <b>reddit.home.page</b> sorted set with the news IDs and associated scores. To show the home page we have just to perform a blazingly fast call to ZRANGE.<br/><br/>From time to time we'll remove too old news from the <b>reddit.home.page</b> sorted set as well in order for our system to work always against a limited set of news.<h3><a name="Updating the scores of a sorted set">Updating the scores of a sorted set</a></h3>Just a final note before to finish this tutorial. Sorted sets scores can be updated at any time. Just calling again ZADD against an element already included in the sorted set will update its score (and position) in O(log(N)), so sorted sets are suitable even when there are tons of updates.<br/><br/>This tutorial is in no way complete, this is just the basics to get started with Redis, read the <a href="CommandReference.html">Command Reference</a> to discover a lot more.<br/><br/>Thanks for reading. Salvatore.
-
                 </div>
         
             </div>
                 </div>
         
             </div>
index ae82792367f00efa342a8e05e8cadc0709031116..6a49d73d7b9444c17078e8e118779babc379d65e 100644 (file)
@@ -26,7 +26,7 @@
                 </div>
 
                 <div class="narrow">
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;== List Commands ==<br/><br/><ul><li> <a href="RpushCommand.html">RPUSH</a></li><li> <a href="RpushCommand.html">LPUSH</a></li><li> <a href="LlenCommand.html">LLEN</a></li><li> <a href="LrangeCommand.html">LRANGE</a></li><li> <a href="LtrimCommand.html">LTRIM</a></li><li> <a href="LindexCommand.html">LINDEX</a></li><li> <a href="LsetCommand.html">LSET</a></li><li> <a href="LremCommand.html">LREM</a></li><li> <a href="LpopCommand.html">LPOP</a></li><li> <a href="LpopCommand.html">RPOP</a></li><li> <a href="BlpopCommand.html">BLPOP</a></li><li> <a href="BlpopCommand.html">BRPOP</a></li><li> <a href="RpoplpushCommand.html">RPOPLPUSH</a></li><li> <a href="SortCommand.html">SORT</a></li></ul>
+                    &iuml;&raquo;&iquest;== List Commands ==<br/><br/><ul><li> <a href="RpushCommand.html">RPUSH</a></li><li> <a href="RpushCommand.html">LPUSH</a></li><li> <a href="LlenCommand.html">LLEN</a></li><li> <a href="LrangeCommand.html">LRANGE</a></li><li> <a href="LtrimCommand.html">LTRIM</a></li><li> <a href="LindexCommand.html">LINDEX</a></li><li> <a href="LsetCommand.html">LSET</a></li><li> <a href="LremCommand.html">LREM</a></li><li> <a href="LpopCommand.html">LPOP</a></li><li> <a href="LpopCommand.html">RPOP</a></li><li> <a href="BlpopCommand.html">BLPOP</a></li><li> <a href="BlpopCommand.html">BRPOP</a></li><li> <a href="RpoplpushCommand.html">RPOPLPUSH</a></li><li> <a href="BrpoplpushCommand.html">BRPOPLPUSH</a></li><li> <a href="SortCommand.html">SORT</a></li></ul>
                 </div>
         
             </div>
                 </div>
         
             </div>
index 65ec67a00279768462fe69af3a1d92aeccc241c2..97f21482a323ea7a0b3584da38e42ef7f6454920 100644 (file)
 <h1><a name="COMMAND_1 ...">COMMAND_1 ...</a></h1>
 <h1><a name="COMMAND_2 ...">COMMAND_2 ...</a></h1>
 <h1><a name="COMMAND_N ...">COMMAND_N ...</a></h1>
 <h1><a name="COMMAND_1 ...">COMMAND_1 ...</a></h1>
 <h1><a name="COMMAND_2 ...">COMMAND_2 ...</a></h1>
 <h1><a name="COMMAND_N ...">COMMAND_N ...</a></h1>
-<h1><a name="EXEC or DISCARD">EXEC or DISCARD</a></h1>MULTI, EXEC, DISCARD and WATCH commands are the fundation of Redis Transactions.
+<h1><a name="EXEC or DISCARD">EXEC or DISCARD</a></h1>MULTI, EXEC, DISCARD and WATCH commands are the foundation of Redis Transactions.
 A Redis Transaction allows the execution of a group of Redis commands in a single
 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>
 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
 replies with OK. At this point the user can issue multiple commands. Instead
 A Redis Transaction allows the execution of a group of Redis commands in a single
 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>
 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
 replies with OK. At this point the user can issue multiple commands. Instead
-to execute this commands Redis will &quot;queue&quot; them. All the commands are
+of executing these commands, Redis will &quot;queue&quot; them. All the commands are
 executed once EXEC is called.<br/><br/>Calling DISCARD instead will flush the transaction queue and will exit
 the transaction.<br/><br/>The following is an example using the Ruby client:
 <pre class="codeblock python" name="code">
 executed once EXEC is called.<br/><br/>Calling DISCARD instead will flush the transaction queue and will exit
 the transaction.<br/><br/>The following is an example using the Ruby client:
 <pre class="codeblock python" name="code">
@@ -57,7 +57,7 @@ replies, where every element is the reply of a single command in the
 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
 will reply with a simple string &quot;QUEUED&quot; if they are correct from the
 point of view of the syntax and arity (number of arguments) of the commaand.
 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
 will reply with a simple string &quot;QUEUED&quot; 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.<br/><br/>This is more clear if at protocol level: in the following example one command
+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
 will fail when executed even if the syntax is right:
 <pre class="codeblock python python" name="code">
 Trying 127.0.0.1...
 will fail when executed even if the syntax is right:
 <pre class="codeblock python python" name="code">
 Trying 127.0.0.1...
@@ -75,7 +75,7 @@ EXEC
 +OK
 -ERR Operation against a key holding the wrong kind of value
 </pre>
 +OK
 -ERR Operation against a key holding the wrong kind of value
 </pre>
-MULTI returned a two elements bulk reply in witch one of this is a +OK
+MULTI returned a two elements bulk reply where one is an +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.<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>
 Another example, again using the write protocol with telnet, shows how
 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.<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>
 Another example, again using the write protocol with telnet, shows how
@@ -87,9 +87,8 @@ INCR a b c
 -ERR wrong number of arguments for 'incr' command
 </pre>
 This time due to the syntax error the &quot;bad&quot; INCR command is not queued
 -ERR wrong number of arguments for 'incr' command
 </pre>
 This time due to the syntax error the &quot;bad&quot; INCR command is not queued
-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
-<blockquote>of a transaction. Example using the Ruby client:</blockquote><pre class="codeblock python python python python" name="code">
+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:
+<pre class="codeblock python python python python" name="code">
 ?&gt; r.set(&quot;foo&quot;,1)
 =&gt; true
 &gt;&gt; r.multi
 ?&gt; r.set(&quot;foo&quot;,1)
 =&gt; true
 &gt;&gt; r.multi
index 686c574e886196d04f74385a6b4d4bf7caa0f3a7..c69115efe6d0ecb72b737f504dcbc093b8ac7865 100644 (file)
@@ -16,7 +16,7 @@
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
-<b>ProtocolSpecification: Contents</b><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Networking layer">Networking layer</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Simple INLINE commands">Simple INLINE commands</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Bulk commands">Bulk commands</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Bulk replies">Bulk replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Multi-Bulk replies">Multi-Bulk replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Nil elements in Multi-Bulk replies">Nil elements in Multi-Bulk replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Single line reply">Single line reply</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Integer reply">Integer reply</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Multi bulk commands">Multi bulk commands</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Multiple commands and pipelining">Multiple commands and pipelining</a>
+<b>ProtocolSpecification: Contents</b><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Networking layer">Networking layer</a><br>&nbsp;&nbsp;<a href="#Requests">Requests</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#The new unified request protocol">The new unified request protocol</a><br>&nbsp;&nbsp;<a href="#Replies">Replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Single line reply">Single line reply</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Error reply">Error reply</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Integer reply">Integer reply</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Bulk replies">Bulk replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Multi-Bulk replies">Multi-Bulk replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Nil elements in Multi-Bulk replies">Nil elements in Multi-Bulk replies</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Multiple commands and pipelining">Multiple commands and pipelining</a><br>&nbsp;&nbsp;<a href="#The old protocol for sending commands">The old protocol for sending commands</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Inline Commands">Inline Commands</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Bulk commands">Bulk commands</a>
                 </div>
                 
                 <h1 class="wikiname">ProtocolSpecification</h1>
                 </div>
                 
                 <h1 class="wikiname">ProtocolSpecification</h1>
                 </div>
 
                 <div class="narrow">
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;= Protocol Specification =<br/><br/>The Redis protocol is a compromise between being easy to parse by a computer
-and being easy to parse by an human. Before reading this section you are
-strongly encouraged to read the &quot;REDIS TUTORIAL&quot; section of this README in order
-to get a first feeling of the protocol playing with it by TELNET.<h2><a name="Networking layer">Networking layer</a></h2>A client connects to a Redis server creating a TCP connection to the port 6379.
-Every redis command or data transmitted by the client and the server is
-terminated by &quot;\r\n&quot; (CRLF).<h2><a name="Simple INLINE commands">Simple INLINE commands</a></h2>The simplest commands are the inline commands. This is an example of a
-server/client chat (the server chat starts with S:, the client chat with C:)<br/><br/><pre class="codeblock python" name="code">
-C: PING
-S: +PONG
-</pre>An inline command is a CRLF-terminated string sent to the client. The server can reply to commands in different ways:
-<ul><li> With an error message (the first byte of the reply will be &quot;-&quot;)</li><li> With a single line reply (the first byte of the reply will be &quot;+)</li><li> With bulk data (the first byte of the reply will be &quot;$&quot;)</li><li> With multi-bulk data, a list of values (the first byte of the reply will be &quot;<code name="code" class="python">*</code>&quot;)</li><li> With an integer number (the first byte of the reply will be &quot;:&quot;)</li></ul>
-The following is another example of an INLINE command returning an integer:<br/><br/><pre class="codeblock python python" name="code">
-C: EXISTS somekey
-S: :0
-</pre>Since 'somekey' does not exist the server returned ':0'.<br/><br/>Note that the EXISTS command takes one argument. Arguments are separated
-simply by spaces.<h2><a name="Bulk commands">Bulk commands</a></h2>A bulk command is exactly like an inline command, but the last argument
-of the command must be a stream of bytes in order to send data to the server.
-the &quot;SET&quot; command is a bulk command, see the following example:<br/><br/><pre class="codeblock python python python" name="code">
-C: SET mykey 6
-C: foobar
-S: +OK
-</pre>The last argument of the commnad is '6'. This specify the number of DATA
-bytes that will follow (note that even this bytes are terminated by two
-additional bytes of CRLF).<br/><br/>All the bulk commands are in this exact form: instead of the last argument
-the number of bytes that will follow is specified, followed by the bytes,
-and CRLF. In order to be more clear for the programmer this is the string
-sent by the client in the above sample:<br/><br/><blockquote>&quot;SET mykey 6\r\nfoobar\r\n&quot;</blockquote>
-<h2><a name="Bulk replies">Bulk replies</a></h2>The server may reply to an inline or bulk command with a bulk reply. See
-the following example:<br/><br/><pre class="codeblock python python python python" name="code">
+                    &iuml;&raquo;&iquest;= Protocol Specification =<br/><br/>The Redis protocol is a compromise between the following things:<br/><br/><ul><li> Simple to implement.</li><li> Fast to parse by a computer.</li><li> Easy enough to parse by a human.</li></ul>
+<h2><a name="Networking layer">Networking layer</a></h2>A client connects to a Redis server creating a TCP connection to the port 6379.
+Every Redis command or data transmitted by the client and the server is
+terminated by &quot;\r\n&quot; (CRLF).<h1><a name="Requests">Requests</a></h1>Redis accepts commands composed of different arguments.
+Once a command is received, it is processed and a reply is sent back to the client.<h2><a name="The new unified request protocol">The new unified request protocol</a></h2>The new unified protocol was introduced in Redis 1.2, but it became the standard way for talking with the Redis server in Redis 2.0.<br/><br/>In the unified protocol all the arguments sent to the Redis server are binary safe. This is the general form:<br/><br/><pre class="codeblock python" name="code">
+*&lt;number of arguments&gt; CR LF
+$&lt;number of bytes of argument 1&gt; CR LF
+&lt;argument data&gt; CR LF
+...
+$&lt;number of bytes of argument N&gt; CR LF
+&lt;argument data&gt; CR LF
+</pre>See the following example:<br/><br/><pre class="codeblock python python" name="code">
+*3
+$3
+SET
+$5
+mykey
+$7
+myvalue
+</pre>This is how the above command looks as a quoted string, so that it is possible to see the exact value of every byte in the query:<br/><br/><pre class="codeblock python python python" name="code">
+&quot;*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$8\r\nmyvalue\r\n&quot;
+</pre>As you will see in a moment this format is also used in Redis replies.
+The format used for every argument &quot;$6\r\nmydata\r\n&quot; is called a Bulk Reply.
+While the actual unified request protocol is what Redis uses to return list of items, and is called a Multi Bulk Reply. It is just the sum of N different
+Bulk Replies prefixed by a <code name="code" class="python">*&lt;argc&gt;\r\n</code> string where <code name="code" class="python">&lt;argc&gt;</code> is the number of arguments (Bulk Replies) that will follow.<h1><a name="Replies">Replies</a></h1>Redis will reply to commands with different kinds of replies. It is possible to check the kind of reply from the first byte sent by the server:<br/><br/><ul><li> With a single line reply the first byte of the reply will be &quot;+&quot;</li><li> With an error message the first byte of the reply will be &quot;-&quot;</li><li> With an integer number the first byte of the reply will be &quot;:&quot;</li><li> With bulk reply the first byte of the reply will be &quot;$&quot;</li><li> With multi-bulk reply the first byte of the reply will be &quot;<code name="code" class="python">*</code>&quot;</li></ul>
+<h2><a name="Single line reply">Single line reply</a></h2>A single line reply is in the form of a single line string
+starting with &quot;+&quot; terminated by &quot;\r\n&quot;. For example:<br/><br/><pre class="codeblock python python python python" name="code">
++OK
+</pre>The client library should return everything after the &quot;+&quot;, that is, the string &quot;OK&quot; in the example.<br/><br/>The following commands reply with a single line reply:
+PING, SET, SELECT, SAVE, BGSAVE, SHUTDOWN, RENAME, LPUSH, RPUSH, LSET, LTRIM<h2><a name="Error reply">Error reply</a></h2>Errors are sent exactly like Single Line Replies. The only difference is that the first byte is &quot;-&quot; instead of &quot;+&quot;.<br/><br/>Error replies are only sent when something strange happened, for instance if you try to perform an operation against the wrong data type, or if the command does not exist and so forth. So an exception should be raised by the library client when an Error Reply is received.<h2><a name="Integer reply">Integer reply</a></h2>This type of reply is just a CRLF terminated string representing an integer, prefixed by a &quot;:&quot; byte. For example &quot;:0\r\n&quot;, or &quot;:1000\r\n&quot; are integer replies.<br/><br/>With commands like INCR or LASTSAVE using the integer reply to actually return a value there is no special meaning for the returned integer. It is just an incremental number for INCR, a UNIX time for LASTSAVE and so on.<br/><br/>Some commands like EXISTS will return 1 for true and 0 for false.<br/><br/>Other commands like SADD, SREM and SETNX will return 1 if the operation was actually done, 0 otherwise.<br/><br/>The following commands will reply with an integer reply: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD<h2><a name="Bulk replies">Bulk replies</a></h2>Bulk replies are used by the server in order to return a single binary safe string.<br/><br/><pre class="codeblock python python python python python" name="code">
 C: GET mykey
 S: $6
 S: foobar
 C: GET mykey
 S: $6
 S: foobar
-</pre>A bulk reply is very similar to the last argument of a bulk command. The
-server sends as the first line a &quot;$&quot; byte followed by the number of bytes
-of the actual reply followed by CRLF, then the bytes are sent followed by
-additional two bytes for the final CRLF. The exact sequence sent by the
-server is:<br/><br/><blockquote>&quot;$6\r\nfoobar\r\n&quot;</blockquote>
-If the requested value does not exist the bulk reply will use the special
-value -1 as data length, example:<br/><br/><pre class="codeblock python python python python python" name="code">
+</pre>The server sends as the first line a &quot;$&quot; byte followed by the number of bytes
+of the actual reply, followed by CRLF, then the actual data bytes are sent,
+followed by additional two bytes for the final CRLF.
+The exact sequence sent by the server is:<br/><br/><pre class="codeblock python python python python python python" name="code">
+&quot;$6\r\nfoobar\r\n&quot;
+</pre>If the requested value does not exist the bulk reply will use the special
+value -1 as data length, example:<br/><br/><pre class="codeblock python python python python python python python" name="code">
 C: GET nonexistingkey
 S: $-1
 </pre>The client library API should not return an empty string, but a nil object, when the requested object does not exist.
 For example a Ruby library should return 'nil' while a C library should return
 C: GET nonexistingkey
 S: $-1
 </pre>The client library API should not return an empty string, but a nil object, when the requested object does not exist.
 For example a Ruby library should return 'nil' while a C library should return
-NULL, and so forth.<h2><a name="Multi-Bulk replies">Multi-Bulk replies</a></h2>Commands similar to LRANGE needs to return multiple values (every element
+NULL (or set a special flag in the reply object), and so forth.<h2><a name="Multi-Bulk replies">Multi-Bulk replies</a></h2>Commands like LRANGE need to return multiple values (every element
 of the list is a value, and LRANGE needs to return more than a single element). This is accomplished using multiple bulk writes,
 prefixed by an initial line indicating how many bulk writes will follow.
 of the list is a value, and LRANGE needs to return more than a single element). This is accomplished using multiple bulk writes,
 prefixed by an initial line indicating how many bulk writes will follow.
-The first byte of a multi bulk reply is always <code name="code" class="python">*</code>. Example:<br/><br/><pre class="codeblock python python python python python python" name="code">
+The first byte of a multi bulk reply is always <code name="code" class="python">*</code>. Example:<br/><br/><pre class="codeblock python python python python python python python python" name="code">
 C: LRANGE mylist 0 3
 S: *4
 S: $3
 C: LRANGE mylist 0 3
 S: *4
 S: $3
@@ -83,56 +84,50 @@ S: $5
 S: Hello
 S: $5
 S: World
 S: Hello
 S: $5
 S: World
-</pre>The first line the server sent is &quot;<b>4\r\n&quot; in order to specify that four bulk
-write will follow. Then every bulk write is transmitted.<br/><br/>If the specified key does not exist instead of the number of elements in the
-list, the special value -1 is sent as count. Example:<br/><br/><pre class="codeblock python python python python python python python" name="code">
+</pre>As you can see the multi bulk reply is exactly the same format used in order
+to send commands to the Redis server unsing the unified protocol.<br/><br/>The first line the server sent is &quot;<b>4\r\n&quot; in order to specify that four bulk
+replies will follow. Then every bulk write is transmitted.<br/><br/>If the specified key does not exist, instead of the number of elements in the
+list the special value -1 is sent as count. Example:<br/><br/><pre class="codeblock python python python python python python python python python" name="code">
 C: LRANGE nokey 0 1
 S: *-1
 </pre>A client library API SHOULD return a nil object and not an empty list when this
 C: LRANGE nokey 0 1
 S: *-1
 </pre>A client library API SHOULD return a nil object and not an empty list when this
-happens. This makes possible to distinguish between empty list and non existing ones.<h2><a name="Nil elements in Multi-Bulk replies">Nil elements in Multi-Bulk replies</a></h2>Single elements of a multi bulk reply may have -1 length, in order to signal that this elements are missing and not empty strings. This can happen with the SORT command when used with the GET <i>pattern</i> option when the specified key is missing. Example of a multi bulk reply containing an empty element:<br/><br/><pre class="codeblock python python python python python python python python" name="code">
+happens. This makes possible to distinguish between empty list and other error conditions (for instance a timeout condition in the BLPOP command).<h2><a name="Nil elements in Multi-Bulk replies">Nil elements in Multi-Bulk replies</a></h2>Single elements of a multi bulk reply may have -1 length, in order to signal that this elements are missing and not empty strings. This can happen with the SORT command when used with the GET <i>pattern</i> option when the specified key is missing. Example of a multi bulk reply containing an empty element:<br/><br/><pre class="codeblock python python python python python python python python python python" name="code">
 S: *3
 S: $3
 S: foo
 S: $-1
 S: $3
 S: bar
 S: *3
 S: $3
 S: foo
 S: $-1
 S: $3
 S: bar
-</pre>The second element is nul. The client library should return something like this:<br/><br/><pre class="codeblock python python python python python python python python python" name="code">
+</pre>The second element is nul. The client library should return something like this:<br/><br/><pre class="codeblock python python python python python python python python python python python" name="code">
 [&quot;foo&quot;,nil,&quot;bar&quot;]
 [&quot;foo&quot;,nil,&quot;bar&quot;]
-</pre><h2><a name="Single line reply">Single line reply</a></h2>As already seen a single line reply is in the form of a single line string
-starting with &quot;+&quot; terminated by &quot;\r\n&quot;. For example:<br/><br/><pre class="codeblock python python python python python python python python python python" name="code">
-+OK
-</pre>The client library should return everything after the &quot;+&quot;, that is, the string &quot;OK&quot; in the example.<br/><br/>The following commands reply with a status code reply:
-PING, SET, SELECT, SAVE, BGSAVE, SHUTDOWN, RENAME, LPUSH, RPUSH, LSET, LTRIM<h2><a name="Integer reply">Integer reply</a></h2>This type of reply is just a CRLF terminated string representing an integer, prefixed by a &quot;:&quot; byte. For example &quot;:0\r\n&quot;, or &quot;:1000\r\n&quot; are integer replies.<br/><br/>With commands like INCR or LASTSAVE using the integer reply to actually return a value there is no special meaning for the returned integer. It is just an incremental number for INCR, a UNIX time for LASTSAVE and so on.<br/><br/>Some commands like EXISTS will return 1 for true and 0 for false.<br/><br/>Other commands like SADD, SREM and SETNX will return 1 if the operation was actually done, 0 otherwise.<br/><br/>The following commands will reply with an integer reply: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD<h2><a name="Multi bulk commands">Multi bulk commands</a></h2>As you can see with the protocol described so far there is no way to
-send multiple binary-safe arguments to a command. With bulk commands the
-last argument is binary safe, but there are commands where multiple binary-safe
-commands are needed, like the MSET command that is able to SET multiple keys
-in a single operation.<br/><br/>In order to address this problem Redis 1.1 introduced a new way of seding
-commands to a Redis server, that uses exactly the same protocol of the
-multi bulk replies. For instance the following is a SET command using the
-normal bulk protocol:<br/><br/><pre class="codeblock python python python python python python python python python python python" name="code">
-SET mykey 8
-myvalue
-</pre>While the following uses the multi bulk command protocol:<br/><br/><pre class="codeblock python python python python python python python python python python python python" name="code">
-*3
-$3
-SET
-$5
-mykey
-$8
-myvalue
-</pre>Commands sent in this format are longer, so currently they are used only in
-order to transmit commands containing multiple binary-safe arguments, but
-actually this protocol can be used to send every kind of command, without to
-know if it's an inline, bulk or multi-bulk command.<br/><br/>It is possible that in the future Redis will support only this format.<br/><br/>A good client library may implement unknown commands using this
-command format in order to support new commands out of the box without
-modifications.<h2><a name="Multiple commands and pipelining">Multiple commands and pipelining</a></h2>A client can use the same connection in order to issue multiple commands.
+</pre><h2><a name="Multiple commands and pipelining">Multiple commands and pipelining</a></h2>A client can use the same connection in order to issue multiple commands.
 Pipelining is supported so multiple commands can be sent with a single
 write operation by the client, it is not needed to read the server reply
 in order to issue the next command. All the replies can be read at the end.<br/><br/>Usually Redis server and client will have a very fast link so this is not
 very important to support this feature in a client implementation, still
 if an application needs to issue a very large number of commands in short
 Pipelining is supported so multiple commands can be sent with a single
 write operation by the client, it is not needed to read the server reply
 in order to issue the next command. All the replies can be read at the end.<br/><br/>Usually Redis server and client will have a very fast link so this is not
 very important to support this feature in a client implementation, still
 if an application needs to issue a very large number of commands in short
-time to use pipelining can be much faster.
-</b>
+time to use pipelining can be much faster.<h1><a name="The old protocol for sending commands">The old protocol for sending commands</a></h1>Before of the Unified Request Protocol Redis used a different protocol to send
+commands, that is still supported since it is simpler to type by hand via telnet. In this protocol there are two kind of commands:<br/><br/><blockquote>* Inline commands: simple commands where argumnets are just space separated strings. No binary safeness is possible.* Bulk commands: bulk commands are exactly like inline commands, but the last argument is handled in a special way in order to allow for a binary-safe last argument.</blockquote>
+<h2><a name="Inline Commands">Inline Commands</a></h2>The simplest way to send Redis a command is via </b>Inline Commands.
+The following is an example of a server/client chat using an inline command (the server chat starts with S:, the client chat with C:)<br/><br/><pre class="codeblock python python python python python python python python python python python python" name="code">
+C: PING
+S: +PONG
+</pre>The following is another example of an INLINE command returning an integer:<br/><br/><pre class="codeblock python python python python python python python python python python python python python" name="code">
+C: EXISTS somekey
+S: :0
+</pre>Since 'somekey' does not exist the server returned ':0'.<br/><br/>Note that the EXISTS command takes one argument. Arguments are separated
+by spaces.<h2><a name="Bulk commands">Bulk commands</a></h2>Some commands when sent as inline commands require a special form in order
+to support a binary safe last argument. This commands will use the last argument
+for a &quot;byte count&quot;, then the bulk data is sent (that can be binary safe since
+the server knows how many bytes to read).<br/><br/>See for instance the following example:<br/><br/><pre class="codeblock python python python python python python python python python python python python python python" name="code">
+C: SET mykey 6
+C: foobar
+S: +OK
+</pre>The last argument of the commnad is '6'. This specify the number of DATA
+bytes that will follow, that is, the string &quot;foobar&quot;. Note that even this bytes are terminated by two additional bytes of CRLF.<br/><br/>All the bulk commands are in this exact form: instead of the last argument
+the number of bytes that will follow is specified, followed by the bytes
+composing the argument itself, and CRLF. In order to be more clear for the programmer this is the string sent by the client in the above sample:<br/><br/><blockquote>&quot;SET mykey 6\r\nfoobar\r\n&quot;</blockquote>
+Redis has an internal list of what command is inline and what command is bulk, so you have to send this commands accordingly. It is strongly suggested to use the new Unified Request Protocol instead.
                 </div>
         
             </div>
                 </div>
         
             </div>
index c3d5d060854d5c606785946205e7a728f6229c3f..0fefe33ba11f1ac78a64616d18cddd21d8288330 100644 (file)
@@ -32,7 +32,7 @@
 <h1><a name="PSUBSCRIBE pattern_1 pattern_2 ... pattern_N">PSUBSCRIBE pattern_1 pattern_2 ... pattern_N</a></h1>
 <h1><a name="PUNSUBSCRIBE pattern_1 pattern_2 ... pattern_N">PUNSUBSCRIBE pattern_1 pattern_2 ... pattern_N</a></h1>
 <h1><a name="PUNSUBSCRIBE (unsubscribe from all patterns)">PUNSUBSCRIBE (unsubscribe from all patterns)</a></h1>
 <h1><a name="PSUBSCRIBE pattern_1 pattern_2 ... pattern_N">PSUBSCRIBE pattern_1 pattern_2 ... pattern_N</a></h1>
 <h1><a name="PUNSUBSCRIBE pattern_1 pattern_2 ... pattern_N">PUNSUBSCRIBE pattern_1 pattern_2 ... pattern_N</a></h1>
 <h1><a name="PUNSUBSCRIBE (unsubscribe from all patterns)">PUNSUBSCRIBE (unsubscribe from all patterns)</a></h1>
-<h1><a name="PUBLISH channel message">PUBLISH channel message</a></h1>Time complexity: subscribe is O(1), unsubscribe is O(N) where N is the number of clients already subscribed to a channel, publish is O(N+M) where N is the number of clients subscribed to the receiving channel, and M is the total number of subscribed patterns (by any client). Psubscribe is O(N) where N is the number of patterns the Psubscribing client is already subscribed to. Punsubscribe is O(N+M) where N is the number of patterns the Punsubscribing client is already subscribed and M is the number of total patterns subscribed in the system (by any client).<br/><br/><blockquote>SUBSCRIBE, UNSUBSCRIBE and PUBLISH commands implement the<a href="http://en.wikipedia.org/wiki/Publish/subscribe" target="_blank">Publish/Subscribe messaging paradigm</a> where (citing Wikipedia) senders (publishers) are not programmed to send their messages to specific receivers (subscribers). Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be. Subscribers express interest in one or more channels, and only receive messages that are of interest, without knowledge of what (if any) publishers there are. This decoupling of publishers and subscribers can allow for greater scalability and a more dynamic network topology.</blockquote>
+<h1><a name="PUBLISH channel message">PUBLISH channel message</a></h1>Time complexity: subscribe is O(1), unsubscribe is O(N) where N is the number of clients already subscribed to a channel, publish is O(N+M) where N is the number of clients subscribed to the receiving channel, and M is the total number of subscribed patterns (by any client). Psubscribe is O(N) where N is the number of patterns the Psubscribing client is already subscribed to. Punsubscribe is O(N+M) where N is the number of patterns the Punsubscribing client is already subscribed and M is the number of total patterns subscribed in the system (by any client).<br/><br/><b>Note</b>: this commands are available starting form Redis 2.0.0<br/><br/><blockquote>SUBSCRIBE, UNSUBSCRIBE and PUBLISH commands implement the<a href="http://en.wikipedia.org/wiki/Publish/subscribe" target="_blank">Publish/Subscribe messaging paradigm</a> where (citing Wikipedia) senders (publishers) are not programmed to send their messages to specific receivers (subscribers). Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be. Subscribers express interest in one or more channels, and only receive messages that are of interest, without knowledge of what (if any) publishers there are. This decoupling of publishers and subscribers can allow for greater scalability and a more dynamic network topology.</blockquote>
 <blockquote>For instance in order to subscribe to the channels foo and bar the clientwill issue the SUBSCRIBE command followed by the names of the channels.</blockquote><pre class="codeblock python" name="code">
 SUBSCRIBE foo bar
 </pre>
 <blockquote>For instance in order to subscribe to the channels foo and bar the clientwill issue the SUBSCRIBE command followed by the names of the channels.</blockquote><pre class="codeblock python" name="code">
 SUBSCRIBE foo bar
 </pre>
@@ -106,7 +106,6 @@ The Publish command is a bulk command where the first argument is the target cla
 Pieter Noordhuis provided a great example using Event-machine and Redis to create <a href="http://chat.redis-db.com" target="_blank">a multi user high performance web chat</a>, with source code included of course!
 <h2><a name="Client library implementations hints">Client library implementations hints</a></h2>
 Because all the messages received contain the original subscription causing the message delivery (the channel in the case of &quot;message&quot; type, and the original pattern in the case of &quot;pmessage&quot; type) clinet libraries may bind the original subscription to callbacks (that can be anonymous functions, blocks, function pointers, and so forth), using an hash table.<br/><br/>When a message is received an O(1) lookup can be done in order to deliver the message to the registered callback.
 Pieter Noordhuis provided a great example using Event-machine and Redis to create <a href="http://chat.redis-db.com" target="_blank">a multi user high performance web chat</a>, with source code included of course!
 <h2><a name="Client library implementations hints">Client library implementations hints</a></h2>
 Because all the messages received contain the original subscription causing the message delivery (the channel in the case of &quot;message&quot; type, and the original pattern in the case of &quot;pmessage&quot; type) clinet libraries may bind the original subscription to callbacks (that can be anonymous functions, blocks, function pointers, and so forth), using an hash table.<br/><br/>When a message is received an O(1) lookup can be done in order to deliver the message to the registered callback.
-
                 </div>
         
             </div>
                 </div>
         
             </div>
index 369b0cfbffeea0612173e355cb733e8949c6aa6c..78bc40e14eae3d8b95cb9fae667101853523d707 100644 (file)
@@ -26,7 +26,7 @@
                 </div>
 
                 <div class="narrow">
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;== String Commands ==<br/><br/><ul><li> <a href="SetCommand.html">SET</a></li><li> <a href="GetCommand.html">GET</a></li><li> <a href="GetsetCommand.html">GETSET</a></li><li> <a href="MgetCommand.html">MGET</a></li><li> <a href="SetnxCommand.html">SETNX</a></li><li> <a href="SetexCommand.html">SETEX</a></li><li> <a href="MsetCommand.html">MSET</a></li><li> <a href="MsetCommand.html">MSETNX</a></li><li> <a href="IncrCommand.html">INCR</a></li><li> <a href="IncrCommand.html">INCRBY</a></li><li> <a href="IncrCommand.html">DECR</a></li><li> <a href="IncrCommand.html">DECRBY</a></li><li> <a href="AppendCommand.html">APPEND</a></li><li> <a href="SubstrCommand.html">SUBSTR</a></li></ul>
+                    &iuml;&raquo;&iquest;== String Commands ==<br/><br/><ul><li> <a href="SetCommand.html">SET</a></li><li> <a href="GetCommand.html">GET</a></li><li> <a href="StrlenCommand.html">STRLEN</a></li><li> <a href="GetsetCommand.html">GETSET</a></li><li> <a href="SetnxCommand.html">SETNX</a></li><li> <a href="SetexCommand.html">SETEX</a></li><li> <a href="SetbitCommand.html">SETBIT</a></li><li> <a href="GetbitCommand.html">GETBIT</a></li><li> <a href="MsetCommand.html">MSET</a></li><li> <a href="MsetCommand.html">MSETNX</a></li><li> <a href="MgetCommand.html">MGET</a></li><li> <a href="IncrCommand.html">INCR</a></li><li> <a href="IncrCommand.html">INCRBY</a></li><li> <a href="IncrCommand.html">DECR</a></li><li> <a href="IncrCommand.html">DECRBY</a></li><li> <a href="AppendCommand.html">APPEND</a></li><li> <a href="SetrangeCommand.html">SETRANGE</a></li><li> <a href="SubstrCommand.html">GETRANGE (or SUBSTR)</a></li></ul>
                 </div>
         
             </div>
                 </div>
         
             </div>
index d05bf9285980ad1cc1c8535cbd8b5fbe0c90981c..010fbed7b1d2acf4bc012af1b45dcf6f27bfb93d 100644 (file)
@@ -26,7 +26,7 @@
                 </div>
 
                 <div class="narrow">
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;#sidebar <a href="StringCommandsSidebar.html">StringCommandsSidebar</a><h1><a name="Redis String Type">Redis String Type</a></h1>Strings are the most basic Redis kind of values. Redis Strings are binary safe, this means a Redis string can contain any kind of data, for instance a JPEG image or a serialized Ruby object, and so forth.<br/><br/>A String value can be at max 1 Gigabyte in length.<br/><br/>Strings are treated as integer values by the <a href="IncrCommand.html">INCR</a> commands family, in this respect the value of an intger is limited to a singed 64 bit value.<br/><br/>Note that the single elements contained in Redis <a href="Lists.html">Lists</a>, <a href="Sets.html">Sets</a> and <a href="SortedSets.html">Sorted Sets</a>, are Redis Strings.<h1><a name="Implementation details">Implementation details</a></h1>Strings are implemented using a dynamic strings library called <code name="code" class="python">sds.c</code> (simple dynamic strings). This library caches the current length of the string, so to obtain the length of a Redis string is an O(1) operation (but currently there is no such STRLEN command. It will likely be added later).<br/><br/>Redis strings are incapsualted into Redis Objects. Redis Objects use a reference counting memory management system, so a single Redis String can be shared in different places of the dataset. This means that if you happen to use the same strings many times (especially if you have <i>object sharing</i> turned on in the configuration file) Redis will try to use the same string object instead to allocate one new every time.<br/><br/>Starting from version 1.1 Redis is also able to encode in a special way strings that are actually just numbers. Instead to save the string as an array of characters Redis will save the integer value in order to use less memory. With many datasets this can reduce the memory usage of about 30% compared to Redis 1.0.
+                    &iuml;&raquo;&iquest;#sidebar <a href="StringCommandsSidebar.html">StringCommandsSidebar</a><h1><a name="Redis String Type">Redis String Type</a></h1>Strings are the most basic Redis kind of values. Redis Strings are binary safe, this means a Redis string can contain any kind of data, for instance a JPEG image or a serialized Ruby object, and so forth.<br/><br/>A String value can be at max 512 Megabytes in length.<br/><br/>Strings are treated as integer values by the <a href="IncrCommand.html">INCR</a> commands family, in this respect the value of an intger is limited to a singed 64 bit value.<br/><br/>Note that the single elements contained in Redis <a href="Lists.html">Lists</a>, <a href="Sets.html">Sets</a> and <a href="SortedSets.html">Sorted Sets</a>, are Redis Strings.<h1><a name="Implementation details">Implementation details</a></h1>Strings are implemented using a dynamic strings library called <code name="code" class="python">sds.c</code> (simple dynamic strings). This library caches the current length of the string, so to obtain the length of a Redis string is an O(1) operation (but currently there is no such STRLEN command. It will likely be added later).<br/><br/>Redis strings are incapsualted into Redis Objects. Redis Objects use a reference counting memory management system, so a single Redis String can be shared in different places of the dataset. This means that if you happen to use the same strings many times (especially if you have <i>object sharing</i> turned on in the configuration file) Redis will try to use the same string object instead to allocate one new every time.<br/><br/>Starting from version 1.1 Redis is also able to encode in a special way strings that are actually just numbers. Instead to save the string as an array of characters Redis will save the integer value in order to use less memory. With many datasets this can reduce the memory usage of about 30% compared to Redis 1.0.
 
                 </div>
         
 
                 </div>
         
index 3b6bdef0aa449c353b9cab371df2d3a70e552638..b5f4f792119392c735f8e55102a55bac79135aa1 100644 (file)
@@ -16,7 +16,7 @@
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
-<b>SubstrCommand: Contents</b><br>&nbsp;&nbsp;<a href="#SUBSTR _key_ _start_ _end_">SUBSTR _key_ _start_ _end_</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Examples">Examples</a>
+<b>SubstrCommand: Contents</b><br>&nbsp;&nbsp;<a href="#SUBSTR _key_ _start_ _end_">SUBSTR _key_ _start_ _end_</a><br>&nbsp;&nbsp;<a href="#GETRANGE _key_ _start_ _end_">GETRANGE _key_ _start_ _end_</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Examples">Examples</a>
                 </div>
                 
                 <h1 class="wikiname">SubstrCommand</h1>
                 </div>
                 
                 <h1 class="wikiname">SubstrCommand</h1>
@@ -27,7 +27,8 @@
 
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="StringCommandsSidebar.html">StringCommandsSidebar</a><h1><a name="SUBSTR _key_ _start_ _end_">SUBSTR _key_ _start_ _end_</a></h1>
 
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="StringCommandsSidebar.html">StringCommandsSidebar</a><h1><a name="SUBSTR _key_ _start_ _end_">SUBSTR _key_ _start_ _end_</a></h1>
-<i>Time complexity: O(start+n) (with start being the start index and n the total length of the requested range). Note that the lookup part of this command is O(1) so for small strings this is actually an O(1) command.</i><blockquote>Return a subset of the string from offset <i>start</i> to offset <i>end</i>(both offsets are inclusive).Negative offsets can be used in order to provide an offset starting fromthe end of the string. So -1 means the last char, -2 the penultimate andso forth.</blockquote>
+<h1><a name="GETRANGE _key_ _start_ _end_">GETRANGE _key_ _start_ _end_</a></h1>
+<i>Time complexity: O(start+n) (with start being the start index and n the total length of the requested range). Note that the lookup part of this command is O(1) so for small strings this is actually an O(1) command.</i><b>Warning:</b> this command was renamed into GETRANGE. SUBSTR will be taken as an alias until the next major release of Redis.<br/><br/><blockquote>Return a subset of the string from offset <i>start</i> to offset <i>end</i>(both offsets are inclusive).Negative offsets can be used in order to provide an offset starting fromthe end of the string. So -1 means the last char, -2 the penultimate andso forth.</blockquote>
 <blockquote>The function handles out of range requests without raising an error, butjust limiting the resulting range to the actual length of the string.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Bulk reply</a><h2><a name="Examples">Examples</a></h2><pre class="codeblock python" name="code">
 redis&gt; set s &quot;This is a string&quot;
 <blockquote>The function handles out of range requests without raising an error, butjust limiting the resulting range to the actual length of the string.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Bulk reply</a><h2><a name="Examples">Examples</a></h2><pre class="codeblock python" name="code">
 redis&gt; set s &quot;This is a string&quot;
index 7bc67b1580b773cff57bff64884fa48cbdb8f818..d4d6f759b89cfed0de79b17857e60fbe8ccde843 100644 (file)
@@ -39,7 +39,7 @@ vm-max-threads 4
 </pre>This is the maximum number of threads used in order to perform I/O from/to the swap file. A good value is just to match the number of cores in your system.<br/><br/>However the special value of &quot;0&quot; will enable blocking VM. When VM is configured to be blocking it performs the I/O in a synchronous blocking way. This is what you can expect from blocking VM:
 <ul><li> Clients accessing swapped out keys will block other clients while reading from disk, so the latency experimented by clients can be larger, especially if the disk is slow or busy and/or if there are big values swapped on disk.</li><li> The blocking VM performances are <b>overall</b> better, as there is no time lost in synchronization, spawning of threads, resuming blocked clients waiting for values.</li></ul>So if you are willing to accept an higher latency from time to time, blocking VM can be a good pick, especially if swapping happens rarely as most of your often accessed data happens to fit in your memory.<br/><br/>If instead you have a lot of swap in and swap out operations and you have many cores that you want to exploit, and in general when you don't want that clients dealing with swapped values will block other clients for a few milliseconds (or more if the swapped value is very big), then it's better to use threaded VM.<br/><br/>To experiment with your dataset and different configurations is warmly encouraged...<h1><a name="Random things to know">Random things to know</a></h1>
 <h2><a name="A good place for the swap file">A good place for the swap file</a></h2>In many configurations the swap file can be fairly large, even 40GB or more.
 </pre>This is the maximum number of threads used in order to perform I/O from/to the swap file. A good value is just to match the number of cores in your system.<br/><br/>However the special value of &quot;0&quot; will enable blocking VM. When VM is configured to be blocking it performs the I/O in a synchronous blocking way. This is what you can expect from blocking VM:
 <ul><li> Clients accessing swapped out keys will block other clients while reading from disk, so the latency experimented by clients can be larger, especially if the disk is slow or busy and/or if there are big values swapped on disk.</li><li> The blocking VM performances are <b>overall</b> better, as there is no time lost in synchronization, spawning of threads, resuming blocked clients waiting for values.</li></ul>So if you are willing to accept an higher latency from time to time, blocking VM can be a good pick, especially if swapping happens rarely as most of your often accessed data happens to fit in your memory.<br/><br/>If instead you have a lot of swap in and swap out operations and you have many cores that you want to exploit, and in general when you don't want that clients dealing with swapped values will block other clients for a few milliseconds (or more if the swapped value is very big), then it's better to use threaded VM.<br/><br/>To experiment with your dataset and different configurations is warmly encouraged...<h1><a name="Random things to know">Random things to know</a></h1>
 <h2><a name="A good place for the swap file">A good place for the swap file</a></h2>In many configurations the swap file can be fairly large, even 40GB or more.
-Not all the kind of file systems are able to deal with large files in a good way, especially Mac OS X file system tends to be really lame about it.<br/><br/>The suggestion is to use Linux ext3 file system, or any other file system with good support for <b>sparse files</b>. What are sparse files?<br/><br/>Sparse files are files where a lot of the content happen to be empty. Advanced file systems like ext2, ext3, ext4, RaiserFS, Raiser4, and many others, are able to encode this files in a more efficient way and will allocate more space for the file when needed, that is, when more actual blocks of the file will be used.<br/><br/>The swap file is obviously pretty sparse, especially if the server is running since little time or it is much bigger compared to the amount of data swapped out. A file system not supporting sparse files can at some point block the Redis process while creating a very big file at once.<br/><br/>For a list of file systems supporting spare files <a href="http://en.wikipedia.org/wiki/Comparison_of_file_systems" target="_blank">check this Wikipedia page comparing different files systems</a>.<h2><a name="Monitoring the VM">Monitoring the VM</a></h2>Once you have a Redis system with VM enabled up and running, you may be very interested in knowing how it's working: how many objects are swapped in total, the number of objects swapped and loaded every second, and so forth.<br/><br/>There is an utility that is very handy in checking how the VM is working, that is part of <a href="http://code.google.com/p/redis-tools" target="_blank">Redis Tools</a>. This tool is called redis-stat, and using it is pretty straightforward:<br/><br/><pre class="codeblock python python python" name="code">
+Not all the kind of file systems are able to deal with large files in a good way, especially Mac OS X file system tends to be really lame about it.<br/><br/>The suggestion is to use Linux ext3 file system, or any other file system with good support for <b>sparse files</b>. What are sparse files?<br/><br/>Sparse files are files where a lot of the content happen to be empty. Advanced file systems like ext2, ext3, ext4, RaiserFS, Raiser4, and many others, are able to encode this files in a more efficient way and will allocate more space for the file when needed, that is, when more actual blocks of the file will be used.<br/><br/>The swap file is obviously pretty sparse, especially if the server is running since little time or it is much bigger compared to the amount of data swapped out. A file system not supporting sparse files can at some point block the Redis process while creating a very big file at once.<br/><br/>For a list of file systems supporting spare files <a href="http://en.wikipedia.org/wiki/Comparison_of_file_systems" target="_blank">check this Wikipedia page comparing different files systems</a>.<h2><a name="Monitoring the VM">Monitoring the VM</a></h2>Once you have a Redis system with VM enabled up and running, you may be very interested in knowing how it's working: how many objects are swapped in total, the number of objects swapped and loaded every second, and so forth.<br/><br/>There is an utility that is very handy in checking how the VM is working, that is part of <a href="http://github.com/antirez/redis-tools" target="_blank">Redis Tools</a>. This tool is called redis-stat, and using it is pretty straightforward:<br/><br/><pre class="codeblock python python python" name="code">
 $ ./redis-stat vmstat
  --------------- objects --------------- ------ pages ------ ----- memory -----
  load-in  swap-out  swapped   delta      used     delta      used     delta    
 $ ./redis-stat vmstat
  --------------- objects --------------- ------ pages ------ ----- memory -----
  load-in  swap-out  swapped   delta      used     delta      used     delta    
@@ -57,7 +57,6 @@ $ ./redis-stat vmstat
  10087    18784     886771    -1574     894577   -1828     200.36M  +91.60K   
  9330     19350     887411    +640       894817   +240       200.17M  -189.72K 
 </pre>The above output is about a redis-server with VM enable, around 1 million of keys inside, and a lot of simulated load using the redis-load utility.<br/><br/>As you can see from the output a number of load-in and swap-out operations are happening every second. Note that the first line reports the actual values since the server was started, while the next lines are differences compared to the previous reading.<br/><br/>If you assigned enough memory to hold your working set of data, probably you should see a lot less dramatic swapping happening, so redis-stat can be a really valuable tool in order to understand if you need to shop for RAM ;)<h2><a name="Redis with VM enabled: better .rdb files or Append Only File?">Redis with VM enabled: better .rdb files or Append Only File?</a></h2>When VM is enabled, saving and loading the database are <b>much slower</b> operations. A DB that usually loads in 2 seconds takes 13 seconds with VM enabled if the server is configured to use the smallest memory possible (that is, vm-max-memory set to 0).<br/><br/>So you probably want to switch to a configuration using the Append Only File for persistence, so that you can perform the BGREWRITEAOF from time to time.<br/><br/>It is important to note that while a BGSAVE or BGREWRITEAOF is in progress Redis does <b>not</b> swap new values on disk. The VM will be read-only while there is another child accessing it. So if you have a lot of writes while there is a child working, the memory usage may grow.<h2><a name="Using as little memory as possible">Using as little memory as possible</a></h2>An interesting setup to turn Redis into an on-disk DB with just keys in memory is setting vm-max-memory to 0. If you don't mind some latency more and poorer performances but want to use very little memory for very big values, this is a good setup.<br/><br/>In this setup you should first try setting the VM as blocking (vm-max-threads 0) as with this configuration and high traffic the number of swap in and swap out operations will be huge, and threading will consume a lot of resources compared to a simple blocking implementation.<h2><a name="VM Stability">VM Stability</a></h2>VM is still experimental code, but in the latest weeks it was tested in many ways in development environments, and even in some production environment. No bugs were noticed during this testing period. Still the more obscure bugs may happen in non controlled environments where there are setups that we are not able to reproduce for some reason.<br/><br/>In this stage you are encouraged to try VM in your development environment, and even in production if your DB is not mission critical, but for instance just a big persistent cache of data that may go away without too much problems.<br/><br/>Please report any problem you will notice to the Redis Google Group or by IRC joining the #redis IRC channel on freenode.
  10087    18784     886771    -1574     894577   -1828     200.36M  +91.60K   
  9330     19350     887411    +640       894817   +240       200.17M  -189.72K 
 </pre>The above output is about a redis-server with VM enable, around 1 million of keys inside, and a lot of simulated load using the redis-load utility.<br/><br/>As you can see from the output a number of load-in and swap-out operations are happening every second. Note that the first line reports the actual values since the server was started, while the next lines are differences compared to the previous reading.<br/><br/>If you assigned enough memory to hold your working set of data, probably you should see a lot less dramatic swapping happening, so redis-stat can be a really valuable tool in order to understand if you need to shop for RAM ;)<h2><a name="Redis with VM enabled: better .rdb files or Append Only File?">Redis with VM enabled: better .rdb files or Append Only File?</a></h2>When VM is enabled, saving and loading the database are <b>much slower</b> operations. A DB that usually loads in 2 seconds takes 13 seconds with VM enabled if the server is configured to use the smallest memory possible (that is, vm-max-memory set to 0).<br/><br/>So you probably want to switch to a configuration using the Append Only File for persistence, so that you can perform the BGREWRITEAOF from time to time.<br/><br/>It is important to note that while a BGSAVE or BGREWRITEAOF is in progress Redis does <b>not</b> swap new values on disk. The VM will be read-only while there is another child accessing it. So if you have a lot of writes while there is a child working, the memory usage may grow.<h2><a name="Using as little memory as possible">Using as little memory as possible</a></h2>An interesting setup to turn Redis into an on-disk DB with just keys in memory is setting vm-max-memory to 0. If you don't mind some latency more and poorer performances but want to use very little memory for very big values, this is a good setup.<br/><br/>In this setup you should first try setting the VM as blocking (vm-max-threads 0) as with this configuration and high traffic the number of swap in and swap out operations will be huge, and threading will consume a lot of resources compared to a simple blocking implementation.<h2><a name="VM Stability">VM Stability</a></h2>VM is still experimental code, but in the latest weeks it was tested in many ways in development environments, and even in some production environment. No bugs were noticed during this testing period. Still the more obscure bugs may happen in non controlled environments where there are setups that we are not able to reproduce for some reason.<br/><br/>In this stage you are encouraged to try VM in your development environment, and even in production if your DB is not mission critical, but for instance just a big persistent cache of data that may go away without too much problems.<br/><br/>Please report any problem you will notice to the Redis Google Group or by IRC joining the #redis IRC channel on freenode.
-
                 </div>
         
             </div>
                 </div>
         
             </div>
index a0a3e39f38e69425314131a6fdfe2cd2b8ecd39c..ccf8c23ad728a142c9d5c0cf993fc714674fdd6a 100644 (file)
@@ -30,8 +30,9 @@
 <h1><a name="ZRANK _key_ _member_ (Redis &gt;">ZRANK _key_ _member_ (Redis &gt;</a></h1> 1.3.4) =
 <h1><a name="ZREVRANK _key_ _member_ (Redis &gt;">ZREVRANK _key_ _member_ (Redis &gt;</a></h1> 1.3.4) =
 <i>Time complexity: O(log(N))</i><blockquote>ZRANK returns the rank of the member in the sorted set, with scores ordered from low to high. ZREVRANK returns the rank with scores ordered from high to low. When the given member does not exist in the sorted set, the special value 'nil' is returned. The returned rank (or index) of the member is 0-based for both commands.</blockquote>
 <h1><a name="ZRANK _key_ _member_ (Redis &gt;">ZRANK _key_ _member_ (Redis &gt;</a></h1> 1.3.4) =
 <h1><a name="ZREVRANK _key_ _member_ (Redis &gt;">ZREVRANK _key_ _member_ (Redis &gt;</a></h1> 1.3.4) =
 <i>Time complexity: O(log(N))</i><blockquote>ZRANK returns the rank of the member in the sorted set, with scores ordered from low to high. ZREVRANK returns the rank with scores ordered from high to low. When the given member does not exist in the sorted set, the special value 'nil' is returned. The returned rank (or index) of the member is 0-based for both commands.</blockquote>
-<h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Bulk reply</a>, specifically:<br/><br/><pre class="codeblock python" name="code">
-the rank (an integer number) represented as an string.
+<h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Integer reply</a> or a nil <a href="ReplyTypes.html">bulk reply</a>, specifically:<br/><br/><pre class="codeblock python" name="code">
+the rank of the element as an integer reply if the element exists.
+A nil bulk reply if there is no such element.
 </pre>
                 </div>
         
 </pre>
                 </div>
         
index 1c72b230b3da1aaa3ef585ddc34b048b8e0bd249..38e1c9f5cea20e7f182a4b976e8dcfddbcbba24b 100644 (file)
@@ -16,7 +16,7 @@
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
             <div id="pagecontent">
                 <div class="index">
 <!-- This is a (PRE) block.  Make sure it's left aligned or your toc title will be off. -->
-<b>index: Contents</b><br>&nbsp;&nbsp;<a href="#HOWTOs about selected features">HOWTOs about selected features</a><br>&nbsp;&nbsp;<a href="#Hacking">Hacking</a><br>&nbsp;&nbsp;<a href="#Videos">Videos</a>
+<b>index: Contents</b><br>&nbsp;&nbsp;<a href="#Getting started">Getting started</a><br>&nbsp;&nbsp;<a href="#Full programming examples">Full programming examples</a><br>&nbsp;&nbsp;<a href="#FAQs and benchmarks">FAQs and benchmarks</a><br>&nbsp;&nbsp;<a href="#HOWTOs about selected features">HOWTOs about selected features</a><br>&nbsp;&nbsp;<a href="#Hacking">Hacking</a><br>&nbsp;&nbsp;<a href="#Videos">Videos</a><br>&nbsp;&nbsp;<a href="#Recipes and books">Recipes and books</a>
                 </div>
                 
                 <h1 class="wikiname">index</h1>
                 </div>
                 
                 <h1 class="wikiname">index</h1>
                 </div>
 
                 <div class="narrow">
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;= Redis Documentation =<br/><br/><a href="http://pyha.ru/wiki/index.php?title=Redis:index" target="_blank">Russian Translation</a>Hello! The followings are pointers to different parts of the Redis Documentation.<br/><br/><ul><li> New! You can now <a href="http://try.redis-db.com" target="_blank">Try Redis directly in your browser!</a>.</li><li> <a href="README.html">The README</a> is the best starting point to know more about the project.</li><li> <a href="QuickStart.html">This short Quick Start</a> provides a five minutes step-by-step istructions on how to download, compile, run and test the basic workings of a Redis server.</li><li> <a href="CommandReference.html">The command reference</a> is a description of all the Redis commands with links to command specific pages. You can also download the <a href="http://go2.wordpress.com/?id=725X1342&site=masonoise.wordpress.com&url=http%3A%2F%2Fmasonoise.files.wordpress.com%2F2010%2F03%2Fredis-cheatsheet-v1.pdf" target="_blank">Redis Commands Cheat-Sheet</a> provided by Mason Jones (btw some command may be missing, the primary source is the wiki).</li><li> <a href="TwitterAlikeExample.html">This is a tutorial about creating a Twitter clone using *only* Redis as database, no relational DB at all is used</a>, it is a good start to understand the key-value database paradigm.</li><li> <a href="IntroductionToRedisDataTypes.html">A Fifteen Minutes Introduction to the Redis Data Types</a> explains how Redis data types work and the basic patterns of working with Redis.</li><li> <a href="http://simonwillison.net/static/2010/redis-tutorial/" target="_blank">the Simon Willison Redis Tutorial</a> is a <b>must read</b>, very good documentation where you will find a lot of real world ideas and use cases.</li><li> <a href="Features.html">The features page</a> (currently in draft) is a good start to understand the strength and limitations of Redis.</li><li> <a href="Benchmarks.html">The benchmark page</a> is about the speed performances of Redis.</li><li> <a href="FAQ.html">Our FAQ</a> contains of course some answers to common questions about Redis.</li><li> <a href="http://www.rediscookbook.org/" target="_blank">The Redis Cookbook</a> is a collaborative effort to provide some good recipe ;)</li></ul>
-<h1><a name="HOWTOs about selected features">HOWTOs about selected features</a></h1><ul><li> <a href="ReplicationHowto.html">The Redis Replication HOWTO</a> is what you need to read in order to understand how Redis master <code name="code" class="python">&lt;-&gt;</code> slave replication works.</li><li> <a href="AppendOnlyFileHowto.html">The Append Only File HOWTO</a> explains how the alternative Redis durability mode works. AOF is an alternative to snapshotting on disk from time to time (the default).</li><li> <a href="VirtualMemoryUserGuide.html">Virtual Memory User Guide</a>. A simple to understand guide about using and configuring the Redis Virtual Memory.</li></ul>
+                    &iuml;&raquo;&iquest;= Redis Documentation =<br/><br/><a href="http://pyha.ru/wiki/index.php?title=Redis:index" target="_blank">Russian Translation</a>Hello! The followings are pointers to different parts of the Redis Documentation.<h1><a name="Getting started">Getting started</a></h1><ul><li> New! You can now <a href="http://try.redis-db.com" target="_blank">Try Redis directly in your browser!</a>.</li><li> <a href="README.html">The README</a> is a good starting point to know more about the project.</li><li> <a href="QuickStart.html">This short Quick Start</a> provides a five minutes step-by-step istructions on how to download, compile, run and test the basic workings of a Redis server.</li><li> <a href="CommandReference.html">The command reference</a> is a description of all the Redis commands with links to command specific pages. You can also download the <a href="http://go2.wordpress.com/?id=725X1342&site=masonoise.wordpress.com&url=http%3A%2F%2Fmasonoise.files.wordpress.com%2F2010%2F03%2Fredis-cheatsheet-v1.pdf" target="_blank">Redis Commands Cheat-Sheet</a> provided by Mason Jones (btw some command may be missing, the primary source is the wiki).</li><li> <a href="IntroductionToRedisDataTypes.html">A Fifteen Minutes Introduction to the Redis Data Types</a> explains how Redis data types work and the basic patterns of working with Redis.</li><li> <a href="http://simonwillison.net/static/2010/redis-tutorial/" target="_blank">the Simon Willison Redis Tutorial</a> is a <b>must read</b>, very good documentation where you will find a lot of real world ideas and use cases.</li><li> <a href="http://blog.mjrusso.com/2010/10/17/redis-from-the-ground-up.html" target="_blank">Redis from the ground up</a> is an impressive article to know more about Redis if you are a newcomer.</li><li> <a href="http://playnice.ly/blog/2010/10/19/getting-started-redis-python/" target="_blank">Getting started with Redis and Python</a></li></ul>
+<h1><a name="Full programming examples">Full programming examples</a></h1><ul><li> <a href="TwitterAlikeExample.html">This is a tutorial about creating a Twitter clone using *only* Redis as database, no relational DB at all is used</a>, it is a good start to understand the key-value database paradigm.</li></ul>
+<h1><a name="FAQs and benchmarks">FAQs and benchmarks</a></h1><ul><li> <a href="Benchmarks.html">The benchmark page</a> is about the speed performances of Redis.</li><li> <a href="FAQ.html">Our FAQ</a> contains of course some answers to common questions about Redis. Not very up-to-date.</li></ul>
+<h1><a name="HOWTOs about selected features">HOWTOs about selected features</a></h1><ul><li> <a href="ReplicationHowto.html">The Redis Replication HOWTO</a> is what you need to read in order to understand how Redis master <code name="code" class="python">&lt;-&gt;</code> slave replication works.</li><li> <a href="AppendOnlyFileHowto.html">The Append Only File HOWTO</a> explains how the alternative Redis durability mode works. AOF is an alternative to snapshotting on disk from time to time (the default).</li><li> <a href="VirtualMemoryUserGuide.html">Virtual Memory User Guide</a>. A simple to understand guide about using and configuring the Redis Virtual Memory.</li><li> <a href="RedisPipelining.html">Redis Pipelining Guide</a>.</li><li> Memory optimization: Full of keys, a <a href="http://antirez.com/post/redis-weekly-update-7.html" target="_blank">blog post at antirez.com</a> showing how to use Redis 2.0 and hashes to create a setup where you can store 5 times more data in your Redis instance.</li><li> <a href="http://antirez.com/post/autocomplete-with-redis.html" target="_blank">Implementing auto complete with Redis</a>.</li></ul>
 <h1><a name="Hacking">Hacking</a></h1>
 <h1><a name="Hacking">Hacking</a></h1>
-<ul><li> <a href="ProtocolSpecification.html">The Protocol Specification</a> is all you need in order to implement a Redis client library for a missing language. PHP, Python, Ruby and Erlang are already supported.</li></ul>
-<ul><li> Look at <a href="RedisInternals.html">Redis Internals</a> if you are interested in the implementation details of the Redis server.</li></ul>
-<h1><a name="Videos">Videos</a></h1><ul><li> <a href="http://mwrc2009.confreaks.com/13-mar-2009-19-24-redis-key-value-nirvana-ezra-zygmuntowicz.html" target="_blank">watch the Ezra Zygmuntowicz talk about Redis</a> to know the most important Redis ideas in few minutes.</li><li> <a href="http://www.ustream.tv/recorded/7855635" target="_blank">Salvatore Sanfilippo and Pieter Noordhuis at the SF Redis Meetup</a></li></ul>
+<ul><li> <a href="ProtocolSpecification.html">The Protocol Specification</a> is all you need in order to implement a Redis client library for a missing language. PHP, Python, Ruby and Erlang are already supported.</li><li> Look at <a href="RedisInternals.html">Redis Internals</a> if you are interested in the implementation details of the Redis server.</li></ul>
+<h1><a name="Videos">Videos</a></h1><ul><li> <a href="http://confreaks.net/videos/62-mwrc2009-redis-key-value-nirvana" target="_blank">Ezra Zygmuntowicz at the Mountain West Ruby Conference 2009</a> to know the most important Redis ideas in few minutes.</li><li> <a href="http://www.ustream.tv/recorded/7855635" target="_blank">Salvatore Sanfilippo and Pieter Noordhuis at the SF Redis Meetup</a></li></ul>
+<h1><a name="Recipes and books">Recipes and books</a></h1><ul><li> <a href="http://www.rediscookbook.org/" target="_blank">The Redis Cookbook</a> is a collaborative effort to provide some good recipe.</li><li> There is an ongoing effort to write a Redis book for O'Reilly</li></ul>
                 </div>
         
             </div>
                 </div>
         
             </div>
index 4578f00c32ec1b768cd3dc4e98edbe1721506c8e..abb69c09ec51ecb35554e12bb39abe9d56696bf1 100644 (file)
Binary files a/doc/redis.png and b/doc/redis.png differ