]> git.saurik.com Git - redis.git/commitdiff
html doc updated
authorantirez <antirez@gmail.com>
Tue, 15 Dec 2009 21:31:38 +0000 (16:31 -0500)
committerantirez <antirez@gmail.com>
Tue, 15 Dec 2009 21:31:38 +0000 (16:31 -0500)
17 files changed:
TODO
doc/BgrewriteaofCommand.html [new file with mode: 0644]
doc/CommandReference.html
doc/ControlCommandsSidebar.html
doc/Lists.html
doc/MsetCommand.html
doc/README.html
doc/Redis_1_2_0_Changelog.html [new file with mode: 0644]
doc/SaddCommand.html
doc/SdiffstoreCommand.html
doc/SetnxCommand.html
doc/Sets.html
doc/SortedSets.html
doc/SponsorshipHistory.html [new file with mode: 0644]
doc/SponsorshipHowto.html [new file with mode: 0644]
doc/SunionstoreCommand.html
doc/index.html

diff --git a/TODO b/TODO
index 8d4b711ed837d2fd3c85af4eb6c07c089aeb5c12..59c0bb14238ed41d0897593db0e3972860676159 100644 (file)
--- a/TODO
+++ b/TODO
@@ -5,8 +5,7 @@ VERSION 1.2 TODO (Zsets, Integer encoding, Append only journal)
 
 Most of the features already implemented for this release. The following is a list of the missing things in order to release the first beta tar.gz:
 
-* When Redis runs as slave make sure to set the fake client it uses to talk to the master as c->authenticated = 1 to avoid problems with slaves with requirepassword set.
-* Document BGREWRITEAOF.
+* Continue adding tests accordingly to gcov output.
 
 VERSION 1.4 TODO (Hash type)
 ============================
diff --git a/doc/BgrewriteaofCommand.html b/doc/BgrewriteaofCommand.html
new file mode 100644 (file)
index 0000000..61e51c3
--- /dev/null
@@ -0,0 +1,41 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+    <head>
+        <link type="text/css" rel="stylesheet" href="style.css" />
+    </head>
+    <body>
+        <div id="page">
+        
+            <div id='header'>
+            <a href="index.html">
+            <img style="border:none" alt="Redis Documentation" src="redis.png">
+            </a>
+            </div>
+        
+            <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>BgrewriteaofCommand: Contents</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#BGREWRITEAOF">BGREWRITEAOF</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a>
+                </div>
+                
+                <h1 class="wikiname">BgrewriteaofCommand</h1>
+
+                <div class="summary">
+                    
+                </div>
+
+                <div class="narrow">
+                    &iuml;&raquo;&iquest;#sidebar <a href="ControlCommandsSidebar.html">ControlCommandsSidebar</a><h3><a name="BGREWRITEAOF">BGREWRITEAOF</a></h3>
+<blockquote>Please for detailed information about the Redis Append Only File check<a href="AppendOnlyFileHowto.html">the Append Only File Howto</a>.</blockquote>
+<blockquote>BGREWRITEAOF rewrites the Append Only File in background when it gets toobig. The Redis Append Only File is a Journal, so every operation modifyingthe dataset is logged in the Append Only File (and replayed at startup).This means that the Append Only File always grows. In order to rebuildits content the BGREWRITEAOF creates a new version of the append only filestarting directly form the dataset in memory in order to guarantee thegeneration of the minimal number of commands needed to rebuild the database.</blockquote>
+<blockquote>The <a href="AppendOnlyFileHowto.html">Append Only File Howto</a> contains further details.</blockquote>
+<h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Status code reply</a>
+
+                </div>
+        
+            </div>
+        </div>
+    </body>
+</html>
+
index fb55c45a762cffa4a556733697ff66f1b63e4dc6..b2586d16ac4ca854b9db2b3b6055f54b32b6b371 100644 (file)
@@ -33,7 +33,7 @@
 <h2><a name="Commands operating on sets">Commands operating on sets</a></h2><ul><li> <a href="SaddCommand.html">SADD</a> <i>key</i> <i>member</i> <code name="code" class="python">Add the specified member to the Set value at key</code></li><li> <a href="SremCommand.html">SREM</a> <i>key</i> <i>member</i> <code name="code" class="python">Remove the specified member from the Set value at key</code></li><li> <a href="SpopCommand.html">SPOP</a> <i>key</i> <code name="code" class="python">Remove and return (pop) a random element from the Set value at key</code></li><li> <a href="SmoveCommand.html">SMOVE</a> <i>srckey</i> <i>dstkey</i> <i>member</i> <code name="code" class="python">Move the specified member from one Set to another atomically</code></li><li> <a href="ScardCommand.html">SCARD</a> <i>key</i> <code name="code" class="python">Return the number of elements (the cardinality) of the Set at key</code></li><li> <a href="SismemberCommand.html">SISMEMBER</a> <i>key</i> <i>member</i> <code name="code" class="python">Test if the specified value is a member of the Set at key</code></li><li> <a href="SinterCommand.html">SINTER</a> <i>key1</i> <i>key2</i> ... <i>keyN</i> <code name="code" class="python">Return the intersection between the Sets stored at key1, key2, ..., keyN</code></li><li> <a href="SinterstoreCommand.html">SINTERSTORE</a> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i> <code name="code" class="python">Compute the intersection between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey</code></li><li> <a href="SunionCommand.html">SUNION</a> <i>key1</i> <i>key2</i> ... <i>keyN</i> <code name="code" class="python">Return the union between the Sets stored at key1, key2, ..., keyN</code></li><li> <a href="SunionstoreCommand.html">SUNIONSTORE</a> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i> <code name="code" class="python">Compute the union between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey</code></li><li> <a href="SdiffCommand.html">SDIFF</a> <i>key1</i> <i>key2</i> ... <i>keyN</i> <code name="code" class="python">Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN</code></li><li> <a href="SdiffstoreCommand.html">SDIFFSTORE</a> <i>dstkey</i> <i>key1</i> <i>key2</i> ... <i>keyN</i> <code name="code" class="python">Compute the difference between the Set key1 and all the Sets key2, ..., keyN, and store the resulting Set at dstkey</code></li><li> <a href="SmembersCommand.html">SMEMBERS</a> <i>key</i> <code name="code" class="python">Return all the members of the Set value at key</code></li><li> <a href="SrandmemberCommand.html">SRANDMEMBER</a> <i>key</i> <code name="code" class="python">Return a random member of the Set value at key</code></li></ul>
 <h2><a name="Commands operating on sorted sets (zsets, Redis version &gt;">Commands operating on sorted sets (zsets, Redis version &gt;</a></h2> 1.1) ==<br/><br/><ul><li> <a href="ZaddCommand.html">ZADD</a> <i>key</i> <i>score</i> <i>member</i> <code name="code" class="python">Add the specified member to the Set value at key or update the score if it already exist</code></li><li> <a href="ZremCommand.html">ZREM</a> <i>key</i> <i>member</i> <code name="code" class="python">Remove the specified member from the Set value at key</code></li><li> <a href="ZrangeCommand.html">ZRANGE</a> <i>key</i> <i>start</i> <i>end</i> <code name="code" class="python">Return a range of elements from the sorted set at key</code></li><li> <a href="ZrangeCommand.html">ZREVRANGE</a> <i>key</i> <i>start</i> <i>end</i> <code name="code" class="python">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</code></li><li> <a href="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a> <i>key</i> <i>min</i> <i>max</i> <code name="code" class="python">Return all the elements with score &gt;= min and score &lt;= max (a range query) from the sorted set</code></li><li> <a href="ZcardCommand.html">ZCARD</a> <i>key</i> <code name="code" class="python">Return the cardinality (number of elements) of the sorted set at key</code></li><li> <a href="ZscoreCommand.html">ZSCORE</a> <i>key</i> <i>element</i> <code name="code" class="python">Return the score associated with the specified element of the sorted set at key</code></li><li> <a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a> <i>key</i> <i>min</i> <i>max</i> <code name="code" class="python">Remove all the elements with score &gt;= min and score &lt;= max from the sorted set</code></li></ul>
 <h2><a name="Sorting">Sorting</a></h2><ul><li> <a href="SortCommand.html">SORT</a> <i>key</i> BY <i>pattern</i> LIMIT <i>start</i> <i>end</i> GET <i>pattern</i> ASC|DESC ALPHA <code name="code" class="python">Sort a Set or a List accordingly to the specified parameters</code></li></ul>
