From b9f7e9e63c053f3d23464171d65fb8995676ee76 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 15 Dec 2010 15:49:29 +0100 Subject: [PATCH] HTML doc updated --- doc/AppendOnlyFileHowto.html | 5 +- doc/CommandReference.html | 4 +- doc/ExpireCommand.html | 9 +- doc/HdelCommand.html | 2 +- doc/HgetallCommand.html | 2 +- doc/IntroductionToRedisDataTypes.html | 3 +- doc/ListCommandsSidebar.html | 2 +- doc/MultiExecCommand.html | 13 ++- doc/ProtocolSpecification.html | 143 +++++++++++++------------- doc/PublishSubscribe.html | 3 +- doc/StringCommandsSidebar.html | 2 +- doc/Strings.html | 2 +- doc/SubstrCommand.html | 5 +- doc/VirtualMemoryUserGuide.html | 3 +- doc/ZrankCommand.html | 5 +- doc/index.html | 14 +-- doc/redis.png | Bin 4852 -> 2801 bytes 17 files changed, 105 insertions(+), 112 deletions(-) diff --git a/doc/AppendOnlyFileHowto.html b/doc/AppendOnlyFileHowto.html index 1a0e468a..295e7548 100644 --- a/doc/AppendOnlyFileHowto.html +++ b/doc/AppendOnlyFileHowto.html @@ -16,7 +16,7 @@

AppendOnlyFileHowto

@@ -31,8 +31,7 @@ What is the solution? To use append only file as alternative to snapshotting. How it works?

Log rewriting

As you can guess... the append log file gets bigger and bigger, every time there is a new operation changing the dataset. Even if you set always the same key "mykey" to the values of "1", "2", "3", ... up to 10000000000 in the end you'll have just a single key in the dataset, just a few bytes! but how big will be the append log file? Very very big.

So Redis supports an interesting feature: it is able to rebuild the append log file, in background, without to stop processing client commands. The key is the command BGREWRITEAOF. This command basically is able to use the dataset in memory in order to rewrite the shortest sequence of commands able to rebuild the exact dataset that is currently in memory.

So from time to time when the log gets too big, try this command. It's safe as if it fails you will not lost your old log (but you can make a backup copy given that currently 1.1 is still in beta!).

Wait... but how does this work?

Basically it uses the same fork() copy-on-write trick that snapshotting already uses. This is how the algorithm works:

How durable is the append only file?

Check redis.conf, you can configure how many times Redis will fsync() data on disk. There are three options:

-Warning: by default Redis will fsync() after every command! This is because the Redis authors want to ship a default configuration that is the safest pick. But the best compromise for most datasets is to fsync() one time every second. - +The suggested (and default) policy is "everysec". It is both very fast and pretty safe. The "always" policy is very slow in practice, even if it was improved in Redis 2.0.0 there is no way to make fsync() faster than it is.

What should I do if my Append Only File gets corrupted?

It is possible that the server crashes while writing the AOF file (this still should never lead to inconsistencies) corrupting the file in a way that is no longer loadable by Redis. When this happens you can fix this problem using the following procedure:

diff --git a/doc/CommandReference.html b/doc/CommandReference.html index 7021bd7e..143b23b5 100644 --- a/doc/CommandReference.html +++ b/doc/CommandReference.html @@ -28,8 +28,8 @@
= Redis Command Reference =

Every command name links to a specific wiki page describing the behavior of the command.

Categorized Command List

Connection handling

Command Parameters Description
QUIT - close the connection
AUTH password simple password authentication if enabled

Commands operating on all value types

Command Parameters Description
EXISTS key test if a key exists
DEL key delete a key
TYPE key return the type of the value stored at key
KEYS pattern return all the keys matching a given pattern
RANDOMKEY - return a random key from the key space
RENAME oldname newname rename the old key in the new one, destroying the newname key if it already exists
RENAMENX oldname newname rename the oldname key to newname, if the newname key does not already exist
DBSIZE - return the number of keys in the current db
EXPIRE - set a time to live in seconds on a key
PERSIST - remove the expire from a key
TTL - get the time to live in seconds of a key
SELECT index Select the DB with the specified index
MOVE key dbindex Move the key from the currently selected DB to the dbindex DB
FLUSHDB - Remove all the keys from the currently selected DB
FLUSHALL - Remove all the keys from all the databases
-

Commands operating on string values

Command Parameters Description
SET key value Set a key to a string value
GET key Return the string value of the key
GETSET key value Set a key to a string returning the old value of the key
MGET key1 key2 ... keyN Multi-get, return the strings values of the keys
SETNX key value Set a key to a string value if the key does not exist
SETEX key time value Set+Expire combo command
MSET key1 value1 key2 value2 ... keyN valueN Set multiple keys to multiple values in a single atomic operation
MSETNX key1 value1 key2 value2 ... keyN valueN Set multiple keys to multiple values in a single atomic operation if none of the keys already exist
INCR key Increment the integer value of key
INCRBY key integer Increment the integer value of key by integer
DECR key Decrement the integer value of key
DECRBY key integer Decrement the integer value of key by integer
APPEND key value Append the specified string to the string stored at key
SUBSTR key start end Return a substring of a larger string
-

Commands operating on lists

Command Parameters Description
RPUSH key value Append an element to the tail of the List value at key
LPUSH key value Append an element to the head of the List value at key
LLEN key Return the length of the List value at key
LRANGE key start end Return a range of elements from the List at key
LTRIM key start end Trim the list at key to the specified range of elements
LINDEX key index Return the element at index position from the List at key
LSET key index value Set a new value as the element at index position of the List at key
LREM key count value Remove the first-N, last-N, or all the elements matching value from the List at key
LPOP key Return and remove (atomically) the first element of the List at key
RPOP key Return and remove (atomically) the last element of the List at key
BLPOP key1 key2 ... keyN timeout Blocking LPOP
BRPOP key1 key2 ... keyN timeout Blocking RPOP
RPOPLPUSH srckey dstkey 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
+

Commands operating on string values

Command Parameters Description
SET key value Set a key to a string value
GET key Return the string value of the key
GETSET key value Set a key to a string returning the old value of the key
SETNX key value Set a key to a string value if the key does not exist
SETEX key time value Set+Expire combo command
SETBIT key offset value Set bit at offset to value
GETBIT key offset Return bit value at offset
MSET key1 value1 key2 value2 ... keyN valueN Set multiple keys to multiple values in a single atomic operation
MSETNX key1 value1 key2 value2 ... keyN valueN Set multiple keys to multiple values in a single atomic operation if none of the keys already exist
MGET key1 key2 ... keyN Multi-get, return the strings values of the keys
INCR key Increment the integer value of key
INCRBY key integer Increment the integer value of key by integer
DECR key Decrement the integer value of key
DECRBY key integer Decrement the integer value of key by integer
APPEND key value Append the specified string to the string stored at key
SUBSTR key start end Return a substring of a larger string
+

Commands operating on lists

