Redis Client Protocol Implementation

Source: Internet
Author: User

There are many Redis clients that have already been http://redis.io/clients in the official website, so you can refer to them.

In fact, the previous article http://blog.csdn.net/yitouhan/article/details/46612925 Redis Client protocol analysis, I have done the main analysis of resp.


Here are all the functions that parse RESP, where the external function is Redisprotocol::D ecode:

Https://github.com/XJM2013/GameEngine/blob/master/lib/src/redis/redisprotocol.cpp

static unsigned intendline (const char *buf, unsigned int len), static intreadnumber (const char *buf, unsigned int len); stat IC char_readstring (const char *buf, unsigned int left_len, int &read_len, Redisdata **data), Static intreadmessage (cha R type, const char *buf, unsigned int len, redisbulkdata **bulk_data), Static intreadinteger (const char *BUF, unsigned int Len, Redisbulkdata **bulk_data); static intreadstring (const char *buf, unsigned int len, redisbulkdata **bulk_data);  Static Intreadarray (const char *buf, unsigned int left_len, redisbulkdata **bulk_data),/*:1\r\n prefix + result + end will have a minimum of 4 bytes */int Redisprotocol::D ecode (const char *buf, unsigned int len, redisbulkdata **bulk_data) {if (Len < 4) {return opr_more_data; }switch (Buf[0]) {case ' + ': Return Readmessage (REPLY_TYPE_OK, buf + 1, len-1, bulk_data); case '-': Return Readmessage (REPLY _type_error, buf + 1, len-1, bulk_data); case ': ': Return Readinteger (buf + 1, len-1, bulk_data); case ' $ ': return READSTR ING (buf + 1, len-1, Bulk_data)Case ' * ': return Readarray (buf + 1, len-1, bulk_data);d Efault:return opr_data_invalid;} return opr_data_invalid;}
From the above code, it can be seen that the structure of the code is quite clear, concise, and the function of the code is only the processing of the Protocol, not including network modules and other more complex package processing, do not need to do additional discrimination reading. For the learning agreement, the individual feels that it is still a good choice. In the code I have to do some memory pool functions, do not want to use, can be used New/delete or malloc/free instead.
I'll take the following 5 examples from the previous article as a test example:

Https://github.com/XJM2013/GameEngine/blob/master/Test/testredis.h

#ifndef test_redis_h#define test_redis_h#include <string> #include "lib/include/redis/redisprotocol.h" Namespace Testredis{void showbulkdata (Redisbulkdata *data) {std::list<redisdata *>::iterator ITR = Data->data _list.begin (); for (; ITR! = Data->data_list.end (); ++itr) {printf ("type =%d\n", (*ITR)->type); switch ((*ITR) Type) {case Redisprotocol::reply_type_integer:case redisprotocol::reply_type_string_error:case RedisProtocol:: reply_type_array_error:printf ("data =%d\n", * (int *) (*ITR)->data); break;default:printf ("data =%.*s\n", (*ITR)- >len, (*ITR)->data); void Decode (char *reply) {Redisbulkdata *data = null;if (redisprotocol::D ecode (reply, strlen (reply), &data) <= Redisprotocol::opr_more_data) {return;} Showbulkdata (data);d elete data;} Short string void Test1 () {char *reply = "+ok\r\n";D Ecode (reply);} Error void Test2 () {char *reply = '-err unknown command ' seet ' \ r \ n ';D ecode (reply);} integer void Test3 () {Char *reply = ": 11\r\n";D ecode (reply);} Long string void TeSt4 () {char *reply1 = "$3\r\ncat\r\n";p rintf ("reply1:\n");D Ecode (reply1); char *reply2 = "$-1\r\n";p rintf ("reply2:\n") ;D Ecode (reply2);} array void Test5 () {char *reply1 = "*2\r\n$3\r\ncat\r\n$2\r\n11\r\n";p rintf ("reply1:\n");D Ecode (reply1); char *reply2 = " *2\r\n$4\r\nfish\r\n$-1\r\n ";p rintf (" reply2:\n ");D Ecode (reply2), char *reply3 =" *-1\r\n ";p rintf (" reply3:\n ");D Ecode (Reply3);}} #endif
Output the results of TEST5 () below:


Protocol Resolution Summary:

1, from the point of view of C + +, serialization to save data, parsing faster.

For example, 1000 data is serialized into 1 data:

From the point of view of allocating space, 1000 data need allocate 1000 space, 1 data need allocate 1 times space.

From an analytic point of view, the structure of RESP is the LV structure, the length-value (LENGTH-VALUE) structure, which does not require a flag type (T,type), because its type is a string type. The serialization implementation can be a combination of TV and TLV structures. Therefore, the C + + type is one by one corresponding to the length, the integer is 4 bytes, and the TLV structure is used for the string. It's just a matter of comparing the RESP L with the serialized T. One needs to match "\ r \ n" and convert the string to a number, and one will only need to read the first byte to determine the length of the data.

2, set key val\r\n, when the Val is very long, such as 10k bytes long, the server to match 10k times to match to \ r \ n, and Val is not allowed to appear \ r \ n otherwise error.


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Redis Client Protocol Implementation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.