-<h2><a name="Persistence control commands">Persistence control commands</a></h2><ul><li> <a href="SaveCommand.html">SAVE</a> <code name="code" class="python">Synchronously save the DB on disk</code></li><li> <a href="BgsaveCommand.html">BGSAVE</a> <code name="code" class="python">Asynchronously save the DB on disk</code></li><li> <a href="LastsaveCommand.html">LASTSAVE</a> <code name="code" class="python">Return the UNIX time stamp of the last successfully saving of the dataset on disk</code></li><li> <a href="ShutdownCommand.html">SHUTDOWN</a> <code name="code" class="python">Synchronously save the DB on disk, then shutdown the server</code></li></ul>
+<h2><a name="Persistence control commands">Persistence control commands</a></h2><ul><li> <a href="SaveCommand.html">SAVE</a> <code name="code" class="python">Synchronously save the DB on disk</code></li><li> <a href="BgsaveCommand.html">BGSAVE</a> <code name="code" class="python">Asynchronously save the DB on disk</code></li><li> <a href="LastsaveCommand.html">LASTSAVE</a> <code name="code" class="python">Return the UNIX time stamp of the last successfully saving of the dataset on disk</code></li><li> <a href="ShutdownCommand.html">SHUTDOWN</a> <code name="code" class="python">Synchronously save the DB on disk, then shutdown the server</code></li><li> <a href="BgrewriteaofCommand.html">BGREWRITEAOF</a> <code name="code" class="python">Rewrite the append only file in background when it gets too big</code></li></ul>
 <h2><a name="Remote server control commands">Remote server control commands</a></h2><ul><li> <a href="InfoCommand.html">INFO</a> <code name="code" class="python">Provide information and statistics about the server</code></li><li> <a href="MonitorCommand.html">MONITOR</a> <code name="code" class="python">Dump all the received requests in real time</code></li><li> <a href="SlaveofCommand.html">SLAVEOF</a> <code name="code" class="python">Change the replication settings</code></li></ul>
                 </div>
         
index e081134edef47ebb5bcf40ce9529982102c2fb9e..ba7d706d1e2ae17406681c75b04bcc76d3516f55 100644 (file)
@@ -26,7 +26,7 @@
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;== Control Commands ==<br/><br/><ul><li> <a href="SaveCommand.html">SAVE</a></li><li> <a href="BgsaveCommand.html">BGSAVE</a></li><li> <a href="LastsaveCommand.html">LASTSAVE</a></li><li> <a href="ShutdownCommand.html">SHUTDOWN</a></li><li> <a href="InfoCommand.html">INFO</a></li><li> <a href="MonitorCommand.html">MONITOR</a></li><li> <a href="SlaveofCommand.html">SLAVEOF</a></li></ul>
+                    &iuml;&raquo;&iquest;== Control Commands ==<br/><br/><ul><li> <a href="SaveCommand.html">SAVE</a></li><li> <a href="BgsaveCommand.html">BGSAVE</a></li><li> <a href="BgrewriteaofCommand.html">BGREWRITEAOF</a></li><li> <a href="LastsaveCommand.html">LASTSAVE</a></li><li> <a href="ShutdownCommand.html">SHUTDOWN</a></li><li> <a href="InfoCommand.html">INFO</a></li><li> <a href="MonitorCommand.html">MONITOR</a></li><li> <a href="SlaveofCommand.html">SLAVEOF</a></li></ul>
                 </div>
         
             </div>