Command Parameters Description
RPUSH key value Append an element to the tail of the List value at key
LPUSH key value Append an element to the head of the List value at key
LLEN key Return the length of the List value at key
LRANGE key start end Return a range of elements from the List at key
LTRIM key start end Trim the list at key to the specified range of elements
LINDEX key index Return the element at index position from the List at key
LSET key index value Set a new value as the element at index position of the List at key
LREM key count value Remove the first-N, last-N, or all the elements matching value from the List at key
LPOP key Return and remove (atomically) the first element of the List at key
RPOP key Return and remove (atomically) the last element of the List at key
BLPOP key1 key2 ... keyN timeout Blocking LPOP
BRPOP key1 key2 ... keyN timeout Blocking RPOP
RPOPLPUSH srckey dstkey 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
BRPOPLPUSH srckey dstkey Like RPOPLPUSH but blocking of source key is empty

Commands operating on sets

Command Parameters Description
SADD key member Add the specified member to the Set value at key
SREM key member Remove the specified member from the Set value at key
SPOP key Remove and return (pop) a random element from the Set value at key
SMOVE srckey dstkey member Move the specified member from one Set to another atomically
SCARD key Return the number of elements (the cardinality) of the Set at key
SISMEMBER key member Test if the specified value is a member of the Set at key
SINTER key1 key2 ... keyN Return the intersection between the Sets stored at key1, key2, ..., keyN
SINTERSTORE dstkey key1 key2 ... keyN Compute the intersection between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey
SUNION key1 key2 ... keyN Return the union between the Sets stored at key1, key2, ..., keyN
SUNIONSTORE dstkey key1 key2 ... keyN Compute the union between the Sets stored at key1, key2, ..., keyN, and store the resulting Set at dstkey
SDIFF key1 key2 ... keyN Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN
SDIFFSTORE dstkey key1 key2 ... keyN Compute the difference between the Set key1 and all the Sets key2, ..., keyN, and store the resulting Set at dstkey
SMEMBERS key Return all the members of the Set value at key
SRANDMEMBER key Return a random member of the Set value at key

Commands operating on sorted zsets (sorted sets)

Command Parameters Description
ZADD key score member Add the specified member to the Sorted Set value at key or update the score if it already exist
ZREM key member Remove the specified member from the Sorted Set value at key
ZINCRBY key increment member If the member already exists increment its score by increment, otherwise add the member setting increment as score
ZRANK key member Return the rank (or index) or member in the sorted set at key, with scores being ordered from low to high
ZREVRANK key member Return the rank (or index) or member in the sorted set at key, with scores being ordered from high to low
ZRANGE key start end Return a range of elements from the sorted set at key
ZREVRANGE key start end 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
ZRANGEBYSCORE key min max Return all the elements with score >= min and score <= max (a range query) from the sorted set
ZCOUNT key min max Return the number of elements with score >= min and score <= max in the sorted set
ZCARD key Return the cardinality (number of elements) of the sorted set at key
ZSCORE key element Return the score associated with the specified element of the sorted set at key
ZREMRANGEBYRANK key min max Remove all the elements with rank >= min and rank <= max from the sorted set
ZREMRANGEBYSCORE key min max Remove all the elements with score >= min and score <= max from the sorted set
ZUNIONSTORE / ZINTERSTORE dstkey N key1 ... keyN WEIGHTS w1 ... wN AGGREGATE SUM|MIN|MAX Perform a union or intersection over a number of sorted sets with optional weight and aggregate

Commands operating on hashes

Command Parameters Description
HSET key field value Set the hash field to the specified value. Creates the hash if needed.
HGET key field Retrieve the value of the specified hash field.
HMGET key field1 ... fieldN Get the hash values associated to the specified fields.
HMSET key field1 value1 ... fieldN valueN Set the hash fields to their respective values.
HINCRBY key field integer Increment the integer value of the hash at key on field with integer.
HEXISTS key field Test for existence of a specified field in a hash
HDEL key field Remove the specified field from a hash
HLEN key Return the number of items in a hash.
HKEYS key Return all the fields in a hash.
HVALS key Return all the values in a hash.
HGETALL key Return all the fields and associated values in a hash.
diff --git a/doc/ExpireCommand.html b/doc/ExpireCommand.html index cebac8b8..736d951a 100644 --- a/doc/ExpireCommand.html +++ b/doc/ExpireCommand.html @@ -16,7 +16,7 @@

ExpireCommand

@@ -28,8 +28,8 @@
#sidebar GenericCommandsSidebar

EXPIRE _key_ _seconds_

EXPIREAT _key_ _unixtime_ (Redis >

1.1)= -

PERSIST _key_

-Time complexity: O(1)
Set a timeout on the specified key. After the timeout the key will beautomatically delete by the server. A key with an associated timeout issaid to be volatile in Redis terminology.
+

PERSIST _key_ (Redis >

2.1.3) = +Time complexity: O(1)
Set a timeout on the specified key. After the timeout the key will beautomatically deleted by the server. A key with an associated timeout issaid to be volatile in Redis terminology.
Voltile keys are stored on disk like the other keys, the timeout is persistenttoo like all the other aspects of the dataset. Saving a dataset containingexpires and stopping the server does not stop the flow of time as Redisstores on disk the time when the key will no longer be available as Unixtime, and not the remaining seconds.
EXPIREAT works exctly like EXPIRE but instead to get the number of secondsrepresenting the Time To Live of the key as a second argument (that is arelative way of specifing the TTL), it takes an absolute one in the form ofa UNIX timestamp (Number of seconds elapsed since 1 Gen 1970).
EXPIREAT was introduced in order to implement the Append Only File persistence modeso that EXPIRE commands are automatically translated into EXPIREAT commands for the append only file. Of course EXPIREAT can alsoused by programmers that need a way to simply specify that a given key should expire at a given time in the future.
@@ -78,7 +78,7 @@ redis> incr a (integer) 1 I set a key to the value of 100, then set an expire of 360 seconds, and then incremented the key (before the 360 timeout expired of course). The obvious result would be: 101, instead the key is set to the value of 1. Why? -There is a very important reason involving the Append Only File and Replication. Let's rework a bit hour example adding the notion of time to the mix: +There is a very important reason involving the Append Only File and Replication. Let's rework a bit our example adding the notion of time to the mix:
 SET a 100
 EXPIRE a 5
@@ -87,7 +87,6 @@ INCR a
 
Imagine a Redis version that does not implement the "Delete keys with an expire set on write operation" semantic. Running the above example with the 10 seconds pause will lead to 'a' being set to the value of 1, as it no longer exists when INCR is called 10 seconds later.

Instead if we drop the 10 seconds pause, the result is that 'a' is set to 101.

And in the practice timing changes! For instance the client may wait 10 seconds before INCR, but the sequence written in the Append Only File (and later replayed-back as fast as possible when Redis is restarted) will not have the pause. Even if we add a timestamp in the AOF, when the time difference is smaller than our timer resolution, we have a race condition.

