<h2><aname="Commands operating on lists">Commands operating on lists</a></h2><ul><li><ahref="RpushCommand.html">RPUSH</a><i>key</i><i>value</i><codename="code"class="python">Append an element to the tail of the List value at key</code></li><li><ahref="RpushCommand.html">LPUSH</a><i>key</i><i>value</i><codename="code"class="python">Append an element to the head of the List value at key</code></li><li><ahref="LlenCommand.html">LLEN</a><i>key</i><codename="code"class="python">Return the length of the List value at key</code></li><li><ahref="LrangeCommand.html">LRANGE</a><i>key</i><i>start</i><i>end</i><codename="code"class="python">Return a range of elements from the List at key</code></li><li><ahref="LtrimCommand.html">LTRIM</a><i>key</i><i>start</i><i>end</i><codename="code"class="python">Trim the list at key to the specified range of elements</code></li><li><ahref="LindexCommand.html">LINDEX</a><i>key</i><i>index</i><codename="code"class="python">Return the element at index position from the List at key</code></li><li><ahref="LsetCommand.html">LSET</a><i>key</i><i>index</i><i>value</i><codename="code"class="python">Set a new value as the element at index position of the List at key</code></li><li><ahref="LremCommand.html">LREM</a><i>key</i><i>count</i><i>value</i><codename="code"class="python">Remove the first-N, last-N, or all the elements matching value from the List at key</code></li><li><ahref="LpopCommand.html">LPOP</a><i>key</i><codename="code"class="python">Return and remove (atomically) the first element of the List at key</code></li><li><ahref="LpopCommand.html">RPOP</a><i>key</i><codename="code"class="python">Return and remove (atomically) the last element of the List at key</code></li><li><ahref="BlpopCommand.html">BLPOP</a><i>key1</i><i>key2</i> ... <i>keyN</i><i>timeout</i><codename="code"class="python">Blocking LPOP</code></li><li><ahref="BlpopCommand.html">BRPOP</a><i>key1</i><i>key2</i> ... <i>keyN</i><i>timeout</i><codename="code"class="python">Blocking RPOP</code></li><li><ahref="RpoplpushCommand.html">RPOPLPUSH</a><i>srckey</i><i>dstkey</i><codename="code"class="python">Return and remove (atomically) the last element of the source List stored at _srckey_ and push the same element to the destination List stored at _dstkey_</code></li></ul>
<h2><aname="Commands operating on sets">Commands operating on sets</a></h2><ul><li><ahref="SaddCommand.html">SADD</a><i>key</i><i>member</i><codename="code"class="python">Add the specified member to the Set value at key</code></li><li><ahref="SremCommand.html">SREM</a><i>key</i><i>member</i><codename="code"class="python">Remove the specified member from the Set value at key</code></li><li><ahref="SpopCommand.html">SPOP</a><i>key</i><codename="code"class="python">Remove and return (pop) a random element from the Set value at key</code></li><li><ahref="SmoveCommand.html">SMOVE</a><i>srckey</i><i>dstkey</i><i>member</i><codename="code"class="python">Move the specified member from one Set to another atomically</code></li><li><ahref="ScardCommand.html">SCARD</a><i>key</i><codename="code"class="python">Return the number of elements (the cardinality) of the Set at key</code></li><li><ahref="SismemberCommand.html">SISMEMBER</a><i>key</i><i>member</i><codename="code"class="python">Test if the specified value is a member of the Set at key</code></li><li><ahref="SinterCommand.html">SINTER</a><i>key1</i><i>key2</i> ... <i>keyN</i><codename="code"class="python">Return the intersection between the Sets stored at key1, key2, ..., keyN</code></li><li><ahref="SinterstoreCommand.html">SINTERSTORE</a><i>dstkey</i><i>key1</i><i>key2</i> ... <i>keyN</i><codename="code"class="python">Compute the intersection between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey</code></li><li><ahref="SunionCommand.html">SUNION</a><i>key1</i><i>key2</i> ... <i>keyN</i><codename="code"class="python">Return the union between the Sets stored at key1, key2, ..., keyN</code></li><li><ahref="SunionstoreCommand.html">SUNIONSTORE</a><i>dstkey</i><i>key1</i><i>key2</i> ... <i>keyN</i><codename="code"class="python">Compute the union between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey</code></li><li><ahref="SdiffCommand.html">SDIFF</a><i>key1</i><i>key2</i> ... <i>keyN</i><codename="code"class="python">Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN</code></li><li><ahref="SdiffstoreCommand.html">SDIFFSTORE</a><i>dstkey</i><i>key1</i><i>key2</i> ... <i>keyN</i><codename="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><ahref="SmembersCommand.html">SMEMBERS</a><i>key</i><codename="code"class="python">Return all the members of the Set value at key</code></li><li><ahref="SrandmemberCommand.html">SRANDMEMBER</a><i>key</i><codename="code"class="python">Return a random member of the Set value at key</code></li></ul>
<h2><aname="Commands operating on sorted sets (zsets, Redis version >">Commands operating on sorted sets (zsets, Redis version ></a></h2> 1.1) ==<br/><br/><ul><li><ahref="ZaddCommand.html">ZADD</a><i>key</i><i>score</i><i>member</i><codename="code"class="python">Add the specified member to the Sorted Set value at key or update the score if it already exist</code></li><li><ahref="ZremCommand.html">ZREM</a><i>key</i><i>member</i><codename="code"class="python">Remove the specified member from the Sorted Set value at key</code></li><li><ahref="ZincrbyCommand.html">ZINCRBY</a><i>key</i><i>increment</i><i>member</i><codename="code"class="python">If the member already exists increment its score by _increment_, otherwise add the member setting _increment_ as score</code></li><li><ahref="ZrankCommand.html">ZRANK</a><i>key</i><i>member</i><codename="code"class="python">Return the rank (or index) or _member_ in the sorted set at _key_, with scores being ordered from low to high</code></li><li><ahref="ZrankCommand.html">ZREVRANK</a><i>key</i><i>member</i><codename="code"class="python">Return the rank (or index) or _member_ in the sorted set at _key_, with scores being ordered from high to low</code></li><li><ahref="ZrangeCommand.html">ZRANGE</a><i>key</i><i>start</i><i>end</i><codename="code"class="python">Return a range of elements from the sorted set at key</code></li><li><ahref="ZrangeCommand.html">ZREVRANGE</a><i>key</i><i>start</i><i>end</i><codename="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><ahref="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a><i>key</i><i>min</i><i>max</i><codename="code"class="python">Return all the elements with score >= min and score <= max (a range query) from the sorted set</code></li><li><ahref="ZcardCommand.html">ZCARD</a><i>key</i><codename="code"class="python">Return the cardinality (number of elements) of the sorted set at key</code></li><li><ahref="ZscoreCommand.html">ZSCORE</a><i>key</i><i>element</i><codename="code"class="python">Return the score associated with the specified element of the sorted set at key</code></li><li><ahref="ZremrangebyrankCommand.html">ZREMRANGEBYRANK</a><i>key</i><i>min</i><i>max</i><codename="code"class="python">Remove all the elements with rank >= min and rank <= max from the sorted set</code></li><li><ahref="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a><i>key</i><i>min</i><i>max</i><codename="code"class="python">Remove all the elements with score >= min and score <= max from the sorted set</code></li><li><ahref="ZunionstoreCommand.html">ZUNIONSTORE / ZINTERSTORE</a><i>dstkey</i><i>N</i><i>key1</i> ... <i>keyN</i> WEIGHTS <i>w1</i> ... <i>wN</i> AGGREGATE SUM|MIN|MAX <codename="code"class="python">Perform a union or intersection over a number of sorted sets with optional weight and aggregate</code></li></ul>
<h2><aname="Commands operating on hashes">Commands operating on hashes</a></h2><ul><li><ahref="HsetCommand.html">HSET</a><i>key</i><i>field</i><i>value</i><codename="code"class="python">Set the hash field to the specified value. Creates the hash if needed.</code></li><li><ahref="HgetCommand.html">HGET</a><i>key</i><i>field</i><codename="code"class="python">Retrieve the value of the specified hash field.</code></li><li><ahref="HmsetCommand.html">HMSET</a><i>key</i><i>field1</i><i>value1</i> ... <i>fieldN</i><i>valueN</i><codename="code"class="python">Set the hash fields to their respective values.</code></li><li><ahref="HincrbyCommand.html">HINCRBY</a><i>key</i><i>field</i><i>integer</i><codename="code"class="python">Increment the integer value of the hash at _key_ on _field_ with _integer_.</code></li><li><ahref="HexistsCommand.html">HEXISTS</a><i>key</i><i>field</i><codename="code"class="python">Test for existence of a specified field in a hash</code></li><li><ahref="HdelCommand.html">HDEL</a><i>key</i><i>field</i><codename="code"class="python">Remove the specified field from a hash</code></li><li><ahref="HlenCommand.html">HLEN</a><i>key</i><codename="code"class="python">Return the number of items in a hash.</code></li><li><ahref="HgetallCommand.html">HKEYS</a><i>key</i><codename="code"class="python">Return all the fields in a hash.</code></li><li><ahref="HgetallCommand.html">HVALS</a><i>key</i><codename="code"class="python">Return all the values in a hash.</code></li><li><ahref="HgetallCommand.html">HGETALL</a><i>key</i><codename="code"class="python">Return all the fields and associated values in a hash.</code></li></ul>
<h2><aname="Commands operating on hashes">Commands operating on hashes</a></h2><ul><li><ahref="HsetCommand.html">HSET</a><i>key</i><i>field</i><i>value</i><codename="code"class="python">Set the hash field to the specified value. Creates the hash if needed.</code></li><li><ahref="HgetCommand.html">HGET</a><i>key</i><i>field</i><codename="code"class="python">Retrieve the value of the specified hash field.</code></li><li><ahref="HmgetCommand.html">HMGET</a><i>key</i><i>field1</i> ... <i>fieldN</i><codename="code"class="python">Get the hash values assoicated to the specified fields.</code></li><li><ahref="HmsetCommand.html">HMSET</a><i>key</i><i>field1</i><i>value1</i> ... <i>fieldN</i><i>valueN</i><codename="code"class="python">Set the hash fields to their respective values.</code></li><li><ahref="HincrbyCommand.html">HINCRBY</a><i>key</i><i>field</i><i>integer</i><codename="code"class="python">Increment the integer value of the hash at _key_ on _field_ with _integer_.</code></li><li><ahref="HexistsCommand.html">HEXISTS</a><i>key</i><i>field</i><codename="code"class="python">Test for existence of a specified field in a hash</code></li><li><ahref="HdelCommand.html">HDEL</a><i>key</i><i>field</i><codename="code"class="python">Remove the specified field from a hash</code></li><li><ahref="HlenCommand.html">HLEN</a><i>key</i><codename="code"class="python">Return the number of items in a hash.</code></li><li><ahref="HgetallCommand.html">HKEYS</a><i>key</i><codename="code"class="python">Return all the fields in a hash.</code></li><li><ahref="HgetallCommand.html">HVALS</a><i>key</i><codename="code"class="python">Return all the values in a hash.</code></li><li><ahref="HgetallCommand.html">HGETALL</a><i>key</i><codename="code"class="python">Return all the fields and associated values in a hash.</code></li></ul>
<h2><aname="Sorting">Sorting</a></h2><ul><li><ahref="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 <codename="code"class="python">Sort a Set or a List accordingly to the specified parameters</code></li></ul>
<h2><aname="Persistence control commands">Persistence control commands</a></h2><ul><li><ahref="SaveCommand.html">SAVE</a><codename="code"class="python">Synchronously save the DB on disk</code></li><li><ahref="BgsaveCommand.html">BGSAVE</a><codename="code"class="python">Asynchronously save the DB on disk</code></li><li><ahref="LastsaveCommand.html">LASTSAVE</a><codename="code"class="python">Return the UNIX time stamp of the last successfully saving of the dataset on disk</code></li><li><ahref="ShutdownCommand.html">SHUTDOWN</a><codename="code"class="python">Synchronously save the DB on disk, then shutdown the server</code></li><li><ahref="BgrewriteaofCommand.html">BGREWRITEAOF</a><codename="code"class="python">Rewrite the append only file in background when it gets too big</code></li></ul>
<h2><aname="Remote server control commands">Remote server control commands</a></h2><ul><li><ahref="InfoCommand.html">INFO</a><codename="code"class="python">Provide information and statistics about the server</code></li><li><ahref="MonitorCommand.html">MONITOR</a><codename="code"class="python">Dump all the received requests in real time</code></li><li><ahref="SlaveofCommand.html">SLAVEOF</a><codename="code"class="python">Change the replication settings</code></li><li><ahref="ConfigCommand.html">CONFIG</a><codename="code"class="python">Configure a Redis server at runtime</code></li></ul>
<i>Time complexity: O(1)</i><blockquote>Remove the specified keys. If a given key does not existno operation is performed for this key. The commnad returns the number ofkeys removed.</blockquote>
<i>Time complexity: O(1)</i><blockquote>Remove the specified keys. If a given key does not existno operation is performed for this key. The command returns the number ofkeys removed.</blockquote>
<!-- This is a (PRE) block. Make sure it's left aligned or your toc title will be off. -->
<b>ExpireCommand: Contents</b><br> <ahref="#EXPIRE _key_ _seconds_">EXPIRE _key_ _seconds_</a><br> <ahref="#EXPIREAT _key_ _unixtime_ (Redis >">EXPIREAT _key_ _unixtime_ (Redis ></a><br> <ahref="#How the expire is removed from a key">How the expire is removed from a key</a><br> <ahref="#Restrictions with write operations against volatile keys">Restrictions with write operations against volatile keys</a><br> <ahref="#Setting the timeout again on already volatile keys">Setting the timeout again on already volatile keys</a><br> <ahref="#Enhanced Lazy Expiration algorithm">Enhanced Lazy Expiration algorithm</a><br> <ahref="#Version 1.0">Version 1.0</a><br> <ahref="#Version 1.1">Version 1.1</a><br> <ahref="#Return value">Return value</a><br> <ahref="#FAQ: Can you explain better why Redis deletes keys with an EXPIRE on write operations?">FAQ: Can you explain better why Redis deletes keys with an EXPIRE on write operations?</a>
<b>ExpireCommand: Contents</b><br> <ahref="#EXPIRE _key_ _seconds_">EXPIRE _key_ _seconds_</a><br> <ahref="#EXPIREAT _key_ _unixtime_ (Redis >">EXPIREAT _key_ _unixtime_ (Redis ></a><br> <ahref="#How the expire is removed from a key">How the expire is removed from a key</a><br> <ahref="#Restrictions with write operations against volatile keys">Restrictions with write operations against volatile keys</a><br> <ahref="#Restrictions for write operations with volatile keys as sources">Restrictions for write operations with volatile keys as sources</a><br> <ahref="#Setting the timeout again on already volatile keys">Setting the timeout again on already volatile keys</a><br> <ahref="#Enhanced Lazy Expiration algorithm">Enhanced Lazy Expiration algorithm</a><br> <ahref="#Version 1.0">Version 1.0</a><br> <ahref="#Version 1.1">Version 1.1</a><br> <ahref="#Return value">Return value</a><br> <ahref="#FAQ: Can you explain better why Redis deletes keys with an EXPIRE on write operations?">FAQ: Can you explain better why Redis deletes keys with an EXPIRE on write operations?</a>
</pre><blockquote>What happened here is that lpush against the key with a timeout set deletedthe key before to perform the operation. There is so a simple rule, writeoperations against volatile keys will destroy the key before to perform theoperation. Why Redis uses this behavior? In order to retain an importantproperty: a server that receives a given number of commands in the samesequence will end with the same dataset in memory. Without the delete-on-writesemantic what happens is that the state of the server depends on the timeof the commands to. This is not a desirable property in a distributed databasethat supports replication.</blockquote>
<h2><aname="Setting the timeout again on already volatile keys">Setting the timeout again on already volatile keys</a></h2><blockquote>Trying to call EXPIRE against a key that already has an associated timeoutwill not change the timeout of the key, but will just return 0. If insteadthe key does not have a timeout associated the timeout will be set and EXPIREwill return 1.</blockquote>
</pre><blockquote>What happened here is that LPUSH against the key with a timeout set deletedthe key before to perform the operation. There is so a simple rule, writeoperations against volatile keys will destroy the key before to perform theoperation. Why Redis uses this behavior? In order to retain an importantproperty: a server that receives a given number of commands in the samesequence will end with the same dataset in memory. Without the delete-on-writesemantic what happens is that the state of the server depends on the timethe commands were issued. This is not a desirable property in a distributed databasethat supports replication.</blockquote>
<h2><aname="Restrictions for write operations with volatile keys as sources">Restrictions for write operations with volatile keys as sources</a></h2>Even when the volatile key is not modified as part of a write operation, if it is
read in a composite write operation (such as SINTERSTORE) it will be cleared at the
start of the operation. This is done to avoid concurrency issues in replication.
Imagine a key that is about to expire and the composite operation is run against it.
On a slave node, this key might already be expired, which leaves you with a
desync in your dataset.<h2><aname="Setting the timeout again on already volatile keys">Setting the timeout again on already volatile keys</a></h2><blockquote>Trying to call EXPIRE against a key that already has an associated timeoutwill not change the timeout of the key, but will just return 0. If insteadthe key does not have a timeout associated the timeout will be set and EXPIREwill return 1.</blockquote>
<h2><aname="Enhanced Lazy Expiration algorithm">Enhanced Lazy Expiration algorithm</a></h2><blockquote>Redis does not constantly monitor keys that are going to be expired.Keys are expired simply when some client tries to access a key, andthe key is found to be timed out.</blockquote>
<blockquote>Of course this is not enough as there are expired keys that will neverbe accessed again. This keys should be expired anyway, so once everysecond Redis test a few keys at random among keys with an expire set.All the keys that are already expired are deleted from the keyspace. </blockquote>
<h3><aname="Version 1.0">Version 1.0</a></h3><blockquote>Each time a fixed number of keys where tested (100 by default). So ifyou had a client setting keys with a very short expire faster than 100for second the memory continued to grow. When you stopped to insertnew keys the memory started to be freed, 100 keys every second in thebest conditions. Under a peak Redis continues to use more and more RAMeven if most keys are expired in each sweep.</blockquote>
@@ -58,7 +58,7 @@ Redis for the same objects. This happens because when data is in
memory is full of pointers, reference counters and other metadata. Add
to this malloc fragmentation and need to return word-aligned chunks of
memory and you have a clear picture of what happens. So this means to
have 10 times the I/O between memory and disk than otherwise needed.<h1><aname="Is there something I can do to lower the Redis memory usage?">Is there something I can do to lower the Redis memory usage?</a></h1>Yes, try to compile it with 32 bit target if you are using a 64 bit box.<br/><br/>If you are using Redis >= 1.3, try using the Hash data type, it can save a lot of memory.<br/><br/>If you are using hashes or any other type with values bigger than 128 bytes try also this to lower the RSS usage (Resident Set Size): EXPORT MMAP_THRESHOLD=4096<h1><aname="I have an empty Redis server but INFO and logs are reporting megabytes of memory in use!">I have an empty Redis server but INFO and logs are reporting megabytes of memory in use!</a></h1>This may happen and it's prefectly ok. Redis objects are small C structures allocated and freed a lot of times. This costs a lot of CPU so instead of being freed, released objects are taken into a free list and reused when needed. This memory is taken exactly by this free objects ready to be reused.<h1><aname="What happens if Redis runs out of memory?">What happens if Redis runs out of memory?</a></h1>With modern operating systems malloc() returning NULL is not common, usually the server will start swapping and Redis performances will be disastrous so you'll know it's time to use more Redis servers or get more RAM.<br/><br/>The INFO command (work in progress in this days) will report the amount of memory Redis is using so you can write scripts that monitor your Redis servers checking for critical conditions.<br/><br/>You can also use the "maxmemory" option in the config file to put a limit to the memory Redis can use. If this limit is reached Redis will start to reply with an error to write commands (but will continue to accept read-only commands).<h1><aname="Does Redis use more memory running in 64 bit boxes? Can I use 32 bit Redis in 64 bit systems?">Does Redis use more memory running in 64 bit boxes? Can I use 32 bit Redis in 64 bit systems?</a></h1>Redis uses a lot more memory when compiled for 64 bit target, especially if the dataset is composed of many small keys and values. Such a database will, for instance, consume 50 MB of RAM when compiled for the 32 bit target, and 80 MB for 64 bit! That's a big difference.<br/><br/>You can run 32 bit Redis binaries in a 64 bit Linux and Mac OS X system without problems. For OS X just use <b>make 32bit</b>. For Linux instead, make sure you have <b>libc6-dev-i386</b> installed, then use <b>make 32bit</b> if you are using the latest Git version. Instead for Redis <= 1.2.2 you have to edit the Makefile and replace "-arch i386" with "-m32".<br/><br/>If your application is already able to perform application-level sharding, it is very advisable to run N instances of Redis 32bit against a big 64 bit Redis box (with more than 4GB of RAM) instead than a single 64 bit instance, as this is much more memory efficient. <h1><aname="How much time it takes to load a big database at server startup?">How much time it takes to load a big database at server startup?</a></h1>Just an example on normal hardware: It takes about 45 seconds to restore a 2 GB database on a fairly standard system, no RAID. This can give you some kind of feeling about the order of magnitude of the time needed to load data when you restart the server.<h1><aname="Background saving is failing with a fork() error under Linux even if I've a lot of free RAM!">Background saving is failing with a fork() error under Linux even if I've a lot of free RAM!</a></h1>Short answer: <codename="code"class="python">echo 1 > /proc/sys/vm/overcommit_memory</code> :)<br/><br/>And now the long one:<br/><br/>Redis background saving schema relies on the copy-on-write semantic of fork in modern operating systems: Redis forks (creates a child process) that is an exact copy of the parent. The child process dumps the DB on disk and finally exits. In theory the child should use as much memory as the parent being a copy, but actually thanks to the copy-on-write semantic implemented by most modern operating systems the parent and child process will <i>share</i> the common memory pages. A page will be duplicated only when it changes in the child or in the parent. Since in theory all the pages may change while the child process is saving, Linux can't tell in advance how much memory the child will take, so if the <codename="code"class="python">overcommit_memory</code> setting is set to zero fork will fail unless there is as much free RAM as required to really duplicate all the parent memory pages, with the result that if you have a Redis dataset of 3 GB and just 2 GB of free memory it will fail.<br/><br/>Setting <codename="code"class="python">overcommit_memory</code> to 1 says Linux to relax and perform the fork in a more optimistic allocation fashion, and this is indeed what you want for Redis.<h1><aname="Are Redis on disk snapshots atomic?">Are Redis on disk snapshots atomic?</a></h1>Yes, redis background saving process is always fork(2)ed when the server is outside of the execution of a command, so every command reported to be atomic in RAM is also atomic from the point of view of the disk snapshot.<h1><aname="Redis is single threaded, how can I exploit multiple CPU / cores?">Redis is single threaded, how can I exploit multiple CPU / cores?</a></h1>Simply start multiple instances of Redis in different ports in the same box and threat them as different servers! Given that Redis is a distributed database anyway in order to scale you need to think in terms of multiple computational units. At some point a single box may not be enough anyway.<br/><br/>In general key-value databases are very scalable because of the property that different keys can stay on different servers independently.<br/><br/>In Redis there are client libraries such Redis-rb (the Ruby client) that are able to handle multiple servers automatically using <i>consistent hashing</i>. We are going to implement consistent hashing in all the other major client libraries. If you use a different language you can implement it yourself otherwise just hash the key before to SET / GET it from a given server. For example imagine to have N Redis servers, server-0, server-1, ..., server-N. You want to store the key "foo", what's the right server where to put "foo" in order to distribute keys evenly among different servers? Just perform the <i>crc</i> = CRC32("foo"), then <i>servernum</i> = <i>crc</i> % N (the rest of the division for N). This will give a number between 0 and N-1 for every key. Connect to this server and store the key. The same for gets.<br/><br/>This is a basic way of performing key partitioning, consistent hashing is much better and this is why after Redis 1.0 will be released we'll try to implement this in every widely used client library starting from Python and PHP (Ruby already implements this support).<h1><aname="I'm using some form of key hashing for partitioning, but what about SORT BY?">I'm using some form of key hashing for partitioning, but what about SORT BY?</a></h1>With <ahref="SortCommand.html">SORT</a> BY you need that all the <i>weight keys</i> are in the same Redis instance of the list/set you are trying to sort. In order to make this possible we developed a concept called <i>key tags</i>. A key tag is a special pattern inside a key that, if preset, is the only part of the key hashed in order to select the server for this key. For example in order to hash the key "foo" I simply perform the CRC32 checksum of the whole string, but if this key has a pattern in the form of the characters {...} I only hash this substring. So for example for the key "foo{bared}" the key hashing code will simply perform the CRC32 of "bared". This way using key tags you can ensure that related keys will be stored on the same Redis instance just using the same key tag for all this keys. Redis-rb already implements key tags.<h1><aname="What is the maximum number of keys a single Redis instance can hold? and what the max number of elements in a List, Set, Ordered Set?">What is the maximum number of keys a single Redis instance can hold? and what the max number of elements in a List, Set, Ordered Set?</a></h1>In theory Redis can handle up to 2<sup>32 keys, and was tested in practice to handle at least 150 million of keys per instance. We are working in order to experiment with larger values.<br/><br/>Every list, set, and ordered set, can hold 2</sup>32 elements.<br/><br/>Actually Redis internals are ready to allow up to 2<sup>64 elements but the current disk dump format don't support this, and there is a lot time to fix this issues in the future as currently even with 128 GB of RAM it's impossible to reach 2</sup>32 elements.<h1><aname="What Redis means actually?">What Redis means actually?</a></h1>Redis means two things:
have 10 times the I/O between memory and disk than otherwise needed.<h1><aname="Is there something I can do to lower the Redis memory usage?">Is there something I can do to lower the Redis memory usage?</a></h1>Yes, try to compile it with 32 bit target if you are using a 64 bit box.<br/><br/>If you are using Redis >= 1.3, try using the Hash data type, it can save a lot of memory.<br/><br/>If you are using hashes or any other type with values bigger than 128 bytes try also this to lower the RSS usage (Resident Set Size): EXPORT MMAP_THRESHOLD=4096<h1><aname="I have an empty Redis server but INFO and logs are reporting megabytes of memory in use!">I have an empty Redis server but INFO and logs are reporting megabytes of memory in use!</a></h1>This may happen and it's prefectly ok. Redis objects are small C structures allocated and freed a lot of times. This costs a lot of CPU so instead of being freed, released objects are taken into a free list and reused when needed. This memory is taken exactly by this free objects ready to be reused.<h1><aname="What happens if Redis runs out of memory?">What happens if Redis runs out of memory?</a></h1>With modern operating systems malloc() returning NULL is not common, usually the server will start swapping and Redis performances will be disastrous so you'll know it's time to use more Redis servers or get more RAM.<br/><br/>The INFO command (work in progress in this days) will report the amount of memory Redis is using so you can write scripts that monitor your Redis servers checking for critical conditions.<br/><br/>You can also use the "maxmemory" option in the config file to put a limit to the memory Redis can use. If this limit is reached Redis will start to reply with an error to write commands (but will continue to accept read-only commands).<h1><aname="Does Redis use more memory running in 64 bit boxes? Can I use 32 bit Redis in 64 bit systems?">Does Redis use more memory running in 64 bit boxes? Can I use 32 bit Redis in 64 bit systems?</a></h1>Redis uses a lot more memory when compiled for 64 bit target, especially if the dataset is composed of many small keys and values. Such a database will, for instance, consume 50 MB of RAM when compiled for the 32 bit target, and 80 MB for 64 bit! That's a big difference.<br/><br/>You can run 32 bit Redis binaries in a 64 bit Linux and Mac OS X system without problems. For OS X just use <b>make 32bit</b>. For Linux instead, make sure you have <b>libc6-dev-i386</b> installed, then use <b>make 32bit</b> if you are using the latest Git version. Instead for Redis <= 1.2.2 you have to edit the Makefile and replace "-arch i386" with "-m32".<br/><br/>If your application is already able to perform application-level sharding, it is very advisable to run N instances of Redis 32bit against a big 64 bit Redis box (with more than 4GB of RAM) instead than a single 64 bit instance, as this is much more memory efficient. <h1><aname="How much time it takes to load a big database at server startup?">How much time it takes to load a big database at server startup?</a></h1>Just an example on normal hardware: It takes about 45 seconds to restore a 2 GB database on a fairly standard system, no RAID. This can give you some kind of feeling about the order of magnitude of the time needed to load data when you restart the server.<h1><aname="Background saving is failing with a fork() error under Linux even if I've a lot of free RAM!">Background saving is failing with a fork() error under Linux even if I've a lot of free RAM!</a></h1>Short answer: <codename="code"class="python">echo 1 > /proc/sys/vm/overcommit_memory</code> :)<br/><br/>And now the long one:<br/><br/>Redis background saving schema relies on the copy-on-write semantic of fork in modern operating systems: Redis forks (creates a child process) that is an exact copy of the parent. The child process dumps the DB on disk and finally exits. In theory the child should use as much memory as the parent being a copy, but actually thanks to the copy-on-write semantic implemented by most modern operating systems the parent and child process will <i>share</i> the common memory pages. A page will be duplicated only when it changes in the child or in the parent. Since in theory all the pages may change while the child process is saving, Linux can't tell in advance how much memory the child will take, so if the <codename="code"class="python">overcommit_memory</code> setting is set to zero fork will fail unless there is as much free RAM as required to really duplicate all the parent memory pages, with the result that if you have a Redis dataset of 3 GB and just 2 GB of free memory it will fail.<br/><br/>Setting <codename="code"class="python">overcommit_memory</code> to 1 says Linux to relax and perform the fork in a more optimistic allocation fashion, and this is indeed what you want for Redis.<br/><br/>A good source to understand how Linux Virtual Memory work and other alternatives for <codename="code"class="python">overcommit_memory</code> and <codename="code"class="python">overcommit_ratio</code> is this classic from Red Hat Magaize, "Understanding Virtual Memory": <ahref="http://www.redhat.com/magazine/001nov04/features/vm/"target="_blank">http://www.redhat.com/magazine/001nov04/features/vm/</a><h1><aname="Are Redis on disk snapshots atomic?">Are Redis on disk snapshots atomic?</a></h1>Yes, redis background saving process is always fork(2)ed when the server is outside of the execution of a command, so every command reported to be atomic in RAM is also atomic from the point of view of the disk snapshot.<h1><aname="Redis is single threaded, how can I exploit multiple CPU / cores?">Redis is single threaded, how can I exploit multiple CPU / cores?</a></h1>Simply start multiple instances of Redis in different ports in the same box and threat them as different servers! Given that Redis is a distributed database anyway in order to scale you need to think in terms of multiple computational units. At some point a single box may not be enough anyway.<br/><br/>In general key-value databases are very scalable because of the property that different keys can stay on different servers independently.<br/><br/>In Redis there are client libraries such Redis-rb (the Ruby client) that are able to handle multiple servers automatically using <i>consistent hashing</i>. We are going to implement consistent hashing in all the other major client libraries. If you use a different language you can implement it yourself otherwise just hash the key before to SET / GET it from a given server. For example imagine to have N Redis servers, server-0, server-1, ..., server-N. You want to store the key "foo", what's the right server where to put "foo" in order to distribute keys evenly among different servers? Just perform the <i>crc</i> = CRC32("foo"), then <i>servernum</i> = <i>crc</i> % N (the rest of the division for N). This will give a number between 0 and N-1 for every key. Connect to this server and store the key. The same for gets.<br/><br/>This is a basic way of performing key partitioning, consistent hashing is much better and this is why after Redis 1.0 will be released we'll try to implement this in every widely used client library starting from Python and PHP (Ruby already implements this support).<h1><aname="I'm using some form of key hashing for partitioning, but what about SORT BY?">I'm using some form of key hashing for partitioning, but what about SORT BY?</a></h1>With <ahref="SortCommand.html">SORT</a> BY you need that all the <i>weight keys</i> are in the same Redis instance of the list/set you are trying to sort. In order to make this possible we developed a concept called <i>key tags</i>. A key tag is a special pattern inside a key that, if preset, is the only part of the key hashed in order to select the server for this key. For example in order to hash the key "foo" I simply perform the CRC32 checksum of the whole string, but if this key has a pattern in the form of the characters {...} I only hash this substring. So for example for the key "foo{bared}" the key hashing code will simply perform the CRC32 of "bared". This way using key tags you can ensure that related keys will be stored on the same Redis instance just using the same key tag for all this keys. Redis-rb already implements key tags.<h1><aname="What is the maximum number of keys a single Redis instance can hold? and what the max number of elements in a List, Set, Ordered Set?">What is the maximum number of keys a single Redis instance can hold? and what the max number of elements in a List, Set, Ordered Set?</a></h1>In theory Redis can handle up to 2<sup>32 keys, and was tested in practice to handle at least 150 million of keys per instance. We are working in order to experiment with larger values.<br/><br/>Every list, set, and ordered set, can hold 2</sup>32 elements.<br/><br/>Actually Redis internals are ready to allow up to 2<sup>64 elements but the current disk dump format don't support this, and there is a lot time to fix this issues in the future as currently even with 128 GB of RAM it's impossible to reach 2</sup>32 elements.<h1><aname="What Redis means actually?">What Redis means actually?</a></h1>Redis means two things:
<ul><li> it's a joke on the word Redistribute (instead to use just a Relational DB redistribute your workload among Redis servers)</li><li> it means REmote DIctionary Server</li></ul>
<h1><aname="Why did you started the Redis project?">Why did you started the Redis project?</a></h1>In order to scale <ahref="http://lloogg.com"target="_blank">LLOOGG</a>. But after I got the basic server working I liked the idea to share the work with other guys, and Redis was turned into an open source project.
<blockquote>the slow commands that may ruin the DB performance if not usedwith care*.</blockquote>
<blockquote>In other words this command is intended only for debugging and *special* operations like creating a script to change the DB schema. Don't use it in your normal code. Use Redis <ahref="Sets.html">Sets</a> in order to group together a subset of objects.</blockquote>
Glob style patterns examples:
<blockquote>* h?llo will match hello hallo hhllo* h*llo will match hllo heeeello* h<codename="code"class="python">[</code>ae<codename="code"class="python">]</code>llo will match hello and hallo, but not hillo</blockquote>Use \ to escape special chars if you want to match them verbatim.<h2><aname="Return value">Return value</a></h2><ahref="ReplyTypes.html">Bulk reply</a>, specifically a string in the form of space separated list of keys. Note that most client libraries will return an Array of keys and not a single string with space separated keys (that is, split by "" is performed in the client library usually).</b></blockquote>
<blockquote>* h?llo will match hello hallo hhllo* h*llo will match hllo heeeello* h<codename="code"class="python">[</code>ae<codename="code"class="python">]</code>llo will match hello and hallo, but not hillo</blockquote>Use \ to escape special chars if you want to match them verbatim.<h2><aname="Return value">Return value</a></h2>
<i>Time complexity: O(n) (with n being the length of the list)</i><blockquote>Return the specified element of the list stored at the specifiedkey. 0 is the first element, 1 the second and so on. Negative indexesare supported, for example -1 is the last element, -2 the penultimateand so on.</blockquote>
<blockquote>If the value stored at key is not of list type an error is returned.If the index is out of range an empty string is returned.</blockquote>
<blockquote>If the value stored at key is not of list type an error is returned.If the index is out of range a 'nil' reply is returned.</blockquote>
<blockquote>Note that even if the average time complexity is O(n) asking forthe first or the last element of the list is O(1).</blockquote>
<h2><aname="Return value">Return value</a></h2><ahref="ReplyTypes.html">Bulk reply</a>, specifically the requested element.
<!-- This is a (PRE) block. Make sure it's left aligned or your toc title will be off. -->
<b>MultiExecCommand: Contents</b><br> <ahref="#MULTI">MULTI</a><br> <ahref="#COMMAND_1 ...">COMMAND_1 ...</a><br> <ahref="#COMMAND_2 ...">COMMAND_2 ...</a><br> <ahref="#COMMAND_N ...">COMMAND_N ...</a><br> <ahref="#EXEC or DISCARD">EXEC or DISCARD</a><br> <ahref="#Usage">Usage</a><br> <ahref="#The DISCARD command">The DISCARD command</a><br> <ahref="#Return value">Return value</a>
<b>MultiExecCommand: Contents</b><br> <ahref="#WATCH key1 key2 ... keyN (Redis >">WATCH key1 key2 ... keyN (Redis ></a><br> <ahref="#UNWATCH">UNWATCH</a><br> <ahref="#MULTI">MULTI</a><br> <ahref="#COMMAND_1 ...">COMMAND_1 ...</a><br> <ahref="#COMMAND_2 ...">COMMAND_2 ...</a><br> <ahref="#COMMAND_N ...">COMMAND_N ...</a><br> <ahref="#EXEC or DISCARD">EXEC or DISCARD</a><br> <ahref="#Usage">Usage</a><br> <ahref="#The DISCARD command">The DISCARD command</a><br> <ahref="#Check and Set (CAS) transactions using WATCH">Check and Set (CAS) transactions using WATCH</a><br> <ahref="#WATCH explained">WATCH explained</a><br> <ahref="#WATCH used to implement ZPOP">WATCH used to implement ZPOP</a><br> <ahref="#Return value">Return value</a>
<h1><aname="EXEC or DISCARD">EXEC or DISCARD</a></h1><blockquote>MULTI, EXEC and DISCARD commands are the fundation of Redis Transactions.A Redis Transaction allows to execute a group of Redis commands in a singlestep, with two important guarantees:</blockquote>
<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>
<h2><aname="Usage">Usage</a></h2><blockquote>A Redis transaction is entered using the MULTI command. The command alwaysreplies with OK. At this point the user can issue multiple commands. Insteadto execute this commands Redis will "queue" them. All the commands areexecuted once EXEC is called.</blockquote>
<blockquote>Calling DISCARD instead will flush the transaction queue and will exitthe transaction.</blockquote>
<blockquote>The following is an example using the Ruby client:</blockquote><preclass="codeblock python"name="code">
<h1><aname="EXEC or DISCARD">EXEC or DISCARD</a></h1>MULTI, EXEC, DISCARD and WATCH commands are the fundation of Redis Transactions.
A Redis Transaction allows the execution of a group of Redis commands in a single
step, with two important guarantees:<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><aname="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 "queue" 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:
<preclass="codeblock python"name="code">
?> r.multi
=>"OK"
>> r.incr "foo"
...
...
@@ -46,9 +52,14 @@
>> r.exec
=> [1, 1, 2]
</pre>
<blockquote>As it is possible to see from the session above, MULTI returns an "array" ofreplies, where every element is the reply of a single command in thetransaction, in the same order the commands were queued.</blockquote>
<blockquote>When a Redis connection is in the context of a MULTI request, all the commandswill reply with a simple string "QUEUED" if they are correct from thepoint of view of the syntax and arity (number of arguments) of the commaand.Some command is still allowed to fail during execution time.</blockquote>
<blockquote>This is more clear if at protocol level: in the following example one commandwill fail when executed even if the syntax is right:</blockquote><preclass="codeblock python python"name="code">
As it is possible to see from the session above, MULTI returns an "array" of
replies, where every element is the reply of a single command in the
transaction, in the same order the commands were queued.<br/><br/>When a Redis connection is in the context of a MULTI request, all the commands
will reply with a simple string "QUEUED" if they are correct from the
point of view of the syntax and arity (number of arguments) of the commaand.
Some command is still allowed to fail during execution time.<br/><br/>This is more clear if at protocol level: in the following example one command
will fail when executed even if the syntax is right:
<preclass="codeblock python python"name="code">
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
...
...
@@ -64,16 +75,21 @@ EXEC
+OK
-ERR Operation against a key holding the wrong kind of value
</pre>
<blockquote>MULTI returned a two elements bulk reply in witch one of this is a +OKcode and one is a -ERR reply. It's up to the client lib to find a sensibleway to provide the error to the user.</blockquote>
<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>
<blockquote>Another example, again using the write protocol with telnet, shows howsyntax errors are reported ASAP instead:</blockquote><preclass="codeblock python python python"name="code">
MULTI returned a two elements bulk reply in witch one of this is a +OK
code and one is a -ERR reply. It's up to the client lib to find a sensible
way to provide the error to the user.<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
<blockquote>This time due to the syntax error the "bad" INCR command is not queuedat all.</blockquote>
<h2><aname="The DISCARD command">The DISCARD command</a></h2><blockquote>DISCARD can be used in order to abort a transaction. No command will beexecuted, and the state of the client is again the normal one, outsideof a transaction. Example using the Ruby client:</blockquote><preclass="codeblock python python python python"name="code">
This time due to the syntax error the "bad" INCR command is not queued
at all.<h2><aname="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><preclass="codeblock python python python python"name="code">
The result of a MULTI/EXEC command is a multi bulk reply where every element is the return value of every command in the atomic transaction.
</pre><h2><aname="Check and Set (CAS) transactions using WATCH">Check and Set (CAS) transactions using WATCH</a></h2>WATCH is used in order to provide a CAS (Check and Set) behavior to
Redis Transactions.<br/><br/>WATCHed keys are monitored in order to detect changes against this keys.
If at least a watched key will be modified before the EXEC call, the
whole transaction will abort, and EXEC will return a nil object
(A Null Multi Bulk reply) to notify that the transaction failed.<br/><br/>For example imagine we have the need to atomically increment the value
of a key by 1 (I know we have INCR, let's suppose we don't have it).<br/><br/>The first try may be the following:
Using the above code, if there are race conditions and another client
modified the result of <i>val</i> in the time between our call to WATCH and
our call to EXEC, the transaction will fail.<br/><br/>We'll have just to re-iterate the operation hoping this time we'll not get
a new race. This form of locking is called <b>optimistic locking</b> and is
a very powerful form of locking as in many problems there are multiple
clients accessing a much bigger number of keys, so it's very unlikely that
there are collisions: usually operations don't need to be performed
multiple times.<h2><aname="WATCH explained">WATCH explained</a></h2>So what is WATCH really about? It is a command that will make the EXEC
conditional: we are asking Redis to perform the transaction only if all
the values WATCHed are still the same. Otherwise the transaction is not
entered at all.<br/><br/>WATCH can be called multiple times. Simply all the WATCH calls will
have the effects to watch for changes starting from the call, up to the
moment EXEC is called.<br/><br/>When EXEC is called, either if it will fail or succeed, all keys are
UNWATCHed. Also when a client connection is closed, everything gets
UNWATCHed.<br/><br/>It is also possible to use the UNWATCH command (without arguments) in order
to flush all the watched keys. Sometimes this is useful as we
optimistically lock a few keys, since possibly we need to perform a transaction
to alter those keys, but after reading the current content of the keys
we don't want to proceed. When this happens we just call UNWATCH so that
the connection can already be used freely for new transactions.<h2><aname="WATCH used to implement ZPOP">WATCH used to implement ZPOP</a></h2>A good example to illustrate how WATCH can be used to create new atomic
operations otherwise not supported by Redis is to implement ZPOP, that is
a command that pops the element with the lower score from a sorted set
in an atomic way. This is the simplest implementation:
If EXEC fails (returns a nil value) we just re-iterate the operation.<h2><aname="Return value">Return value</a></h2><ahref="ReplyTypes.html">Multi bulk reply</a>, specifically:<br/><br/><preclass="codeblock python python python python python python python python"name="code">
The result of a MULTI/EXEC command is a multi bulk reply where every element is the return value of every command in the atomic transaction.
</pre>If a MULTI/EXEC transaction is aborted because of WATCH detected modified keys, a <ahref="ReplyTypes.html">Null Multi Bulk reply</a> is returned.
== Sorted Set Commands ==<br/><br/><ul><li><ahref="ZaddCommand.html">ZADD</a></li><li><ahref="ZremCommand.html">ZREM</a></li><li><ahref="ZincrbyCommand.html">ZINCRBY</a></li><li><ahref="ZrankCommand.html">ZRANK</a></li><li><ahref="ZrankCommand.html">ZREVRANK</a></li><li><ahref="ZrangeCommand.html">ZRANGE</a></li><li><ahref="ZrangeCommand.html">ZREVRANGE</a></li><li><ahref="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a></li><li><ahref="ZremrangebyrankCommand.html">ZREMRANGEBYRANK</a></li><li><ahref="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a></li><li><ahref="ZcardCommand.html">ZCARD</a></li><li><ahref="ZscoreCommand.html">ZSCORE</a></li><li><ahref="ZunionstoreCommand.html">ZUNION / ZINTER</a></li><li><ahref="SortCommand.html">SORT</a></li></ul>
== Sorted Set Commands ==<br/><br/><ul><li><ahref="ZaddCommand.html">ZADD</a></li><li><ahref="ZremCommand.html">ZREM</a></li><li><ahref="ZincrbyCommand.html">ZINCRBY</a></li><li><ahref="ZrankCommand.html">ZRANK</a></li><li><ahref="ZrankCommand.html">ZREVRANK</a></li><li><ahref="ZrangeCommand.html">ZRANGE</a></li><li><ahref="ZrangeCommand.html">ZREVRANGE</a></li><li><ahref="ZrangebyscoreCommand.html">ZRANGEBYSCORE</a></li><li><ahref="ZremrangebyrankCommand.html">ZREMRANGEBYRANK</a></li><li><ahref="ZremrangebyscoreCommand.html">ZREMRANGEBYSCORE</a></li><li><ahref="ZcardCommand.html">ZCARD</a></li><li><ahref="ZscoreCommand.html">ZSCORE</a></li><li><ahref="ZunionstoreCommand.html">ZUNIONSTORE</a></li><li><ahref="ZunionstoreCommand.html">ZINTERSTORE</a></li><li><ahref="SortCommand.html">SORT</a></li></ul>
<i>Time complexity O(log(N)) with N being the number of elements in the sorted set</i><blockquote>If <i>member</i> already exists in the sorted set adds the <i>increment</i> to its scoreand updates the position of the element in the sorted set accordingly.If <i>member</i> does not already exist in the sorted set it is added with_increment_ as score (that is, like if the previous score was virtually zero).If <i>key</i> does not exist a new sorted set with the specified_member_ as sole member is crated. If the key exists but does not hold asorted set value an error is returned.</blockquote>
<blockquote>The score value can be the string representation of a double precision floatingpoint number. It's possible to provide a negative value to perform a decrement.</blockquote>
<blockquote>For an introduction to sorted sets check the <ahref="IntroductionToRedisDataTypes.html">Introduction to Redis data types</a> page.</blockquote>
<h1><aname="ZUNION / ZINTER _dstkey_ _N_ _k1_ ... _kN_ `[`WEIGHTS _w1_ ... _wN_`]` `[`AGGREGATE SUM|MIN|MAX`]` (Redis >">ZUNION / ZINTER _dstkey_ _N_ _k1_ ... _kN_ `[`WEIGHTS _w1_ ... _wN_`]` `[`AGGREGATE SUM|MIN|MAX`]` (Redis ></a></h1> 1.3.5) =<br/><br/><i>Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set</i><blockquote>Creates a union or intersection of <i>N</i> sorted sets given by keys <i>k1</i> through <i>kN</i>, and stores it at <i>dstkey</i>. It is mandatory to provide the number of input keys <i>N</i>, before passing the input keys and the other (optional) arguments.</blockquote>
<blockquote>As the terms imply, the ZINTER command requires an element to be present in each of the given inputs to be inserted in the result. The ZUNION command inserts all elements across all inputs.</blockquote>
<h1><aname="ZINTERSTORE _dstkey_ _N_ _k1_ ... _kN_ `[`WEIGHTS _w1_ ... _wN_`]` `[`AGGREGATE SUM|MIN|MAX`]` (Redis >">ZINTERSTORE _dstkey_ _N_ _k1_ ... _kN_ `[`WEIGHTS _w1_ ... _wN_`]` `[`AGGREGATE SUM|MIN|MAX`]` (Redis ></a></h1> 1.3.12) =<br/><br/><i>Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set</i><blockquote>Creates a union or intersection of <i>N</i> sorted sets given by keys <i>k1</i> through <i>kN</i>, and stores it at <i>dstkey</i>. It is mandatory to provide the number of input keys <i>N</i>, before passing the input keys and the other (optional) arguments.</blockquote>
<blockquote>As the terms imply, the ZINTERSTORE command requires an element to be present in each of the given inputs to be inserted in the result. The ZUNIONSTORE command inserts all elements across all inputs.</blockquote>
<blockquote>Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means that the score of each element in the sorted set is first multiplied by this weight before being passed to the aggregation. When this option is not given, all weights default to 1.</blockquote>
<blockquote>With the AGGREGATE option, it's possible to specify how the results of the union or intersection are aggregated. This option defaults to SUM, where the score of an element is summed across the inputs where it exists. When this option is set to be either MIN or MAX, the resulting set will contain the minimum or maximum score of an element across the inputs where it exists.</blockquote>
<h2><aname="Return value">Return value</a></h2><ahref="ReplyTypes.html">Integer reply</a>, specifically the number of elements in the sorted set at <i>dstkey</i>.
<h1><aname="ZUNION / ZINTER _dstkey_ _N_ _k1_ ... _kN_ `[`WEIGHTS _w1_ ... _wN_`]` `[`AGGREGATE SUM|MIN|MAX`]` (Redis >">ZUNION / ZINTER _dstkey_ _N_ _k1_ ... _kN_ `[`WEIGHTS _w1_ ... _wN_`]` `[`AGGREGATE SUM|MIN|MAX`]` (Redis ></a></h1> 1.3.5) =<br/><br/><i>Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set</i><blockquote>Creates a union or intersection of <i>N</i> sorted sets given by keys <i>k1</i> through <i>kN</i>, and stores it at <i>dstkey</i>. It is mandatory to provide the number of input keys <i>N</i>, before passing the input keys and the other (optional) arguments.</blockquote>
<blockquote>As the terms imply, the ZINTER command requires an element to be present in each of the given inputs to be inserted in the result. The ZUNION command inserts all elements across all inputs.</blockquote>
<i>Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set</i><blockquote>Creates a union or intersection of <i>N</i> sorted sets given by keys <i>k1</i> through <i>kN</i>, and stores it at <i>dstkey</i>. It is mandatory to provide the number of input keys <i>N</i>, before passing the input keys and the other (optional) arguments.</blockquote>
<blockquote>As the terms imply, the ZINTERSTORE command requires an element to be present in each of the given inputs to be inserted in the result. The ZUNIONSTORE command inserts all elements across all inputs.</blockquote>
<blockquote>Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means that the score of each element in the sorted set is first multiplied by this weight before being passed to the aggregation. When this option is not given, all weights default to 1.</blockquote>
<blockquote>With the AGGREGATE option, it's possible to specify how the results of the union or intersection are aggregated. This option defaults to SUM, where the score of an element is summed across the inputs where it exists. When this option is set to be either MIN or MAX, the resulting set will contain the minimum or maximum score of an element across the inputs where it exists.</blockquote>
<h2><aname="Return value">Return value</a></h2><ahref="ReplyTypes.html">Integer reply</a>, specifically the number of elements in the sorted set at <i>dstkey</i>.