index a79d9fd9bf7d48177f233e5288b24d75ad3ec545..5f71937f9be048bcccf08866d78b60b111c9faf0 100644 (file)
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;#sidebar <a href="ListCommandsSidebar.html">ListCommandsSidebar</a><h1><a name="Redis List Type">Redis List Type</a></h1>Redis Lists are lists of <a href="Stings.html">Redis Strings</a>, sorted by insertion order. It's possible to add elements to a Redis List pushing new elements on the head (on the left) or on the tail (on the right) of the list.<br/><br/>The <a href="RpushCommand.html">LPUSH</a> command inserts a new elmenet on head, while <a href="RpushCommand.html">RPUSH</a> inserts a new element on tail. A new list is created when one of this operations is performed against an empty key.<br/><br/>For instance if perform the following operations:
+                    &iuml;&raquo;&iquest;#sidebar <a href="ListCommandsSidebar.html">ListCommandsSidebar</a><h1><a name="Redis List Type">Redis List Type</a></h1>Redis Lists are lists of <a href="Strings.html">Redis Strings</a>, sorted by insertion order. It's possible to add elements to a Redis List pushing new elements on the head (on the left) or on the tail (on the right) of the list.<br/><br/>The <a href="RpushCommand.html">LPUSH</a> command inserts a new elmenet on head, while <a href="RpushCommand.html">RPUSH</a> inserts a new element on tail. A new list is created when one of this operations is performed against an empty key.<br/><br/>For instance if perform the following operations:
 <pre class="codeblock python" name="code">
 LPUSH mylist a   # now the list is &quot;a&quot;
 LPUSH mylist b   # now the list is &quot;b&quot;,&quot;a&quot;
 RPUSH mylist c   # now the list is &quot;b&quot;,&quot;a&quot;,&quot;c&quot; (RPUSH was used this time)
 </pre>
 The resulting list stored at <i>mylist</i> will contain the elements &quot;b&quot;,&quot;a&quot;,&quot;c&quot;.<br/><br/>The max length of a list is 232-1 elements (4294967295, more than 4 billion of elements per list).<h1><a name="Implementation details">Implementation details</a></h1>Redis Lists are implemented as doubly liked lists. A few commands benefit from the fact the lists are doubly linked in order to reach the needed element starting from the nearest extreme (head or tail). <a href="LrangeCommand.html">LRANGE</a> and <a href="LindexCommand.html">LINDEX</a> are examples of such commands.<br/><br/>The use of linked lists also guarantees that regardless of the length of the list pushing and popping are O(1) operations.<br/><br/>Redis Lists cache length information so <a href="LlenCommand.html">LLEN</a> is O(1) as well.
-
                 </div>
         
             </div>
index 5ef51c1caae1e6f298f62788e8438a8f9079644a..2b6bff0fe9f998eef4c7d01ad4e5f689d3996cf2 100644 (file)
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="StringCommandsSidebar.html">StringCommandsSidebar</a><h1><a name="MSET _key1_ _value1_ _key2_ _value2_ ... _keyN_ _valueN_ (Redis &gt;">MSET _key1_ _value1_ _key2_ _value2_ ... _keyN_ _valueN_ (Redis &gt;</a></h1> 1.1) =
 <h1><a name="MSETNX _key1_ _value1_ _key2_ _value2_ ... _keyN_ _valueN_ (Redis &gt;">MSETNX _key1_ _value1_ _key2_ _value2_ ... _keyN_ _valueN_ (Redis &gt;</a></h1> 1.1) =
-<i>Time complexity: O(1) to set every key</i><blockquote>Set the the rispective keys to the rispective values. MSET will replace oldvalues with new values, while MSETNX will not perform any operation at alleven if just a single key already exists.</blockquote>
+<i>Time complexity: O(1) to set every key</i><blockquote>Set the the respective keys to the respective values. MSET will replace oldvalues with new values, while MSETNX will not perform any operation at alleven if just a single key already exists.</blockquote>
 <blockquote>Because of this semantic MSETNX can be used in order to set different keysrepresenting different fields of an unique logic object in a way thatensures that either all the fields or none at all are set.</blockquote>
 <blockquote>Both MSET and MSETNX are atomic operations. This means that for instanceif the keys A and B are modified, another client talking to Redis can eithersee the changes to both A and B at once, or no modification at all.</blockquote>
 <h2><a name="MSET Return value">MSET Return value</a></h2><a href="ReplyTypes.html">Status code reply</a> Basically +OK as MSET can't fail<h2><a name="MSETNX Return value">MSETNX Return value</a></h2><a href="ReplyTypes.html">Integer reply</a>, specifically:<br/><br/><pre class="codeblock python" name="code">
 1 if the all the keys were set
 0 if no key was set (at least one key already existed)
 </pre>
-
                 </div>
         
             </div>
index 2cdeb5c7a7b72a63cee3520479ddbeb22406d195..f70fe83f043062ca9b6a0cdce9defb10996397ac 100644 (file)
@@ -27,7 +27,7 @@
 
                 <div class="narrow">
                     &iuml;&raquo;&iquest;= Introduction =<br/><br/>Redis is a database. To be specific, Redis is a database implementing a dictionary, where every key is associated with a value. For example I can set the key &quot;surname_1992&quot; to the string &quot;Smith&quot;.