The same happens with master-slave replication. Again, consider the example above: the client will use the same sequence of commands without the 10 seconds pause, but the replication link will slow down for a few seconds due to a network problem. Result? The master will contain 'a' set to 101, the slave 'a' set to 1.

The only way to avoid this but at the same time have reliable non time dependent timeouts on keys is to destroy volatile keys when a write operation is attempted against it.

After all Redis is one of the rare fully persistent databases that will give you EXPIRE. This comes to a cost :)

FAQ: How this limitations were solved in Redis versions > 2.1.3?

Since Redis 2.1.3 there are no longer restrictions in the use you can do of write commands against volatile keys, still the replication and AOF file are guaranteed to be fully consistent.

In order to obtain a correct behavior without sacrificing consistency now when a key expires, a DEL operation is synthesized in both the AOF file and against all the attached slaves. This way the expiration process is centralized in the master instance, and there is no longer a chance of consistency errors.

However while the slaves while connected to a master will not expire keys independently, they'll still take the full state of the expires existing in the dataset, so when a slave is elected to a master it will be able to expire the keys independently, fully acting as a master. -
diff --git a/doc/HdelCommand.html b/doc/HdelCommand.html index 7afdb935..2ecb2098 100644 --- a/doc/HdelCommand.html +++ b/doc/HdelCommand.html @@ -28,7 +28,7 @@
#sidebar HashCommandsSidebar

HDEL _key_ _field_ (Redis >

1.3.10)= Time complexity: O(1)
Remove the specified field from an hash stored at key.
-
If the field was present in the hash it is returned and 1 is returned, otherwise 0 is returned and no operation is performed.
+
If the field was present in the hash it is deleted and 1 is returned, otherwise 0 is returned and no operation is performed.

Return value

Integer reply
diff --git a/doc/HgetallCommand.html b/doc/HgetallCommand.html index 7d85c415..bfc6c4f8 100644 --- a/doc/HgetallCommand.html +++ b/doc/HgetallCommand.html @@ -29,7 +29,7 @@ #sidebar HashCommandsSidebar

HKEYS _key_ (Redis >

1.3.10)=

HVALS _key_ (Redis >

1.3.10)=

HGETALL _key_ (Redis >

1.3.10)= -Time complexity: O(N), where N is the total number of entries
HKEYS returns all the fields names contained into a hash, HVALS all the associated values, while HGETALL returns both the fields and values in the form of field1, value1, field2, value2, ..., fieldN, valueN.
+Time complexity: O(N), where N is the total number of fields in the hash
HKEYS returns all the fields names contained into a hash, HVALS all the associated values, while HGETALL returns both the fields and values in the form of field1, value1, field2, value2, ..., fieldN, valueN.

Return value

Multi Bulk Reply
diff --git a/doc/IntroductionToRedisDataTypes.html b/doc/IntroductionToRedisDataTypes.html index 26b2ba19..82078aeb 100644 --- a/doc/IntroductionToRedisDataTypes.html +++ b/doc/IntroductionToRedisDataTypes.html @@ -79,7 +79,7 @@ $ ./redis-cli sismember myset 3 (integer) 1 $ ./redis-cli sismember myset 30 (integer) 0 -"3" is a member of the set, while "30" is not. Sets are very good in order to express relations between objects. For instance we can easily Redis Sets in order to implement tags.

A simple way to model this is to have, for every object you want to tag, a Set with all the IDs of the tags associated with the object, and for every tag that exists, a Set of of all the objects tagged with this tag.

For instance if our news ID 1000 is tagged with tag 1,2,5 and 77, we can specify the following two Sets:

+
"3" is a member of the set, while "30" is not. Sets are very good in order to express relations between objects. For instance we can easily use Redis Sets in order to implement tags.

A simple way to model this is to have, for every object you want to tag, a Set with all the IDs of the tags associated with the object, and for every tag that exists, a Set of of all the objects tagged with this tag.

For instance if our news ID 1000 is tagged with tag 1,2,5 and 77, we can specify the following two Sets:

 $ ./redis-cli sadd news:1000:tags 1
 (integer) 1
 $ ./redis-cli sadd news:1000:tags 2
@@ -143,7 +143,6 @@ $ ./redis-cli zrangebyscore hackers -inf 1950
 $ ./redis-cli zremrangebyscore hackers 1940 1960
 (integer) 2
 
ZREMRANGEBYSCORE is not the best command name, but it can be very useful, and returns the number of removed elements.

Back to the reddit example

For the last time, back to the Reddit example. Now we have a decent plan to populate a sorted set in order to generate the home page. A sorted set can contain all the news that are not older than a few days (we remove old entries from time to time using ZREMRANGEBYSCORE). A background job gets all the elements from this sorted set, get the user votes and the time of the news, and compute the score to populate the reddit.home.page sorted set with the news IDs and associated scores. To show the home page we have just to perform a blazingly fast call to ZRANGE.

From time to time we'll remove too old news from the reddit.home.page sorted set as well in order for our system to work always against a limited set of news.

Updating the scores of a sorted set

Just a final note before to finish this tutorial. Sorted sets scores can be updated at any time. Just calling again ZADD against an element already included in the sorted set will update its score (and position) in O(log(N)), so sorted sets are suitable even when there are tons of updates.

This tutorial is in no way complete, this is just the basics to get started with Redis, read the Command Reference to discover a lot more.

Thanks for reading. Salvatore. - diff --git a/doc/ListCommandsSidebar.html b/doc/ListCommandsSidebar.html index ae827923..6a49d73d 100644 --- a/doc/ListCommandsSidebar.html +++ b/doc/ListCommandsSidebar.html @@ -26,7 +26,7 @@
- == List Commands ==

+ == List Commands ==

diff --git a/doc/MultiExecCommand.html b/doc/MultiExecCommand.html index 65ec67a0..97f21482 100644 --- a/doc/MultiExecCommand.html +++ b/doc/MultiExecCommand.html @@ -32,12 +32,12 @@

COMMAND_1 ...

COMMAND_2 ...

COMMAND_N ...

-

EXEC or DISCARD

MULTI, EXEC, DISCARD and WATCH commands are the fundation of Redis Transactions. +

EXEC or DISCARD

MULTI, EXEC, DISCARD and WATCH commands are the foundation of Redis Transactions. A Redis Transaction allows the execution of a group of Redis commands in a single step, with two important guarantees:

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.

Usage

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 +of executing these commands, Redis will "queue" them. All the commands are executed once EXEC is called.

Calling DISCARD instead will flush the transaction queue and will exit the transaction.

The following is an example using the Ruby client:
@@ -57,7 +57,7 @@ replies, where every element is the reply of a single command in the
 transaction, in the same order the commands were queued.

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.

This is more clear if at protocol level: in the following example one command +Some commands are still allowed to fail during execution time.

This is more clear on the protocol level; In the following example one command will fail when executed even if the syntax is right:
 Trying 127.0.0.1...
