summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2009-12-05 19:35:15 +0100
committerantirez <antirez@gmail.com>2009-12-05 19:35:15 +0100
commit76d31044d44c7adb4af71dd273b52ec9a4768e17 (patch)
treec3d852c2e2750219feaed1110cf642159863bd82 /doc
parent43f30ac0f9bcc4a7afb06136a8dfe5b703be7935 (diff)
downloadredis-76d31044d44c7adb4af71dd273b52ec9a4768e17.tar.gz
more HTML doc changes
Diffstat (limited to 'doc')
-rw-r--r--doc/SetnxCommand.html14
-rw-r--r--doc/SortCommand.html33
2 files changed, 30 insertions, 17 deletions
diff --git a/doc/SetnxCommand.html b/doc/SetnxCommand.html
index ed4ee167b..91f9206d8 100644
--- a/doc/SetnxCommand.html
+++ b/doc/SetnxCommand.html
@@ -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. -->
-<b>SetnxCommand: Contents</b><br>&nbsp;&nbsp;<a href="#SETNX _key_ _value_">SETNX _key_ _value_</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a>
+<b>SetnxCommand: Contents</b><br>&nbsp;&nbsp;<a href="#SETNX _key_ _value_">SETNX _key_ _value_</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Design pattern: Implementing locking with SETNX">Design pattern: Implementing locking with SETNX</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Handling deadlocks">Handling deadlocks</a>
</div>
<h1 class="wikiname">SetnxCommand</h1>
@@ -31,8 +31,16 @@
<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 key was set
0 if the key was not set
-</pre>
-
+</pre><h2><a name="Design pattern: Implementing locking with SETNX">Design pattern: Implementing locking with SETNX</a></h2><blockquote>SETNX can also be seen as a locking primitive. For instance to acquirethe lock of the key <b>foo</b>, the client could try the following:</blockquote>
+<pre class="codeblock python python" name="code">
+SETNX lock.foo &lt;current UNIX time + lock timeout + 1&gt;
+</pre><blockquote>If SETNX returns 1 the client acquired the lock, setting the <b>lock.foo</b>key to the UNIX time at witch the lock should no longer be considered valid.The client will later use <b>DEL lock.foo</b> in order to release the lock.</blockquote>
+<blockquote>If SETNX returns 0 the key is already locked by some other client. We caneither return to the caller if it's a non blocking lock, or enter aloop retrying to hold the lock until we succeed or some kind of timeoutexpires.</blockquote>
+<h3><a name="Handling deadlocks">Handling deadlocks</a></h3><blockquote>In the above locking algorithm there is a problem: what happens if a clientfails, crashes, or is otherwise not able to release the lock?It's possible to detect this condition because the lock key contains aUNIX timestamp. If such a timestamp is &lt;= the current Unix time the lockis no longer valid.</blockquote>
+<blockquote>When this happens we can't just call DEL against the key to remove the lockand then try to issue a SETNX, as there is a race condition here, whenmultiple clients detected an expired lock and are trying to release it.</blockquote>
+<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>
</div>
</div>
diff --git a/doc/SortCommand.html b/doc/SortCommand.html
index 8022d53cd..f89fd7c22 100644
--- a/doc/SortCommand.html
+++ b/doc/SortCommand.html
@@ -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. -->
-<b>SortCommand: Contents</b><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a>
+<b>SortCommand: Contents</b><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Sorting by external keys">Sorting by external keys</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Retrieving external keys">Retrieving external keys</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Storing the result of a SORT operation">Storing the result of a SORT operation</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Return value">Return value</a>
</div>
<h1 class="wikiname">SortCommand</h1>
@@ -26,33 +26,38 @@
</div>
<div class="narrow">
- &iuml;&raquo;&iquest;= SORT <i>key</i> <code name="code" class="python">[</code>BY <i>pattern</i><code name="code" class="python">]</code> <code name="code" class="python">[</code>LIMIT <i>start</i> <i>count</i><code name="code" class="python">]</code> <code name="code" class="python">[</code>GET <i>pattern</i><code name="code" class="python">]</code> <code name="code" class="python">[</code>ASC|DESC<code name="code" class="python">]</code> <code name="code" class="python">[</code>ALPHA<code name="code" class="python">]</code> =
-<blockquote>Sort the elements contained in the List or Set value at <i>key</i>. By defaultsorting is numeric with elements being compared as double precisionfloating point numbers. This is the simplest form of SORT.</blockquote>
+ &iuml;&raquo;&iquest;= SORT <i>key</i> <code name="code" class="python">[</code>BY <i>pattern</i><code name="code" class="python">]</code> <code name="code" class="python">[</code>LIMIT <i>start</i> <i>count</i><code name="code" class="python">]</code> <code name="code" class="python">[</code>GET <i>pattern</i><code name="code" class="python">]</code> <code name="code" class="python">[</code>ASC|DESC<code name="code" class="python">]</code> <code name="code" class="python">[</code>ALPHA<code name="code" class="python">]</code> <code name="code" class="python">[</code>STORE <i>dstkey</i><code name="code" class="python">]</code> =
+<blockquote>Sort the elements contained in the <a href="Lists.html">List</a>, <a href="Sets.html">Set</a>, or<a href="SortedSets.html">Sorted Set</a> value at <i>key</i>. By defaultsorting is numeric with elements being compared as double precisionfloating point numbers. This is the simplest form of SORT:</blockquote>
<pre class="codeblock python" name="code">
SORT mylist
-</pre><blockquote>Assuming mylist contains a list of numbers, the return value will bethe list of numbers ordered from the smallest to the bigger number.In order to get the sorting in reverse order use DESC:</blockquote>
+</pre><blockquote>Assuming mylist contains a list of numbers, the return value will bethe list of numbers ordered from the smallest to the biggest number.In order to get the sorting in reverse order use <b>DESC</b>:</blockquote>
<pre class="codeblock python python" name="code">
SORT mylist DESC
-</pre><blockquote>ASC is also supported but it's the default so you don't really need it.If you want to sort lexicographically use ALPHA. Note that Redis isutf-8 aware assuming you set the right value for the LC_COLLATEenvironment variable.</blockquote>
-<blockquote>Sort is able to limit the number of results using the LIMIT option:</blockquote>
+</pre><blockquote>The <b>ASC</b> option is also supported but it's the default so you don'treally need it.If you want to sort lexicographically use <b>ALPHA</b>. Note that Redis isutf-8 aware assuming you set the right value for the LC_COLLATEenvironment variable.</blockquote>
+<blockquote>Sort is able to limit the number of returned elements using the <b>LIMIT</b> option:</blockquote>
<pre class="codeblock python python python" name="code">
SORT mylist LIMIT 0 10
-</pre><blockquote>In the above example SORT will return only 10 elements, starting fromthe first one (star is zero-based). Almost all the sort options canbe mixed together. For example:</blockquote>
+</pre><blockquote>In the above example SORT will return only 10 elements, starting fromthe first one (start is zero-based). Almost all the sort options canbe mixed together. For example the command:</blockquote>
<pre class="codeblock python python python python" name="code">
SORT mylist LIMIT 0 10 ALPHA DESC
</pre><blockquote>Will sort <i>mylist</i> lexicographically, in descending order, returning onlythe first 10 elements.</blockquote>
-<blockquote>Sometimes you want to sort elements using external keys as weights tocompare instead to compare the actual List or Set elements. For examplethe list <i>mylist</i> may contain the elements 1, 2, 3, 4, that are justthe unique IDs of objects stored at object_1, object_2, object_3and object_4, while the keys weight_1, weight_2, weight_3 and weight_4can contain weights we want to use to sort the list of objectsidentifiers. We can use the following command:</blockquote>
-<pre class="codeblock python python python python python" name="code">
+<blockquote>Sometimes you want to sort elements using external keys as weights tocompare instead to compare the actual List Sets or Sorted Set elements.For example the list <i>mylist</i> may contain the elements 1, 2, 3, 4, thatare just unique IDs of objects stored at object_1, object_2, object_3and object_4, while the keys weight_1, weight_2, weight_3 and weight_4can contain weights we want to use to sort our list of objectsidentifiers. We can use the following command:</blockquote>
+<h2><a name="Sorting by external keys">Sorting by external keys</a></h2><pre class="codeblock python python python python python" name="code">
SORT mylist BY weight_*
-</pre><blockquote>the BY option takes a pattern (<code name="code" class="python">weight_*</code> in our example) that is usedin order to generate the key names of the weights used for sorting.Weight key names are obtained substituting the first occurrence of <code name="code" class="python">*</code>with the actual value of the elements on the list (1,2,3,4 in our example).</blockquote>
-<blockquote>Still our previous example will return just the sorted IDs. Often it isneeded to get the actual objects sorted (object_1, ..., object_4 in theexample). We can do it with the following command:</blockquote>
-<pre class="codeblock python python python python python python" name="code">
+</pre><blockquote>the <b>BY</b> option takes a pattern (<code name="code" class="python">weight_*</code> in our example) that is usedin order to generate the key names of the weights used for sorting.Weight key names are obtained substituting the first occurrence of <code name="code" class="python">*</code>with the actual value of the elements on the list (1,2,3,4 in our example).</blockquote>
+<blockquote>Our previous example will return just the sorted IDs. Often it isneeded to get the actual objects sorted (object_1, ..., object_4 in theexample). We can do it with the following command:</blockquote>
+<h2><a name="Retrieving external keys">Retrieving external keys</a></h2><pre class="codeblock python python python python python python" name="code">
SORT mylist BY weight_* GET object_*
-</pre><blockquote>Note that GET can be used multiple times in order to get more keys forevery element of the original List or Set sorted.</blockquote>
+</pre><blockquote>Note that <b>GET</b> can be used multiple times in order to get more keys forevery element of the original List, Set or Sorted Set sorted.</blockquote>
<blockquote>Since Redis &gt;= 1.1 it's possible to also GET the list elements itselfusing the special # pattern:</blockquote>
<pre class="codeblock python python python python python python python" name="code">
SORT mylist BY weight_* GET object_* GET #
-</pre><h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Multi bulk reply</a>, specifically a list of sorted elements.
+</pre><h2><a name="Storing the result of a SORT operation">Storing the result of a SORT operation</a></h2><blockquote>By default SORT returns the sorted elements as its return value.Using the <b>STORE</b> option instead to return the elements SORT willstore this elements as a <a href="Lists.html">Redis List</a> in the specified key.An example:</blockquote>
+<pre class="codeblock python python python python python python python python" name="code">
+SORT mylist BY weight_* STORE resultkey
+</pre><blockquote>An interesting pattern using SORT ... STORE consists in associatingan <a href="ExpireCommand.html">EXPIRE</a> timeout to the resulting key so that inapplications where the result of a sort operation can be cached forsome time other clients will use the cached list instead to call SORTfor every request. When the key will timeout an updated version ofthe cache can be created using SORT ... STORE again.</blockquote>
+<blockquote>Note that implementing this pattern it is important to avoid that multipleclients will try to rebuild the cached version of the cacheat the same time, so some form of locking should be implemented(for instance using <a href="SetnxCommand.html">SETNX</a>).</blockquote>
+<h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Multi bulk reply</a>, specifically a list of sorted elements.
</div>