-What makes Redis different from many other key-value stores, is that every single value has a type. The following types are supported:<br/><br/><ul><li> String</li><li> List</li><li> Set</li><li> Sorted Set (since version 1.1)</li></ul>
+What makes Redis different from many other key-value stores, is that every single value has a type. The following types are supported:<br/><br/><ul><li> <a href="Strings.html">Strings</a></li><li> <a href="Lists.html">Lists</a></li><li> <a href="Sets.html">Sets</a></li><li> <a href="SortedSets.html">Sorted Set</a> (since version 1.1)</li></ul>
 The type of a value determines what operations (called commands) are available for the value itself. 
 For example you can append elements to a list stored at the key &quot;mylist&quot; using the LPUSH or RPUSH command in O(1). Later you'll be able to get a range of elements with LRANGE or trim the list with LTRIM. Sets are very flexible too, it is possible to add and remove elements from Sets (unsorted collections of strings), and then ask for server-side intersection, union, difference of Sets. Each command is performed through server-side atomic operations.
 Please refer to the <a href="CommandReference.html">Command Reference</a> to see the full list of operations associated to these data types.<br/><br/>In other words, you can look at Redis as a data structures server. A Redis user is virtually provided with an interface to  <a href="http://en.wikipedia.org/wiki/Abstract_data_type" target="_blank">Abstract Data Types</a>, saving her from the responsibility to implement concrete data structures and algorithms. Indeed both algorithms and data structures in Redis are properly choosed in order to obtain the best performance.<h1><a name="All data in memory, but saved on disk">All data in memory, but saved on disk</a></h1>Redis loads and mantains the whole dataset into memory, but the dataset is persistent, since at the same time it is saved on disk, so that when the server is restarted data can be loaded back in memory.<br/><br/>There are two kind of persistence supported: the first one is called snapshotting. In this mode Redis, from time to time, writes a dump on disk asynchronously. The dataset is loaded from the dump every time the server is (re)started.<br/><br/>Redis can be configured to save the dataset when a certain number of changes is reached and after a given number of seconds elapses. For example, you can configure Redis to save after 1000 changes and at most 60 seconds since the last save. You can specify any combination for these numbers.<br/><br/>Because data is written asynchronously, when a system crash occurs, the last few queries can get lost (that is acceptable in many applications but not in all).  In order to make this a non issue Redis supports another, safer persistence mode, called <a href="AppendOnlyFileHowto.html">Append Only File</a>, where every command received altering the dataset (so not a read-only command, but a write command) is written on an append only file ASAP. This commands are <i>replayed</i> when the server is restarted in order to rebuild the dataset in memory.<br/><br/>Redis Append Only File supports a very handy feature: the server is able to safely rebuild the append only file in background in a non-blocking fashion when it gets too long. You can find <a href="AppendOnlyFileHowto.html">more details in the Append Only File HOWTO</a>.<h1><a name="Master-Slave replication made trivial">Master-Slave replication made trivial</a></h1>Whatever will be the persistence mode you'll use Redis supports master-slave replications if you want to stay really safe or if you need to scale to huge amounts of reads.<br/><br/><b>Redis Replication is trivial to setup</b>. So trivial that all you need to do in order to configure a Redis server to be a slave of another one, with automatic synchronization if the link will go down and so forth, is the following config line: <code name="code" class="python">slaveof 192.168.1.100 6379</code>. <a href="ReplicationHowto.html">We provide a Replication Howto</a> if you want to know more about this feature.<h1><a name="It's persistent but supports expires">It's persistent but supports expires</a></h1>Redis can be used as a <b>memcached on steroids</b> because is as fast as memcached but with a number of features more. Like memcached, Redis also supports setting timeouts to keys so that this key will be automatically removed when a given amount of time passes.<h1><a name="Beyond key-value databases">Beyond key-value databases</a></h1>All these features allow to use Redis as the sole DB for your scalable application without the need of any relational database. <a href="TwitterAlikeExample.html">We wrote a simple Twitter clone in PHP + Redis</a> to show a real world example, the link points to an article explaining the design and internals in very simple words.<h1><a name="Multiple databases support">Multiple databases support</a></h1>Redis supports multiple databases with commands to atomically move keys from one database to the other. By default DB 0 is selected for every new connection, but using the SELECT command it is possible to select a different database. The MOVE operation can move an item from one DB to another atomically. This can be used as a base for locking free algorithms together with the 'RANDOMKEY' commands.<h1><a name="Know more about Redis!">Know more about Redis!</a></h1>To really get a feeling about what Redis is and how it works please try reading <a href="IntroductionToRedisDataTypes.html">A fifteen minutes introduction to Redis data types</a>.<br/><br/>To know a bit more about how Redis works <i>internally</i> continue reading.<h1><a name="Redis Tutorial">Redis Tutorial</a></h1>(note, you can skip this section if you are only interested in &quot;formal&quot; doc.)<br/><br/>Later in this document you can find detailed information about Redis commands,
@@ -79,7 +79,6 @@ exist, and ':1' for 'foo', a key that actually exists. Replies starting with the
 learn all the commands supported by Redis and the <a href="ProtocolSpecification.html">PROTOCOL SPECIFICATION</a>
 section for more details about the protocol used if you plan to implement one
 for a language missing a decent client implementation.<h1><a name="License">License</a></h1>Redis is released under the BSD license. See the COPYING file for more information.<h1><a name="Credits">Credits</a></h1>Redis is written and maintained by Salvatore Sanfilippo, Aka 'antirez'.
-
                 </div>
         
             </div>
