Because the clusterreadhandler processor for the read event is mainly responsible for parsing the data received on the cluster bus and subcontracting the message, and then processing the message. For packet subcontracting, You need to first understand the message structure, the message structure for communication between redis cluster nodes is defined as follows:
Typedef struct {char sig [4];/* siganture "rcmb" (redis cluster message Bus ). */uint32_t totlen;/* total length of this message */uint16_t ver;/* Protocol version, currently set to 0. */uint16_t notused0;/* 2 bytes not used. * // * message type, such as ping and Pong. For details about the definition, refer to clustermsg_type _ **/uint16_t type; uint16_t count;/* only used for some kind of messages. */uint64_t currentepoch;/* the epoch accordingly to the sending node. */uint64_t configepoch;/* The Config epoch if it's a master, or the last epoch advertised by its master if it is a slave. */uint64_t offset;/* master replication offset if node is a master or processed replication offset if node is a slave. * // node sender, represented by nodeid, for example, 123ed65d59ff22370f2f09546f109d31207789f6 char sender [redis_cluster_namelen]; /* Name of the sender node * // slots bits unsigned char myslots maintained by the current node [redis_cluster_slots/8]; // if the current node is a slave node, the slaveof record the corresponding master node ID char slaveof [redis_cluster_namelen]; char notused1 [32];/* 32 bytes reserved for future usage. */uint16_t port;/* sender TCP base port */uint16_t flags;/* sender node flags * // cluster status, such as redis_cluster_ OK, redis_cluster_fail... unsigned char state;/* cluster state from the POV of the sender */unsigned char mflags [3];/* message flags: clustermsg_flag [012] _... * /// message body pointing to different message types // see clustermsgdata structure description Union clustermsgdata data;} clustermsg;
From the above structure, we can see that the message subcontracting is mainly parsed in the first eight bytes, respectively:
-Char sig [4]; // message signature. For cluster messages, it is fixed to the Character Sequence rcmb.
-Uint32_t totlen; // total message length
Other structure members are used for message processing. They will be analyzed later when explaining the message processing process.
/* Read data. try to read the first field of the header first to check the * Full Length of the packet. when a whole packet is in memory this function * will call the function to process the packet. and so forth. */void clusterreadhandler (aeeventloop * El, int FD, void * privdata, int mask) {char Buf [sizeof (clustermsg)]; ssize_t nread; clustermsg * HDR; clusterlink * link = (clusterlink *) privdata; in T readlen, rcvbuflen; redis_notused (EL); redis_notused (mask); While (1) {/* read as long as there is data to read. */rcvbuflen = sdslen (Link-> rcvbuf); If (rcvbuflen <8) {/* First, obtain the first 8 bytes to get the full message * length. */readlen = 8-rcvbuflen;} else {// you already know the message length. // This code mainly calculates the remaining bytes to be read (readlen) is the complete message/* finally read the full message. */HDR = (clustermsg *) Link-> rcvb UF; If (rcvbuflen = 8) {/* perform some sanity check on the message signature * and length. */If (memcmp (HDR-> Sig, "rcmb", 4 )! = 0 | ntohl (HDR-> totlen) <clustermsg_min_len) {redislog (redis_warning, "Bad message length or signature received" "from cluster bus. "); handlelinkioerror (Link); Return ;}} readlen = ntohl (HDR-> totlen)-rcvbuflen; If (readlen> sizeof (BUF )) readlen = sizeof (BUF);} // read the remaining readlen bytes of the message record. // The FD here is not blocked, therefore, you need to determine eagain nread = read (FD, Buf, readlen); If (nread =-1 & errno = eagain) Re Turn;/* No more data ready. */If (nread <= 0) {/* I/O error... */redislog (redis_debug, "I/O Error reading from node link: % s", (nread = 0 )? "Connection closed": strerror (errno); handlelinkioerror (Link); return;} else {/* read data and recast the pointer to the new buffer. */link-> rcvbuf = sdscatlen (Link-> rcvbuf, Buf, nread); HDR = (clustermsg *) Link-> rcvbuf; rcvbuflen + = nread ;} /* total length obtained? Process this packet. */If (rcvbuflen> = 8 & rcvbuflen = ntohl (HDR-> totlen )) {// indicates that the rcvbuf on the link is already a complete cluster message // the following processes the message if (clusterprocesspacket (Link) {sdsfree (Link-> rcvbuf ); link-> rcvbuf = sdsempty ();} else {return;/* link no longer valid. */}}}}
This article is from the "quiet Madman" blog, please be sure to keep this source http://quietmadman.blog.51cto.com/3269500/1558889
[Original] Implementation of redis cluster-receiving and subcontracting of cluster messages