@@ -75,7 +75,7 @@ EXEC
 +OK
 -ERR Operation against a key holding the wrong kind of value
 
-MULTI returned a two elements bulk reply in witch one of this is a +OK +MULTI returned a two elements bulk reply where one is an +OK code and one is a -ERR reply. It's up to the client lib to find a sensible way to provide the error to the user.

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.
Another example, again using the write protocol with telnet, shows how @@ -87,9 +87,8 @@ INCR a b c -ERR wrong number of arguments for 'incr' command
This time due to the syntax error the "bad" INCR command is not queued -at all.

The DISCARD command

DISCARD can be used in order to abort a transaction. No command will be -executed, and the state of the client is again the normal one, outside -
of a transaction. Example using the Ruby client:
+at all.

The DISCARD command

DISCARD can be used in order to abort a transaction. No command will be executed, and the state of the client is again the normal one, outside of a transaction. Example using the Ruby client: +
 ?> r.set("foo",1)
 => true
 >> r.multi
diff --git a/doc/ProtocolSpecification.html b/doc/ProtocolSpecification.html
index 686c574e..c69115ef 100644
--- a/doc/ProtocolSpecification.html
+++ b/doc/ProtocolSpecification.html
@@ -16,7 +16,7 @@
             
 
                 
- = Protocol Specification =

The Redis protocol is a compromise between being easy to parse by a computer -and being easy to parse by an human. Before reading this section you are -strongly encouraged to read the "REDIS TUTORIAL" section of this README in order -to get a first feeling of the protocol playing with it by TELNET.

Networking layer

A client connects to a Redis server creating a TCP connection to the port 6379. -Every redis command or data transmitted by the client and the server is -terminated by "\r\n" (CRLF).

Simple INLINE commands

The simplest commands are the inline commands. This is an example of a -server/client chat (the server chat starts with S:, the client chat with C:)

