Redis has adopted the new unified protocol since version 1.2 and has become the standard mode for interaction with redis server since version 2.0. The redis protocol is a compromise that balances the following requirements:
- Simple implementation
- Computer quick resolution
- Simple enough for manual explanation
Overview
The client connects to the redis server through the tcp6379 port. every redis command or data transmitted between client servers ends with \ r \ n (CRLF. redis accepts commands and parameters, and the server receives the commands and then processes them and sends them back to the client.
For the complete content of the Protocol, see the following http://redis.io/topics/protocol's overview diagram of the Protocol:
Request requests
All data sent to the redis server in the new unified request protocol is binary safe. What is binary security? See Wikipedia http://en.wikipedia.org/wiki/Binary-safe to briefly describe binary security functions to treat all input as the original data stream without a specific format, in other words not parse the data according to a specific format, a byte (8 bits) all the 256 values that may be expressed in the data can be properly interpreted.
The following describes the format of redis request:
* <Number of arguments> cr lf % ParametersQuantity $ <nuMber of bytes of argument 1> data of cr lf % parameter 1 <argument data> cr lf % parameter 1... $ <number of bytes of argument n> cr lf % parameter n Bytes <argument data> cr lf % parameter n data
The following is an example that complies with the above specifications:
"* 3 \ r \ N $3 \ r \ NSET \ r \ N $5 \ r \ nmykey \ r \ N $7 \ r \ nmyvalue \ r \ n"
The redis response uses the same structure.$6 \ r \ nmydata \ r \ n is called
Bulk reply. If redis returns a data item list, it is called multi-bulk reply. In this case, a * <arg_count> \ r \ n data header is added before a group of bulk reply.
Response replies
The first byte of the Response Message represents the type of the message:
- Single-line message "+"
- Error message "-"
- Returns an integer value ":"
- Returns bulk reply "$"
- Return multi-bulk reply"
*
"
Status response
Status response (single row response) is a single row string ending with + start \ r \ n, for example, + OK
The client class library should return all the content after + characters. In the above example, OK is returned.
The client library shoshould return everything after the "+", that is, the string "OK" in this example.
Error Response
The error response is similar to the status response. The only difference is that the first character is "-". An error response is sent only when an exception occurs, for example, you perform an operation on the wrong data type, and the command does not exist. when an error response is received, the client class library should throw an exception.
Integer response
The response type starts with ":". The data body is an integer string ending with CRLF. Example: ": 0 \ r \ n "": 1000 \ r \ n"
Commands such as incr and lastsave use integer values to respond. This value has no special meaning. incr is only an auto-increment value, and lastsave is a UNIX time. the Return Value of the exists command indicates that 1 represents true 0 represents false. for example, if sadd or Srem setnx is returned, 1 indicates that the operation is successful, and 0 indicates other cases. the following command returns an integer response: setnx, Del, exists, incr, incrby, decr, decrby, dbsize, lastsave, renamenx, move, llen, sadd, Srem, sismember, scard
Block response bulk replies
Bulk replies is used to return a single binary secure string, for example:
Get mykey % client request
$6 \ r \ nfoobar \ r \ n % Server Response
The server's response starts with $, followed by a number representing the number of bytes of the response followed by CRLF, followed by the actual data, followed by two CRLF bytes indicating the end.
If the value without a request does not exist, bulk reply uses the special value-1 to indicate the Data Length. For example:
Get nonexistingkey % client requests a nonexistent key
$-1% the server returns a result with a Data Length of-1.
When the client class library encounters a condition where the value does not exist, do not return a Null String. The Null Object (nil object) should be returned. For example, the ruby class library returns nil, the C Class Library returns NULL, and so on.
Multi-bulk replies
Commands like lrange return multiple values (each element in the list has one value, and lrange needs to return more than one element). The returned value structure starts with * and then the number of block data.
If the given key does not exist, the key corresponds to an empty list. The number of block data values is 0. For example:
Lrange nokey 0 1% client request
* 0% Server Response
When the blpop command times out, an empty multi bulk reply response (nil multi bulk reply) is returned. The value of-1 should be parsed as a null object, for example:
Blpop key 1
*-1
In this case, the client API should return an empty object instead of an empty list, so that the empty list and the error can be distinguished.
Nil elements in Multi-bulk replies of multiple responses
An element in a multi-block response may return a value of-1, indicating that the element is not found to distinguish it from a null string. the specified key value cannot be found when you use get and sort commands. for example: "* 3 \ r \ N $3 \ r \ nfoo \ r \ N $-1 \ r \ N $3 \ r \ nbar \ r \ n" the second element here is null Value, the client should return a value similar to this: ["foo", nil, "bar"]
Multiple commands and Pipelines
A client can use the same connection to send multiple commands. MPs queue allows the client to send multiple commands after one write operation. there is no need to wait for the Service to respond before sending the next command. finally, all response results can be read. usually, the redis server and the client have a quick link. It is not important for the client to realize this feature. If an applicationProgramA large number of commands need to be sent in a short time to use pipelines much faster.
Separation between theory and practice
Protocol implementation in. Net Client
Redis. Net version of the open source client has a lot, here we select the project is booksleeve, Project address: http://code.google.com/p/booksleeve/
Stack exchange of the famous technology Q & A site uses this project. For details, refer to http://www.biaodianfu.com/stack-exchanges-ubunture.html.Code:
// Source: Https://github.com/migueldeicaza/redis-sharp/blob/master/redis-sharp.cs
Public Void Set (idictionary < String , Byte []> Dict)
{
If (Dict = Null )
Throw New Argumentnullexception ( " Dict " );
VaR NL = encoding. utf8.getbytes ( " \ R \ n " );
VaR MS = New Memorystream ();
Foreach ( VaR Key In Dict. Keys)
{
VaR Val = dict [Key];
VaR Klength = encoding. utf8.getbytes ( " $ " + Key. Length + " \ R \ n " );
VaR K = encoding. utf8.getbytes (Key + " \ R \ n " );
VaR Vlength = encoding. utf8.getbytes ( " $ " + Val. Length + " \ R \ n " );
Ms. Write (klength, 0 , Klength. Length );
Ms. Write (K, 0 , K. Length );
Ms. Write (vlength, 0 , Vlength. Length );
Ms. Write (Val, 0 , Val. Length );
Ms. Write (NL,0 , NL. Length );
}
Senddatacommand (Ms. toarray (), " * " + (Dict. Count * 2 + 1 ) + " \ R \ N $4 \ r \ nmset \ r \ n " );
Expectsuccess ();
}
Protocol implementation in Erlang Client
Redis Erlang version of the client we can look at the Erl-redis written by Li Tao, Project address: https://github.com/litaocheng/erl-redis
The following is a piece of code extracted from redis_proto.erl. It is obvious that Erlang is more expressive of binary data than above. compared with the language, the Net version has much less syntax noise, and the implementation of redis-related protocols is more intuitive;
% @ Doc generate the mbulk command
Mbulk (type)->
[< " * 1 " >> ,? CRLF, mbulk0 (type)].
Mbulk (type, ARG)->
[< " * 2 " >> ,? CRLF, mbulk0 (type), mbulk0 (ARG)].
Mbulk (type, arg1, arg2)->
[< " * 3 " >> ,? CRLF, mbulk0 (type), mbulk0 (arg1), mbulk0 (arg2)].
Mbulk (type, arg1, arg2, arg3)->
[< " * 4 " >> ,? CRLF, mbulk0 (type), mbulk0 (arg1), mbulk0 (arg2), mbulk0 (arg3)].
Mbulk (type, arg1, arg2, arg3, arg4)->
[< " * 5 " >> ,? CRLF, mbulk0 (type), mbulk0 (arg1), mbulk0 (arg2), mbulk0 (arg3), mbulk0 (arg4)].
Mbulk_list (l)->
N = length (L ),
Lines = [mbulk0 (e) | E <-L],
[< " * " >> ,? N2s (N ),? CRLF, lines].
% @ Doc parse the reply
Parse_reply (< " + " , Rest/binary>)->
Parse_status_reply (rest );
Parse_reply (< " - " , Rest/binary>)->
Parse_error_reply (rest );
Parse_reply (< " : " , Rest/binary>)->
B2n (rest );
Parse_reply (< " $-1 \ r \ n " >>)->
Null ;
Parse_reply (< " $0 \ r \ n " >>)->
{Bulk_more, 0 };
Parse_reply (< " $ " , Rest/binary>)->
N = b2n (rest ),
{Bulk_more, n };
Parse_reply (< " *-1 \ r \ n " >>)->
Null ;
Parse_reply (< " * 0 \ r \ n " >>)->
Null ;
Parse_reply (< " * " , Rest/binary>)->
N = b2n (rest ),
{Mbulk_more, n }.
OK, today is here, the above two versions of the implementation code are very good, you can download to have a look. For more redis client selection please refer to here: http://redis.io/clients