diff --git a/doc/Redis_1_2_0_Changelog.html b/doc/Redis_1_2_0_Changelog.html
new file mode 100644 (file)
index 0000000..c57f56b
--- /dev/null
@@ -0,0 +1,36 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+    <head>
+        <link type="text/css" rel="stylesheet" href="style.css" />
+    </head>
+    <body>
+        <div id="page">
+        
+            <div id='header'>
+            <a href="index.html">
+            <img style="border:none" alt="Redis Documentation" src="redis.png">
+            </a>
+            </div>
+        
+            <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>Redis_1_2_0_Changelog: Contents</b><br>&nbsp;&nbsp;<a href="#CHANGELOG for Redis 1.1.90">CHANGELOG for Redis 1.1.90</a>
+                </div>
+                
+                <h1 class="wikiname">Redis_1_2_0_Changelog</h1>
+
+                <div class="summary">
+                    
+                </div>
+
+                <div class="narrow">
+                    <h1><a name="CHANGELOG for Redis 1.1.90">CHANGELOG for Redis 1.1.90</a></h1><ul><li> 2009-09-10 in-memory specialized object encoding. (antirez)</li><li> 2009-09-17 maxmemory fixed in 64 systems for values &gt; 4GB. (antirez)</li><li> 2009-10-07 multi-bulk protocol implemented. (antriez)</li><li> 2009-10-16 MSET and MSETNX commands implemented (antirez)</li><li> 2009-10-21 SRANDMEMBER added (antirez)</li><li> 2009-10-23 Fixed compilation in mac os x snow leopard when compiling a 32 bit binary.  (antirez)</li><li> 2009-10-23 New data type: Sorted sets and Z-commands (antirez)</li><li> 2009-10-26 Solaris fixed (Alan Harder)</li><li> 2009-10-29 Fixed Issue a number of open issues (antirez)</li><li> 2009-10-30 New persistence mode: append only file (antirez)</li><li> 2009-11-01 SORT STORE option (antirez)</li><li> 2009-11-03 redis-cli now accepts a -r (repeat) switch. (antirez)</li><li> 2009-11-04 masterauth option merged (Anthony Lauzon)</li><li> 2009-11-04 redis-test is now a better Redis citizen, testing everything against DB 9 and 10 and only if this DBs are empty. (antirez)</li><li> 2009-11-10 Implemented a much better lazy expiring algorithm for EXPIRE (antirez)</li><li> 2009-11-11 RPUSHLPOP (antirez from an idea of @ezmobius)</li><li> 2009-11-12 Merge git://github.com/ianxm/redis (Can't remmber what this implements, sorry)</li><li> 2009-11-17 multi-bulk reply support for redis-bench, LRANGE speed tests (antirez)</li><li> 2009-11-17 support for writev implemented. (Stefano Barbato)</li><li> 2009-11-19 debug mode (-D) in redis-bench (antirez)</li><li> 2009-11-21 SORT GET # implemented (antirez)</li><li> 2009-11-23 ae.c made modular, with support for epoll. (antirez)</li><li> 2009-11-26 background append log rebuilding (antirez)</li><li> 2009-11-28 Added support for kqueue. (Harish Mallipeddi)</li><li> 2009-11-29 SORT support for sorted sets (antirez, thanks to @tobi for the idea)</li></ul>
+                </div>
+        
+            </div>
+        </div>
+    </body>
+</html>
+
index 699ff22d4105fa186a70ce05ad474eb272a3ffe3..57c2dfadbf4d53f876c0d4cd4b1e6aaef8ec7751 100644 (file)
 
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="SetCommandsSidebar.html">SetCommandsSidebar</a><h1><a name="SADD _key_ _member_">SADD _key_ _member_</a></h1>
-<i>Time complexity O(1)</i><blockquote>Add the specified <i>member</i> to the set value stored at <i>key</i>. If <i>member</i>is already a member of the set no operation is performed. If <i>key</i>does not exist a new set with the specified <i>member</i> as sole member iscrated. If the key exists but does not hold a set value an error isreturned.</blockquote>
+<i>Time complexity O(1)</i><blockquote>Add the specified <i>member</i> to the set value stored at <i>key</i>. If <i>member</i>is already a member of the set no operation is performed. If <i>key</i>does not exist a new set with the specified <i>member</i> as sole member iscreated. If the key exists but does not hold a set value an error isreturned.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Integer reply</a>, specifically:<br/><br/><pre class="codeblock python" name="code">
 1 if the new element was added
 0 if the element was already a member of the set
 </pre>
-
                 </div>
         
             </div>
index 93713ac3ec354ae842a4aface7edabf8edb43865..91962acbfb2039750def5a1a8d4952ef4b118555 100644 (file)
@@ -27,9 +27,8 @@
 
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="SetCommandsSidebar.html">SetCommandsSidebar</a><h1><a name="SDIFFSTORE _dstkey_ _key1_ _key2_ ... _keyN_">SDIFFSTORE _dstkey_ _key1_ _key2_ ... _keyN_</a></h1>
-<i>Time complexity O(N) where N is the total number of elements in all the provided sets</i><blockquote>This commnad works exactly like SDIFF but instead of being returned the resulting set is sotred in <i>dstkey</i>.</blockquote>
+<i>Time complexity O(N) where N is the total number of elements in all the provided sets</i><blockquote>This command works exactly like SDIFF but instead of being returned the resulting set is stored in <i>dstkey</i>.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Status code reply</a>
-
                 </div>
         
             </div>
index 91f9206d8e368d009ae36674d5a195ff7e2cbfa9..8c47e72d671575df194a56c85ad4c5344897f47e 100644 (file)
@@ -41,6 +41,7 @@ SETNX lock.foo &lt;current UNIX time + lock timeout + 1&gt;
 <ul><li> C1 and C2 read lock.foo to check the timestamp, because SETNX returned 0 to both C1 and C2, as the lock is still hold by C3 that crashed after holding the lock.</li><li> C1 sends DEL lock.foo</li><li> C1 sends SETNX =&gt; success!</li><li> C2 sends DEL lock.foo</li><li> C2 sends SETNX =&gt; success!</li><li> ERROR: both C1 and C2 acquired the lock because of the race condition.</li></ul>
 <blockquote>Fortunately it's possible to avoid this issue using the following algorithm.Let's see how C4, our sane client, uses the good algorithm:</blockquote>
 <ul><li> C4 sends SETNX lock.foo in order to acquire the lock</li><li> The crashed C3 client still holds it, so Redis will reply with 0 to C4.</li><li> C4 GET lock.foo to check if the lock expired. If not it will sleep one second (for instance) and retry from the start.</li><li> If instead the lock is expired because the UNIX time at lock.foo is older than the current UNIX time, C4 tries to perform GETSET lock.foo &lt;current unix timestamp + lock timeout + 1&gt;</li><li> Thanks to the <a href="GetsetCommand.html">GETSET</a> command semantic C4 can check if the old value stored at key is still an expired timestamp. If so we acquired the lock!</li><li> Otherwise if another client, for instance C5, was faster than C4 and acquired the lock with the GETSET operation, C4 GETSET operation will return a non expired timestamp. C4 will simply restart from the first step. Note that even if C4 set the key a bit a few seconds in the future this is not a problem.</li></ul>