-C: PING
-S: +PONG
-
An inline command is a CRLF-terminated string sent to the client. The server can reply to commands in different ways: -
  • With an error message (the first byte of the reply will be "-")
  • With a single line reply (the first byte of the reply will be "+)
  • With bulk data (the first byte of the reply will be "$")
  • With multi-bulk data, a list of values (the first byte of the reply will be "*")
  • With an integer number (the first byte of the reply will be ":")
-The following is another example of an INLINE command returning an integer:

-C: EXISTS somekey
-S: :0
-
Since 'somekey' does not exist the server returned ':0'.

Note that the EXISTS command takes one argument. Arguments are separated -simply by spaces.

Bulk commands

A bulk command is exactly like an inline command, but the last argument -of the command must be a stream of bytes in order to send data to the server. -the "SET" command is a bulk command, see the following example:

-C: SET mykey 6
-C: foobar
-S: +OK
-
The last argument of the commnad is '6'. This specify the number of DATA -bytes that will follow (note that even this bytes are terminated by two -additional bytes of CRLF).

All the bulk commands are in this exact form: instead of the last argument -the number of bytes that will follow is specified, followed by the bytes, -and CRLF. In order to be more clear for the programmer this is the string -sent by the client in the above sample:

"SET mykey 6\r\nfoobar\r\n"
-

Bulk replies

The server may reply to an inline or bulk command with a bulk reply. See -the following example:

+                    = Protocol Specification =

The Redis protocol is a compromise between the following things:

  • Simple to implement.
  • Fast to parse by a computer.
  • Easy enough to parse by a human.
+

Networking layer

A client connects to a Redis server creating a TCP connection to the port 6379. +Every Redis command or data transmitted by the client and the server is +terminated by "\r\n" (CRLF).

Requests

Redis accepts commands composed of different arguments. +Once a command is received, it is processed and a reply is sent back to the client.

The new unified request protocol

The new unified protocol was introduced in Redis 1.2, but it became the standard way for talking with the Redis server in Redis 2.0.

In the unified protocol all the arguments sent to the Redis server are binary safe. This is the general form:

+*<number of arguments> CR LF
+$<number of bytes of argument 1> CR LF
+<argument data> CR LF
+...
+$<number of bytes of argument N> CR LF
+<argument data> CR LF
+
See the following example:

+*3
+$3
+SET
+$5
+mykey
+$7
+myvalue
+
This is how the above command looks as a quoted string, so that it is possible to see the exact value of every byte in the query:

+"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$8\r\nmyvalue\r\n"
+
As you will see in a moment this format is also used in Redis replies. +The format used for every argument "$6\r\nmydata\r\n" is called a Bulk Reply. +While the actual unified request protocol is what Redis uses to return list of items, and is called a Multi Bulk Reply. It is just the sum of N different +Bulk Replies prefixed by a *<argc>\r\n string where <argc> is the number of arguments (Bulk Replies) that will follow.

Replies

Redis will reply to commands with different kinds of replies. It is possible to check the kind of reply from the first byte sent by the server:

  • With a single line reply the first byte of the reply will be "+"
  • With an error message the first byte of the reply will be "-"
  • With an integer number the first byte of the reply will be ":"
  • With bulk reply the first byte of the reply will be "$"
  • With multi-bulk reply the first byte of the reply will be "*"
+

Single line reply

A single line reply is in the form of a single line string +starting with "+" terminated by "\r\n". For example:

++OK
+
The client library should return everything after the "+", that is, the string "OK" in the example.

The following commands reply with a single line reply: +PING, SET, SELECT, SAVE, BGSAVE, SHUTDOWN, RENAME, LPUSH, RPUSH, LSET, LTRIM

Error reply

Errors are sent exactly like Single Line Replies. The only difference is that the first byte is "-" instead of "+".

Error replies are only sent when something strange happened, for instance if you try to perform an operation against the wrong data type, or if the command does not exist and so forth. So an exception should be raised by the library client when an Error Reply is received.

Integer reply

This type of reply is just a CRLF terminated string representing an integer, prefixed by a ":" byte. For example ":0\r\n", or ":1000\r\n" are integer replies.

With commands like INCR or LASTSAVE using the integer reply to actually return a value there is no special meaning for the returned integer. It is just an incremental number for INCR, a UNIX time for LASTSAVE and so on.

Some commands like EXISTS will return 1 for true and 0 for false.

Other commands like SADD, SREM and SETNX will return 1 if the operation was actually done, 0 otherwise.

The following commands will reply with an integer reply: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD

Bulk replies

Bulk replies are used by the server in order to return a single binary safe string.

 C: GET mykey
 S: $6
 S: foobar
-
A bulk reply is very similar to the last argument of a bulk command. The -server sends as the first line a "$" byte followed by the number of bytes -of the actual reply followed by CRLF, then the bytes are sent followed by -additional two bytes for the final CRLF. The exact sequence sent by the -server is:

"$6\r\nfoobar\r\n"
-If the requested value does not exist the bulk reply will use the special -value -1 as data length, example:

+
The server sends as the first line a "$" byte followed by the number of bytes +of the actual reply, followed by CRLF, then the actual data bytes are sent, +followed by additional two bytes for the final CRLF. +The exact sequence sent by the server is:

+"$6\r\nfoobar\r\n"
+
If the requested value does not exist the bulk reply will use the special +value -1 as data length, example:

 C: GET nonexistingkey
 S: $-1
 
The client library API should not return an empty string, but a nil object, when the requested object does not exist. For example a Ruby library should return 'nil' while a C library should return -NULL, and so forth.

Multi-Bulk replies

Commands similar to LRANGE needs to return multiple values (every element +NULL (or set a special flag in the reply object), and so forth.

Multi-Bulk replies

Commands like LRANGE need to return multiple values (every element of the list is a value, and LRANGE needs to return more than a single element). This is accomplished using multiple bulk writes, prefixed by an initial line indicating how many bulk writes will follow. -The first byte of a multi bulk reply is always *. Example:

+The first byte of a multi bulk reply is always *. Example:

 C: LRANGE mylist 0 3
 S: *4
 S: $3
@@ -83,56 +84,50 @@ S: $5
 S: Hello
 S: $5
 S: World
-
The first line the server sent is "4\r\n" in order to specify that four bulk -write will follow. Then every bulk write is transmitted.

If the specified key does not exist instead of the number of elements in the -list, the special value -1 is sent as count. Example:

+
As you can see the multi bulk reply is exactly the same format used in order +to send commands to the Redis server unsing the unified protocol.

The first line the server sent is "4\r\n" in order to specify that four bulk +replies will follow. Then every bulk write is transmitted.

If the specified key does not exist, instead of the number of elements in the +list the special value -1 is sent as count. Example:

 C: LRANGE nokey 0 1
 S: *-1
 
A client library API SHOULD return a nil object and not an empty list when this -happens. This makes possible to distinguish between empty list and non existing ones.

Nil elements in Multi-Bulk replies

Single elements of a multi bulk reply may have -1 length, in order to signal that this elements are missing and not empty strings. This can happen with the SORT command when used with the GET pattern option when the specified key is missing. Example of a multi bulk reply containing an empty element:

+happens. This makes possible to distinguish between empty list and other error conditions (for instance a timeout condition in the BLPOP command).

Nil elements in Multi-Bulk replies

Single elements of a multi bulk reply may have -1 length, in order to signal that this elements are missing and not empty strings. This can happen with the SORT command when used with the GET pattern option when the specified key is missing. Example of a multi bulk reply containing an empty element:

 S: *3
 S: $3
 S: foo
 S: $-1
 S: $3
 S: bar
-
The second element is nul. The client library should return something like this:

+
The second element is nul. The client library should return something like this:

 ["foo",nil,"bar"]
-

Single line reply

As already seen a single line reply is in the form of a single line string -starting with "+" terminated by "\r\n". For example:

-+OK
-
The client library should return everything after the "+", that is, the string "OK" in the example.

The following commands reply with a status code reply: -PING, SET, SELECT, SAVE, BGSAVE, SHUTDOWN, RENAME, LPUSH, RPUSH, LSET, LTRIM

Integer reply

This type of reply is just a CRLF terminated string representing an integer, prefixed by a ":" byte. For example ":0\r\n", or ":1000\r\n" are integer replies.

With commands like INCR or LASTSAVE using the integer reply to actually return a value there is no special meaning for the returned integer. It is just an incremental number for INCR, a UNIX time for LASTSAVE and so on.

Some commands like EXISTS will return 1 for true and 0 for false.

Other commands like SADD, SREM and SETNX will return 1 if the operation was actually done, 0 otherwise.

The following commands will reply with an integer reply: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD

Multi bulk commands

As you can see with the protocol described so far there is no way to -send multiple binary-safe arguments to a command. With bulk commands the -last argument is binary safe, but there are commands where multiple binary-safe -commands are needed, like the MSET command that is able to SET multiple keys -in a single operation.

In order to address this problem Redis 1.1 introduced a new way of seding -commands to a Redis server, that uses exactly the same protocol of the -multi bulk replies. For instance the following is a SET command using the -normal bulk protocol:

-SET mykey 8
-myvalue
-
While the following uses the multi bulk command protocol:

-*3
-$3
-SET
-$5
-mykey
-$8
-myvalue
-
Commands sent in this format are longer, so currently they are used only in -order to transmit commands containing multiple binary-safe arguments, but -actually this protocol can be used to send every kind of command, without to -know if it's an inline, bulk or multi-bulk command.

It is possible that in the future Redis will support only this format.

A good client library may implement unknown commands using this -command format in order to support new commands out of the box without -modifications.

Multiple commands and pipelining

A client can use the same connection in order to issue multiple commands. +

Multiple commands and pipelining

A client can use the same connection in order to issue multiple commands. Pipelining is supported so multiple commands can be sent with a single write operation by the client, it is not needed to read the server reply in order to issue the next command. All the replies can be read at the end.

Usually Redis server and client will have a very fast link so this is not very important to support this feature in a client implementation, still if an application needs to issue a very large number of commands in short -time to use pipelining can be much faster. -
+time to use pipelining can be much faster.

The old protocol for sending commands

Before of the Unified Request Protocol Redis used a different protocol to send +commands, that is still supported since it is simpler to type by hand via telnet. In this protocol there are two kind of commands:

* Inline commands: simple commands where argumnets are just space separated strings. No binary safeness is possible.* Bulk commands: bulk commands are exactly like inline commands, but the last argument is handled in a special way in order to allow for a binary-safe last argument.
+

Inline Commands

The simplest way to send Redis a command is via
Inline Commands. +The following is an example of a server/client chat using an inline command (the server chat starts with S:, the client chat with C:)

+C: PING
+S: +PONG
+
The following is another example of an INLINE command returning an integer:

+C: EXISTS somekey
+S: :0
+
Since 'somekey' does not exist the server returned ':0'.

Note that the EXISTS command takes one argument. Arguments are separated +by spaces.

Bulk commands

Some commands when sent as inline commands require a special form in order +to support a binary safe last argument. This commands will use the last argument +for a "byte count", then the bulk data is sent (that can be binary safe since +the server knows how many bytes to read).

See for instance the following example:

+C: SET mykey 6
+C: foobar
+S: +OK
+
The last argument of the commnad is '6'. This specify the number of DATA +bytes that will follow, that is, the string "foobar". Note that even this bytes are terminated by two additional bytes of CRLF.

All the bulk commands are in this exact form: instead of the last argument +the number of bytes that will follow is specified, followed by the bytes +composing the argument itself, and CRLF. In order to be more clear for the programmer this is the string sent by the client in the above sample:

"SET mykey 6\r\nfoobar\r\n"
+Redis has an internal list of what command is inline and what command is bulk, so you have to send this commands accordingly. It is strongly suggested to use the new Unified Request Protocol instead.
diff --git a/doc/PublishSubscribe.html b/doc/PublishSubscribe.html index c3d5d060..0fefe33b 100644 --- a/doc/PublishSubscribe.html +++ b/doc/PublishSubscribe.html @@ -32,7 +32,7 @@

PSUBSCRIBE pattern_1 pattern_2 ... pattern_N

PUNSUBSCRIBE pattern_1 pattern_2 ... pattern_N

PUNSUBSCRIBE (unsubscribe from all patterns)

-

PUBLISH channel message

Time complexity: subscribe is O(1), unsubscribe is O(N) where N is the number of clients already subscribed to a channel, publish is O(N+M) where N is the number of clients subscribed to the receiving channel, and M is the total number of subscribed patterns (by any client). Psubscribe is O(N) where N is the number of patterns the Psubscribing client is already subscribed to. Punsubscribe is O(N+M) where N is the number of patterns the Punsubscribing client is already subscribed and M is the number of total patterns subscribed in the system (by any client).

SUBSCRIBE, UNSUBSCRIBE and PUBLISH commands implement thePublish/Subscribe messaging paradigm where (citing Wikipedia) senders (publishers) are not programmed to send their messages to specific receivers (subscribers). Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be. Subscribers express interest in one or more channels, and only receive messages that are of interest, without knowledge of what (if any) publishers there are. This decoupling of publishers and subscribers can allow for greater scalability and a more dynamic network topology.
+

PUBLISH channel message

Time complexity: subscribe is O(1), unsubscribe is O(N) where N is the number of clients already subscribed to a channel, publish is O(N+M) where N is the number of clients subscribed to the receiving channel, and M is the total number of subscribed patterns (by any client). Psubscribe is O(N) where N is the number of patterns the Psubscribing client is already subscribed to. Punsubscribe is O(N+M) where N is the number of patterns the Punsubscribing client is already subscribed and M is the number of total patterns subscribed in the system (by any client).

Note: this commands are available starting form Redis 2.0.0

SUBSCRIBE, UNSUBSCRIBE and PUBLISH commands implement thePublish/Subscribe messaging paradigm where (citing Wikipedia) senders (publishers) are not programmed to send their messages to specific receivers (subscribers). Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be. Subscribers express interest in one or more channels, and only receive messages that are of interest, without knowledge of what (if any) publishers there are. This decoupling of publishers and subscribers can allow for greater scalability and a more dynamic network topology.
For instance in order to subscribe to the channels foo and bar the clientwill issue the SUBSCRIBE command followed by the names of the channels.
 SUBSCRIBE foo bar
 
@@ -106,7 +106,6 @@ The Publish command is a bulk command where the first argument is the target cla Pieter Noordhuis provided a great example using Event-machine and Redis to create a multi user high performance web chat, with source code included of course!

Client library implementations hints

Because all the messages received contain the original subscription causing the message delivery (the channel in the case of "message" type, and the original pattern in the case of "pmessage" type) clinet libraries may bind the original subscription to callbacks (that can be anonymous functions, blocks, function pointers, and so forth), using an hash table.

When a message is received an O(1) lookup can be done in order to deliver the message to the registered callback. - diff --git a/doc/StringCommandsSidebar.html b/doc/StringCommandsSidebar.html index 369b0cfb..78bc40e1 100644 --- a/doc/StringCommandsSidebar.html +++ b/doc/StringCommandsSidebar.html @@ -26,7 +26,7 @@ diff --git a/doc/Strings.html b/doc/Strings.html index d05bf928..010fbed7 100644 --- a/doc/Strings.html +++ b/doc/Strings.html @@ -26,7 +26,7 @@
- #sidebar StringCommandsSidebar

Redis String Type

Strings are the most basic Redis kind of values. Redis Strings are binary safe, this means a Redis string can contain any kind of data, for instance a JPEG image or a serialized Ruby object, and so forth.

A String value can be at max 1 Gigabyte in length.

Strings are treated as integer values by the INCR commands family, in this respect the value of an intger is limited to a singed 64 bit value.

Note that the single elements contained in Redis Lists, Sets and Sorted Sets, are Redis Strings.

Implementation details

Strings are implemented using a dynamic strings library called sds.c (simple dynamic strings). This library caches the current length of the string, so to obtain the length of a Redis string is an O(1) operation (but currently there is no such STRLEN command. It will likely be added later).

Redis strings are incapsualted into Redis Objects. Redis Objects use a reference counting memory management system, so a single Redis String can be shared in different places of the dataset. This means that if you happen to use the same strings many times (especially if you have object sharing turned on in the configuration file) Redis will try to use the same string object instead to allocate one new every time.

Starting from version 1.1 Redis is also able to encode in a special way strings that are actually just numbers. Instead to save the string as an array of characters Redis will save the integer value in order to use less memory. With many datasets this can reduce the memory usage of about 30% compared to Redis 1.0. + #sidebar StringCommandsSidebar

Redis String Type

Strings are the most basic Redis kind of values. Redis Strings are binary safe, this means a Redis string can contain any kind of data, for instance a JPEG image or a serialized Ruby object, and so forth.

A String value can be at max 512 Megabytes in length.

Strings are treated as integer values by the INCR commands family, in this respect the value of an intger is limited to a singed 64 bit value.

Note that the single elements contained in Redis Lists, Sets and Sorted Sets, are Redis Strings.

Implementation details

Strings are implemented using a dynamic strings library called sds.c (simple dynamic strings). This library caches the current length of the string, so to obtain the length of a Redis string is an O(1) operation (but currently there is no such STRLEN command. It will likely be added later).

Redis strings are incapsualted into Redis Objects. Redis Objects use a reference counting memory management system, so a single Redis String can be shared in different places of the dataset. This means that if you happen to use the same strings many times (especially if you have object sharing turned on in the configuration file) Redis will try to use the same string object instead to allocate one new every time.

Starting from version 1.1 Redis is also able to encode in a special way strings that are actually just numbers. Instead to save the string as an array of characters Redis will save the integer value in order to use less memory. With many datasets this can reduce the memory usage of about 30% compared to Redis 1.0.
diff --git a/doc/SubstrCommand.html b/doc/SubstrCommand.html index 3b6bdef0..b5f4f792 100644 --- a/doc/SubstrCommand.html +++ b/doc/SubstrCommand.html @@ -16,7 +16,7 @@
-SubstrCommand: Contents
  SUBSTR _key_ _start_ _end_
    Return value
    Examples +SubstrCommand: Contents
  SUBSTR _key_ _start_ _end_
  GETRANGE _key_ _start_ _end_
    Return value
    Examples

SubstrCommand

@@ -27,7 +27,8 @@
#sidebar StringCommandsSidebar

SUBSTR _key_ _start_ _end_

-Time complexity: O(start+n) (with start being the start index and n the total length of the requested range). Note that the lookup part of this command is O(1) so for small strings this is actually an O(1) command.
Return a subset of the string from offset start to offset end(both offsets are inclusive).Negative offsets can be used in order to provide an offset starting fromthe end of the string. So -1 means the last char, -2 the penultimate andso forth.
+

GETRANGE _key_ _start_ _end_

+Time complexity: O(start+n) (with start being the start index and n the total length of the requested range). Note that the lookup part of this command is O(1) so for small strings this is actually an O(1) command.Warning: this command was renamed into GETRANGE. SUBSTR will be taken as an alias until the next major release of Redis.

Return a subset of the string from offset start to offset end(both offsets are inclusive).Negative offsets can be used in order to provide an offset starting fromthe end of the string. So -1 means the last char, -2 the penultimate andso forth.
The function handles out of range requests without raising an error, butjust limiting the resulting range to the actual length of the string.

Return value

Bulk reply

Examples

 redis> set s "This is a string"
diff --git a/doc/VirtualMemoryUserGuide.html b/doc/VirtualMemoryUserGuide.html
index 7bc67b15..d4d6f759 100644
--- a/doc/VirtualMemoryUserGuide.html
+++ b/doc/VirtualMemoryUserGuide.html
@@ -39,7 +39,7 @@ vm-max-threads 4
 
This is the maximum number of threads used in order to perform I/O from/to the swap file. A good value is just to match the number of cores in your system.

However the special value of "0" will enable blocking VM. When VM is configured to be blocking it performs the I/O in a synchronous blocking way. This is what you can expect from blocking VM:
  • Clients accessing swapped out keys will block other clients while reading from disk, so the latency experimented by clients can be larger, especially if the disk is slow or busy and/or if there are big values swapped on disk.
  • The blocking VM performances are overall better, as there is no time lost in synchronization, spawning of threads, resuming blocked clients waiting for values.
So if you are willing to accept an higher latency from time to time, blocking VM can be a good pick, especially if swapping happens rarely as most of your often accessed data happens to fit in your memory.

If instead you have a lot of swap in and swap out operations and you have many cores that you want to exploit, and in general when you don't want that clients dealing with swapped values will block other clients for a few milliseconds (or more if the swapped value is very big), then it's better to use threaded VM.

To experiment with your dataset and different configurations is warmly encouraged...

Random things to know

A good place for the swap file

In many configurations the swap file can be fairly large, even 40GB or more. -Not all the kind of file systems are able to deal with large files in a good way, especially Mac OS X file system tends to be really lame about it.

The suggestion is to use Linux ext3 file system, or any other file system with good support for sparse files. What are sparse files?

Sparse files are files where a lot of the content happen to be empty. Advanced file systems like ext2, ext3, ext4, RaiserFS, Raiser4, and many others, are able to encode this files in a more efficient way and will allocate more space for the file when needed, that is, when more actual blocks of the file will be used.

The swap file is obviously pretty sparse, especially if the server is running since little time or it is much bigger compared to the amount of data swapped out. A file system not supporting sparse files can at some point block the Redis process while creating a very big file at once.

For a list of file systems supporting spare files check this Wikipedia page comparing different files systems.

Monitoring the VM

Once you have a Redis system with VM enabled up and running, you may be very interested in knowing how it's working: how many objects are swapped in total, the number of objects swapped and loaded every second, and so forth.

There is an utility that is very handy in checking how the VM is working, that is part of Redis Tools. This tool is called redis-stat, and using it is pretty straightforward:

+Not all the kind of file systems are able to deal with large files in a good way, especially Mac OS X file system tends to be really lame about it.

The suggestion is to use Linux ext3 file system, or any other file system with good support for sparse files. What are sparse files?

Sparse files are files where a lot of the content happen to be empty. Advanced file systems like ext2, ext3, ext4, RaiserFS, Raiser4, and many others, are able to encode this files in a more efficient way and will allocate more space for the file when needed, that is, when more actual blocks of the file will be used.

The swap file is obviously pretty sparse, especially if the server is running since little time or it is much bigger compared to the amount of data swapped out. A file system not supporting sparse files can at some point block the Redis process while creating a very big file at once.

For a list of file systems supporting spare files check this Wikipedia page comparing different files systems.

Monitoring the VM

Once you have a Redis system with VM enabled up and running, you may be very interested in knowing how it's working: how many objects are swapped in total, the number of objects swapped and loaded every second, and so forth.

There is an utility that is very handy in checking how the VM is working, that is part of Redis Tools. This tool is called redis-stat, and using it is pretty straightforward:

 $ ./redis-stat vmstat
  --------------- objects --------------- ------ pages ------ ----- memory -----
  load-in  swap-out  swapped   delta      used     delta      used     delta    
@@ -57,7 +57,6 @@ $ ./redis-stat vmstat
  10087    18784     886771    -1574     894577   -1828     200.36M  +91.60K   
  9330     19350     887411    +640       894817   +240       200.17M  -189.72K 
 
The above output is about a redis-server with VM enable, around 1 million of keys inside, and a lot of simulated load using the redis-load utility.

As you can see from the output a number of load-in and swap-out operations are happening every second. Note that the first line reports the actual values since the server was started, while the next lines are differences compared to the previous reading.

If you assigned enough memory to hold your working set of data, probably you should see a lot less dramatic swapping happening, so redis-stat can be a really valuable tool in order to understand if you need to shop for RAM ;)

Redis with VM enabled: better .rdb files or Append Only File?

When VM is enabled, saving and loading the database are much slower operations. A DB that usually loads in 2 seconds takes 13 seconds with VM enabled if the server is configured to use the smallest memory possible (that is, vm-max-memory set to 0).

So you probably want to switch to a configuration using the Append Only File for persistence, so that you can perform the BGREWRITEAOF from time to time.

It is important to note that while a BGSAVE or BGREWRITEAOF is in progress Redis does not swap new values on disk. The VM will be read-only while there is another child accessing it. So if you have a lot of writes while there is a child working, the memory usage may grow.

Using as little memory as possible

An interesting setup to turn Redis into an on-disk DB with just keys in memory is setting vm-max-memory to 0. If you don't mind some latency more and poorer performances but want to use very little memory for very big values, this is a good setup.

In this setup you should first try setting the VM as blocking (vm-max-threads 0) as with this configuration and high traffic the number of swap in and swap out operations will be huge, and threading will consume a lot of resources compared to a simple blocking implementation.

VM Stability

VM is still experimental code, but in the latest weeks it was tested in many ways in development environments, and even in some production environment. No bugs were noticed during this testing period. Still the more obscure bugs may happen in non controlled environments where there are setups that we are not able to reproduce for some reason.

In this stage you are encouraged to try VM in your development environment, and even in production if your DB is not mission critical, but for instance just a big persistent cache of data that may go away without too much problems.

Please report any problem you will notice to the Redis Google Group or by IRC joining the #redis IRC channel on freenode. -
diff --git a/doc/ZrankCommand.html b/doc/ZrankCommand.html index a0a3e39f..ccf8c23a 100644 --- a/doc/ZrankCommand.html +++ b/doc/ZrankCommand.html @@ -30,8 +30,9 @@

ZRANK _key_ _member_ (Redis >

1.3.4) =

ZREVRANK _key_ _member_ (Redis >

1.3.4) = Time complexity: O(log(N))
ZRANK returns the rank of the member in the sorted set, with scores ordered from low to high. ZREVRANK returns the rank with scores ordered from high to low. When the given member does not exist in the sorted set, the special value 'nil' is returned. The returned rank (or index) of the member is 0-based for both commands.
-

Return value

Bulk reply, specifically:

-the rank (an integer number) represented as an string.
+

Return value

Integer reply or a nil bulk reply, specifically:

+the rank of the element as an integer reply if the element exists.
+A nil bulk reply if there is no such element.
 
diff --git a/doc/index.html b/doc/index.html index 1c72b230..38e1c9f5 100644 --- a/doc/index.html +++ b/doc/index.html @@ -16,7 +16,7 @@
- = Redis Documentation =

Russian TranslationHello! The followings are pointers to different parts of the Redis Documentation.

-

HOWTOs about selected features

  • The Redis Replication HOWTO is what you need to read in order to understand how Redis master <-> slave replication works.
  • The Append Only File HOWTO explains how the alternative Redis durability mode works. AOF is an alternative to snapshotting on disk from time to time (the default).
  • Virtual Memory User Guide. A simple to understand guide about using and configuring the Redis Virtual Memory.
+ = Redis Documentation =

Russian TranslationHello! The followings are pointers to different parts of the Redis Documentation.

Getting started

+

Full programming examples

+

FAQs and benchmarks

  • The benchmark page is about the speed performances of Redis.
  • Our FAQ contains of course some answers to common questions about Redis. Not very up-to-date.
+

HOWTOs about selected features

Hacking

-
  • The Protocol Specification is all you need in order to implement a Redis client library for a missing language. PHP, Python, Ruby and Erlang are already supported.
-
  • Look at Redis Internals if you are interested in the implementation details of the Redis server.
-

Videos

+
  • The Protocol Specification is all you need in order to implement a Redis client library for a missing language. PHP, Python, Ruby and Erlang are already supported.
  • Look at Redis Internals if you are interested in the implementation details of the Redis server.
+

Videos

+

Recipes and books

  • The Redis Cookbook is a collaborative effort to provide some good recipe.
  • There is an ongoing effort to write a Redis book for O'Reilly
diff --git a/doc/redis.png b/doc/redis.png index 4578f00c32ec1b768cd3dc4e98edbe1721506c8e..abb69c09ec51ecb35554e12bb39abe9d56696bf1 100644 GIT binary patch literal 2801 zcmaJ@c{o&k8=i(jA`!|ujjhBi#xf>LF_wvuJ=teDn3%=P$;?Pavh~W62(MDF7NKmR zd{n&2t}Mw~LJP{iw5Yz(TYcXjU*EZ|bAHeByYBmb);~^yql1maMum+K2t7tEr7(E;c1^e;91<}~l0Gu=4 z`bR8*X9^DjK^6{)Q(JdV0D7gf55A07*Pu21o6u0v_N{*fbVM zV=`cCiX<}g2xtlyWcp7Dbk;9f2Iohc1Pw#-NGv28fm$o+Cy+?||4=&p7n%b)1OLhQ ze+qM4`78kG3~-o7*c8Fw0@T(*v2d1bfCMtxu1sdg&n`L!F+nCLh{=Lkx){KSBnpkO z=6}Z%i8um-1CkgNfPgoJ3ltDE8Wm@0jj=G=hqtyeMp>cJcx$Y+o{<#>i#Ebq3oJ{_ zPcEKGIYI{*;7=~~7uO2)TkhH_&{=}Wcz{g{1E|()CLQ*@WE}1Hx!`}R_k&CQZ7z7L z-*SRm7CxwOi&soG06&>YLCygWEUX|g~m3Rla@n~0K$>#?x4Rq|9FQ8+jnTTm^6 z(A9Vy`*4R`T!E{F&!t_r_xI4#u9Xh=)G${cC2EyVRk)~I%wL(9PT~e|@2}L()Mnkb z0cl2(TFN+TzH;7c7B_1kCi>ZMSs&VOY62Rv9yA;=6f>)U8b26}x-0%f?5(=81ExH! z;9JAvdnt|SGsUOB&ef7~-c_J24 z@=?9w_D8R87i-BYpIv$!3_iQx^4W6Y_RcJ4VVr6vrIREG6Ot{WMshc-9M&dH;zKf24`mn}5^vUB>_S6X?o zd+{Gv54-UWT#WZSm=V+c0=c|dB0-)US|{25gkzeKyXsChf1@+V$MP?4Hn(Y{x!@q` zkt>*>Dl#Thl5j(JC@ zv(+^M4KBo8{e)T-d}PdJ&m{d*0}L)NdKhQ<@AKgH-FaVEzR-lWA96v_1)XOz;N*dBM;v4 zNoSL-MYJ;wJ}DRZ9sT60vt?}E+vvkqiH&2553KP+H(g(uQqyLJ@A_^0ASIjnp>NFd zxl>qq zW+a%bqoC1#=5!FV_}u9Rq>(0IOUN1Mo9c##jikIKs#D47I0wp*%uLe)w!KtKE^l3r zZEN}tX*t5w%$7c0m`FyK^s}7z+^twWHVGj)^ObY*!f*Ho@epzOmX6(GjSE z#n`RbidccDX?N|iGbx)Atv)yGG_JdC){a&nN+$aCu7x9Apw!;Sq4~J#M`a!RM_xioR5u)Q zN^jw)=13<{&UA%N6h^oV3aL}0cT`*FeYvY<#N=kDK-$j94OA_%u6^D0{!^mnfs-2k zCzF#5{T!YSwGH({DhJ_&Lzrxj>2s9Ug77S@*H;H(O!QT|qIZ@&eP8{kDotu!(x;_Q zGur*;;ymY3+=OR#ueylN@&3RhJ5QBNed^)A;c;ptUru7zqJ*r(QhTtZv(vH=J0UAY zt#E4UM%_I#C`?mvn^?ff%bJu&vkk?7=E^IVSBQPY*%9W0?Ni$WA6D>>+bri`0AD;2AMS{ zf*fnIx24M3yi?UQERcsTCpQL^-adENs}V&&SY8!=H|zuu{cP)ct`C|rY< z?ibyZ6rEUfc( zAYMmy8t5;Z^tGlpZ4wfVv!6Z2*WD3tx8reewt075Z*kW`H+bP$iyP^rG@ z&x^t^@0NsdE$>94Wk1t<9W3lcQZ2g{SI0H`k3aIrX;LOaVL_zmalZXj>nR{Cvc`C_ z-)w#4;2&2+{ghSUi?q!!*{a$ujvmlP#u?P^kzhLTRL qieCyIx$Y4LQ)^Hb6AL^cj)EMBx4Air+<0~ECzN32fWKwofAZhJ&9Ei_ literal 4852 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