+IMPORTANT NOTE: In order to make this locking algorithm more robust, a client holding a lock should always check the timeout didn't expired before to unlock the key with DEL because client failures can be complex, not just crashing but also blocking a lot of time against some operation and trying to issue DEL after a lot of time (when the LOCK is already hold by some other client).
                 </div>
         
             </div>
index db7e7f9dde138caa3b6d04a14777d2cf21d00dce..19fe7f80652c1cff4e2fe795660ed603c190bf39 100644 (file)
@@ -26,8 +26,7 @@
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;#sidebar <a href="SetCommandsSidebar.html">SetCommandsSidebar</a><h1><a name="Redis Set Type">Redis Set Type</a></h1>Redis Sets are unordered collections of <a href="Stings.html">Redis Strings</a>. It's possible to add, remove, and test for existence of members in O(1).<br/><br/>Redis Sets have the desirable property of not allowing repeated members. Adding the same element multiple times will result in a set having a single copy of this element. Practically speaking this means that adding an members does not require a &quot;check if exists then add&quot; operation.<br/><br/>Commands operating on sets try to make a good use of the return value in order to signal the application about previous existence of members. For instance the <a href="SaddCommand.html">SADD</a> command will return 1 if the element added was not already a member of the set, otherwise will return 0.<br/><br/>The max number of members in a set is 232-1 (4294967295, more than 4 billion of members per set).<br/><br/>Redis Sets support a wide range of operations, like union, intersection, difference. Intersection is optimized in order to perform the smallest number of lookups. For instance if you try to intersect a 10000 members set with a 2 members set Redis will iterate the 2 members set testing for members existence in the other set, performing 2 lookups instead of 10000.<h1><a name="Implementation details">Implementation details</a></h1>Redis Sets are implemented using hash tables, so adding, removing and testing for members is O(1) in the average. The hash table will automatically resize when new elements are added or removed into a Set.<br/><br/>The hash table resizing is a blocking operation performed synchronously so working with huge sets (consisting of many millions of elements) care should be taken when mass-inserting a very big amount of elements in a Set while other clients are querying Redis at high speed.<br/><br/>It is possible that in the near future Redis will switch to skip lists (already used in sorted sets) in order to avoid such a problem.
-
+                    &iuml;&raquo;&iquest;#sidebar <a href="SetCommandsSidebar.html">SetCommandsSidebar</a><h1><a name="Redis Set Type">Redis Set Type</a></h1>Redis Sets are unordered collections of <a href="Strings.html">Redis Strings</a>. It's possible to add, remove, and test for existence of members in O(1).<br/><br/>Redis Sets have the desirable property of not allowing repeated members. Adding the same element multiple times will result in a set having a single copy of this element. Practically speaking this means that adding an members does not require a &quot;check if exists then add&quot; operation.<br/><br/>Commands operating on sets try to make a good use of the return value in order to signal the application about previous existence of members. For instance the <a href="SaddCommand.html">SADD</a> command will return 1 if the element added was not already a member of the set, otherwise will return 0.<br/><br/>The max number of members in a set is 232-1 (4294967295, more than 4 billion of members per set).<br/><br/>Redis Sets support a wide range of operations, like union, intersection, difference. Intersection is optimized in order to perform the smallest number of lookups. For instance if you try to intersect a 10000 members set with a 2 members set Redis will iterate the 2 members set testing for members existence in the other set, performing 2 lookups instead of 10000.<h1><a name="Implementation details">Implementation details</a></h1>Redis Sets are implemented using hash tables, so adding, removing and testing for members is O(1) in the average. The hash table will automatically resize when new elements are added or removed into a Set.<br/><br/>The hash table resizing is a blocking operation performed synchronously so working with huge sets (consisting of many millions of elements) care should be taken when mass-inserting a very big amount of elements in a Set while other clients are querying Redis at high speed.<br/><br/>It is possible that in the near future Redis will switch to skip lists (already used in sorted sets) in order to avoid such a problem.
                 </div>
         
             </div>
index 2a619cf9170976c0026ae5ac90236b2d10e75c08..e31550b595b764270559a711dab50b5bd40a0969 100644 (file)
@@ -26,8 +26,7 @@
                 </div>
 
                 <div class="narrow">
-                    &iuml;&raquo;&iquest;#sidebar <a href="SortedSetCommandsSidebar.html">SortedSetCommandsSidebar</a><h1><a name="Redis Sorted Set Type">Redis Sorted Set Type</a></h1>Redis Sorted Sets are, similarly to <a href="Sets.html">Sets</a>, collections of <a href="Stings.html">Redis Strings</a>. The difference is that every member of a Sorted Set hash an <b>associated score</b> that is used in order to take this member in order.<br/><br/>The <a href="ZADD.html">ZaddCommand</a> command is used to add a new member to a Sorted Set, specifying the score of the element. Calling ZADD against a member already present in the sorted set but using a different score will update the score for the element, moving it to the right position in order to preserve ordering.<br/><br/>It's possible to get ranges of elements from Sorted Sets in a very similar way to what happens with <a href="Lists.html">Lists</a> and the <a href="LrangeCommnad.html">LRANGE</a> command  using the Sorted Sets <a href="ZrangeCommand.html">ZRANGE</a> command.<br/><br/>It's also possible to get or remove ranges of elements by score using the <a href="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a> and <a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a> commands.<br/><br/>The max number of members in a sorted set is 232-1 (4294967295, more than 4 billion of members per set).<br/><br/>Note that while Sorted Sets are already ordered, it is still possible to use the <a href="SortCommand.html">SORT</a> command against sorted sets to get the elements in a different order.<h1><a name="Implementation details">Implementation details</a></h1>Redis Sets are implemented using a dual-ported data structure containing a skip list and an hash table. When an element is added a map between the element and the score is added to the hash table (so that given the element we get the score in O(1)), and a map between the score and the element is added in the skip list so that elements are taken in order.<br/><br/>Redis uses a special skip list implementation that is doubly linked so that it's possible to traverse the sorted set from tail to head if needed (Check the <a href="ZRevrangeCommand.html">ZREVRANGE</a> command).<br/><br/>When <a href="ZaddCommand.html">ZADD</a> is used in order to update the score of an element, Redis retrieve the score of the element using the hash table, so that it's fast to access the element inside the skip list (that's indexed by score) in order to update the position.<br/><br/>Like it happens for Sets the hash table resizing is a blocking operation performed synchronously so working with huge sorted sets (consisting of many millions of elements) care should be taken when mass-inserting a very big amount of elements in a Set while other clients are querying Redis at high speed.<br/><br/>It is possible that in the near future Redis will switch to skip lists even for the element =&gt; score map, so every Sorted Set will have two skip lists, one indexed by element and one indexed by score.
-
+                    &iuml;&raquo;&iquest;#sidebar <a href="SortedSetCommandsSidebar.html">SortedSetCommandsSidebar</a><h1><a name="Redis Sorted Set Type">Redis Sorted Set Type</a></h1>Redis Sorted Sets are, similarly to <a href="Sets.html">Sets</a>, collections of <a href="Strings.html">Redis Strings</a>. The difference is that every member of a Sorted Set hash an <b>associated score</b> that is used in order to take this member in order.<br/><br/>The <a href="ZADD.html">ZaddCommand</a> command is used to add a new member to a Sorted Set, specifying the score of the element. Calling ZADD against a member already present in the sorted set but using a different score will update the score for the element, moving it to the right position in order to preserve ordering.<br/><br/>It's possible to get ranges of elements from Sorted Sets in a very similar way to what happens with <a href="Lists.html">Lists</a> and the <a href="LrangeCommnad.html">LRANGE</a> command  using the Sorted Sets <a href="ZrangeCommand.html">ZRANGE</a> command.<br/><br/>It's also possible to get or remove ranges of elements by score using the <a href="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a> and <a href="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a> commands.<br/><br/>The max number of members in a sorted set is 232-1 (4294967295, more than 4 billion of members per set).<br/><br/>Note that while Sorted Sets are already ordered, it is still possible to use the <a href="SortCommand.html">SORT</a> command against sorted sets to get the elements in a different order.<h1><a name="Implementation details">Implementation details</a></h1>Redis Sets are implemented using a dual-ported data structure containing a skip list and an hash table. When an element is added a map between the element and the score is added to the hash table (so that given the element we get the score in O(1)), and a map between the score and the element is added in the skip list so that elements are taken in order.<br/><br/>Redis uses a special skip list implementation that is doubly linked so that it's possible to traverse the sorted set from tail to head if needed (Check the <a href="ZRevrangeCommand.html">ZREVRANGE</a> command).<br/><br/>When <a href="ZaddCommand.html">ZADD</a> is used in order to update the score of an element, Redis retrieve the score of the element using the hash table, so that it's fast to access the element inside the skip list (that's indexed by score) in order to update the position.<br/><br/>Like it happens for Sets the hash table resizing is a blocking operation performed synchronously so working with huge sorted sets (consisting of many millions of elements) care should be taken when mass-inserting a very big amount of elements in a Set while other clients are querying Redis at high speed.<br/><br/>It is possible that in the near future Redis will switch to skip lists even for the element =&gt; score map, so every Sorted Set will have two skip lists, one indexed by element and one indexed by score.
                 </div>
         
             </div>
diff --git a/doc/SponsorshipHistory.html b/doc/SponsorshipHistory.html
new file mode 100644 (file)
index 0000000..ff81c87
--- /dev/null
@@ -0,0 +1,36 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+    <head>
+        <link type="text/css" rel="stylesheet" href="style.css" />
+    </head>
+    <body>
+        <div id="page">
+        
+            <div id='header'>
+            <a href="index.html">
+            <img style="border:none" alt="Redis Documentation" src="redis.png">
+            </a>
+            </div>
+        
+            <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>SponsorshipHistory: Contents</b><br>&nbsp;&nbsp;<a href="#Redis Sponsorship History">Redis Sponsorship History</a>
+                </div>
+                
+                <h1 class="wikiname">SponsorshipHistory</h1>
+
+                <div class="summary">
+                    
+                </div>
+
+                <div class="narrow">
+                    <h1><a name="Redis Sponsorship History">Redis Sponsorship History</a></h1>This is a list of companies that sponsorship Redis developments, with details about the sponsored features. <b>Thanks for helping the project!</b>.<br/><br/>If your company is considering a sponsorship please read the <a href="SponsorshipHowto.html">How to Sponsor</a> page.<br/><br/><ul><li> <a href="http://www.hitmeister.de/" target="_blank"><img src="http://redis.googlecode.com/files/logo_hitmeister_2.png" border="0"></img></a><br></br> 15 Dec 2009, part of Redis Cluster.</li><li> <a href="http://engineyard.com" target="_blank"><img src="http://redis.googlecode.com/files/engine_yard_logo.jpg" border="0"></img></a><br></br> 13 Dec 2009, for blocking POP (BLPOP) and part of the Virtual Memory implementation.</li></ul>
+                </div>
+        
+            </div>
+        </div>
+    </body>
+</html>
+
diff --git a/doc/SponsorshipHowto.html b/doc/SponsorshipHowto.html
new file mode 100644 (file)
index 0000000..2dc14fd
--- /dev/null
@@ -0,0 +1,37 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+    <head>
+        <link type="text/css" rel="stylesheet" href="style.css" />
+    </head>
+    <body>
+        <div id="page">
+        
+            <div id='header'>
+            <a href="index.html">
+            <img style="border:none" alt="Redis Documentation" src="redis.png">
+            </a>
+            </div>
+        
+            <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>SponsorshipHowto: Contents</b><br>&nbsp;&nbsp;<a href="#Other donations">Other donations</a>
+                </div>
+                
+                <h1 class="wikiname">SponsorshipHowto</h1>
+
+                <div class="summary">
+                    
+                </div>
+
+                <div class="narrow">
+                    &iuml;&raquo;&iquest;= How to sponsor my work on Redis =<br/><br/>I'm accepting sponsorships for Redis development, the idea is that a company using Redis and willing to donate some money can receive something back: visibility in the Redis site, and prioritization of features planned in the TODO list that are somewhat more important for this company compared to other features.<br/><br/>In the last year I spent 50% of my time working on Redis. At the same time Redis is released under the very liberal BSD license, this is very important for users as it prevents <a href="http://monty-says.blogspot.com/2009/10/importance-of-license-model-of-mysql-or.html" target="_blank">that in the future the project will be killed</a>, but at the same time it's not possible to build a business model selling licenses like it happens for MySQL. The alternative is to run a consultancy company, but this means to use more time to work with customers than working to the Redis code base itself, or sponsorship, that I think is the best option currently to ensure fast development of the project.<br/><br/>So, if you are considering a donation, thank you! This is a set of simple rules I developed in order to make sure I'm fair with everybody willing to help the project:<br/><br/><ul><li> 1. Every company can donate any amount of money, even 10$, in order to support Redis development.</li><li> 2. Every company donating an amount equal or greater than 1000$ will be featured in the home page for at least 6 months, and anyway for all the time the sponsored feature takes to reach a <b>stable release</b> of Redis.</li><li> 3. Every company donating at least 100$ will anyway be featured in the &quot;Sponsors&quot; page forever, this page is linked near to the logos of the current sponsors in the front page (the logos about point 2 of this list).</li><li> 4. A sponsoring company can donate for sponsorship of a feature already in the TODO list. If a feature not planned is needed we should first get in touch, discuss if this is a good idea, put it in the TODO list, and then the sponsorship can start, but I've to be genuinely convinced this feature will be good and of general interest ;)</li><li> 5. Not really a sponsorship/donation, but in rare case of a vertical, self-contained feature, I could develop it as a patch for the current stable Redis distribution for a &quot;donation&quot; proportional to the work needed to develop the feature, but in order to have the patch for the next release of Redis there will be to donate again for the porting work and so forth.</li><li> 6. Features for which I receive a good sponsorship (proportionally to the work required to implement the sponsored feature) are prioritized and will get developed faster than other features, possibly changing the development roadmap.</li><li> 7. To sponsor a specific feature is not a must, a company can just donate to the project as a whole.</li></ul>
+If you want to get in touch with me about this issues please drop me an email to my gmail account (username is antirez) or direct-message me @antirez on Twitter. Thanks in advance for the help!<h1><a name="Other donations">Other donations</a></h1>If you just feel like donating a small amount to Redis the simplest way is to use paypal, my paypal address is <b>antirez@invece.org</b>. Please specify in the donation if you don't like to have your name / company name published in the donations history (the amount will not be published anyway).
+                </div>
+        
+            </div>
+        </div>
+    </body>
+</html>
+
index ea1a59e2dbb3abd2954da66476f0a2cfdb9ae70a..e4f627e2e972d507f8cf03761d14f812890a66f0 100644 (file)
@@ -27,9 +27,8 @@
 
                 <div class="narrow">
                     &iuml;&raquo;&iquest;#sidebar <a href="SetCommandsSidebar.html">SetCommandsSidebar</a><h1><a name="SUNIONSTORE _dstkey_ _key1_ _key2_ ... _keyN_">SUNIONSTORE _dstkey_ _key1_ _key2_ ... _keyN_</a></h1>
-<i>Time complexity O(N) where N is the total number of elements in all the provided sets</i><blockquote>This commnad works exactly like SUNION but instead of being returned the resulting set is sotred as <i>dstkey</i>.</blockquote>
+<i>Time complexity O(N) where N is the total number of elements in all the provided sets</i><blockquote>This command works exactly like SUNION but instead of being returned the resulting set is stored as <i>dstkey</i>. Any existing value in <i>dstkey</i> will be over-written.</blockquote>
 <h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Status code reply</a>
-
                 </div>
         
             </div>
index 6daaa2b64cf090013526c27420715e303bb83ada..85e49d4b07e1559f1976b86c4c8e089b41fc3139 100644 (file)
@@ -26,7 +26,7 @@
                 </div>
 
                 <div class="narrow">
-                    <h1><a name="Redis Documentation">Redis Documentation</a></h1>Hello! The followings are pointers to different parts of the Redis Documentation.<br/><br/><ul><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.</li><li> <a href="TwitterAlikeExample.html">This is a tuturial 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="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></ul>
+                    <h1><a name="Redis Documentation">Redis Documentation</a></h1>Hello! The followings are pointers to different parts of the Redis Documentation.<br/><br/><ul><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.</li><li> <a href="TwitterAlikeExample.html">This is a tuturial 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="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> <b><a href="SponsorshipHowto.html">How to donate</a></b> to the project sponsoring features.</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></ul>
 <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>