1 #ifndef __REDIS_CLUSTER_H 2 #define __REDIS_CLUSTER_H 3 4 /*----------------------------------------------------------------------------- 5 * Redis cluster data structures, defines, exported API. 6 *----------------------------------------------------------------------------*/ 7 8 #define REDIS_CLUSTER_SLOTS 16384 9 #define REDIS_CLUSTER_OK 0 /* Everything looks ok */ 10 #define REDIS_CLUSTER_FAIL 1 /* The cluster can't work */ 11 #define REDIS_CLUSTER_NAMELEN 40 /* sha1 hex length */ 12 #define REDIS_CLUSTER_PORT_INCR 10000 /* Cluster port = baseport + PORT_INCR */ 13 14 /* The following defines are amunt of time, sometimes expressed as 15 * multiplicators of the node timeout value (when ending with MULT). */ 16 #define REDIS_CLUSTER_DEFAULT_NODE_TIMEOUT 15000 17 #define REDIS_CLUSTER_FAIL_REPORT_VALIDITY_MULT 2 /* Fail report validity. */ 18 #define REDIS_CLUSTER_FAIL_UNDO_TIME_MULT 2 /* Undo fail if master is back. */ 19 #define REDIS_CLUSTER_FAIL_UNDO_TIME_ADD 10 /* Some additional time. */ 20 #define REDIS_CLUSTER_SLAVE_VALIDITY_MULT 10 /* Slave data validity. */ 21 #define REDIS_CLUSTER_FAILOVER_AUTH_RETRY_MULT 4 /* Auth request retry time. */ 22 #define REDIS_CLUSTER_FAILOVER_DELAY 5 /* Seconds */ 23 #define REDIS_CLUSTER_DEFAULT_MIGRATION_BARRIER 1 24 #define REDIS_CLUSTER_MF_TIMEOUT 5000 /* Milliseconds to do a manual failover. */ 25 #define REDIS_CLUSTER_MF_PAUSE_MULT 2 /* Master pause manual failover mult. */ 26 27 struct clusterNode; 28 29 /* clusterLink encapsulates everything needed to talk with a remote node. */ 30 typedef struct clusterLink { 31 mstime_t ctime; /* Link creation time */ 32 int fd; /* TCP socket file descriptor */ 33 sds sndbuf; /* Packet send buffer */ 34 sds rcvbuf; /* Packet reception buffer */ 35 struct clusterNode *node; /* Node related to this link if any, or NULL */ 36 } clusterLink; 37 38 /* Cluster node flags and macros. */ 39 #define REDIS_NODE_MASTER 1 /* The node is a master */ 40 #define REDIS_NODE_SLAVE 2 /* The node is a slave */ 41 #define REDIS_NODE_PFAIL 4 /* Failure? Need acknowledge */ 42 #define REDIS_NODE_FAIL 8 /* The node is believed to be malfunctioning */ 43 #define REDIS_NODE_MYSELF 16 /* This node is myself */ 44 #define REDIS_NODE_HANDSHAKE 32 /* We have still to exchange the first ping */ 45 #define REDIS_NODE_NOADDR 64 /* We don't know the address of this node */ 46 #define REDIS_NODE_MEET 128 /* Send a MEET message to this node */ 47 #define REDIS_NODE_PROMOTED 256 /* Master was a slave propoted by failover */ 48 #define REDIS_NODE_NULL_NAME "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" 49 50 #define nodeIsMaster(n) ((n)->flags & REDIS_NODE_MASTER) 51 #define nodeIsSlave(n) ((n)->flags & REDIS_NODE_SLAVE) 52 #define nodeInHandshake(n) ((n)->flags & REDIS_NODE_HANDSHAKE) 53 #define nodeHasAddr(n) (!((n)->flags & REDIS_NODE_NOADDR)) 54 #define nodeWithoutAddr(n) ((n)->flags & REDIS_NODE_NOADDR) 55 #define nodeTimedOut(n) ((n)->flags & REDIS_NODE_PFAIL) 56 #define nodeFailed(n) ((n)->flags & REDIS_NODE_FAIL) 57 58 /* This structure represent elements of node->fail_reports. */ 59 struct clusterNodeFailReport { 60 struct clusterNode *node; /* Node reporting the failure condition. */ 61 mstime_t time; /* Time of the last report from this node. */ 62 } typedef clusterNodeFailReport; 63 64 struct clusterNode { 65 mstime_t ctime; /* Node object creation time. */ 66 char name[REDIS_CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */ 67 int flags; /* REDIS_NODE_... */ 68 uint64_t configEpoch; /* Last configEpoch observed for this node */ 69 unsigned char slots[REDIS_CLUSTER_SLOTS/8]; /* slots handled by this node */ 70 int numslots; /* Number of slots handled by this node */ 71 int numslaves; /* Number of slave nodes, if this is a master */ 72 struct clusterNode **slaves; /* pointers to slave nodes */ 73 struct clusterNode *slaveof; /* pointer to the master node */ 74 mstime_t ping_sent; /* Unix time we sent latest ping */ 75 mstime_t pong_received; /* Unix time we received the pong */ 76 mstime_t fail_time; /* Unix time when FAIL flag was set */ 77 mstime_t voted_time; /* Last time we voted for a slave of this master */ 78 mstime_t repl_offset_time; /* Unix time we received offset for this node */ 79 long long repl_offset; /* Last known repl offset for this node. */ 80 char ip[REDIS_IP_STR_LEN]; /* Latest known IP address of this node */ 81 int port; /* Latest known port of this node */ 82 clusterLink *link; /* TCP/IP link with this node */ 83 list *fail_reports; /* List of nodes signaling this as failing */ 84 }; 85 typedef struct clusterNode clusterNode; 86 87 typedef struct clusterState { 88 clusterNode *myself; /* This node */ 89 uint64_t currentEpoch; 90 int state; /* REDIS_CLUSTER_OK, REDIS_CLUSTER_FAIL, ... */ 91 int size; /* Num of master nodes with at least one slot */ 92 dict *nodes; /* Hash table of name -> clusterNode structures */ 93 dict *nodes_black_list; /* Nodes we don't re-add for a few seconds. */ 94 clusterNode *migrating_slots_to[REDIS_CLUSTER_SLOTS]; 95 clusterNode *importing_slots_from[REDIS_CLUSTER_SLOTS]; 96 clusterNode *slots[REDIS_CLUSTER_SLOTS]; 97 zskiplist *slots_to_keys; 98 /* The following fields are used to take the slave state on elections. */ 99 mstime_t failover_auth_time; /* Time of previous or next election. */ 100 int failover_auth_count; /* Number of votes received so far. */ 101 int failover_auth_sent; /* True if we already asked for votes. */ 102 int failover_auth_rank; /* This slave rank for current auth request. */ 103 uint64_t failover_auth_epoch; /* Epoch of the current election. */ 104 /* Manual failover state in common. */ 105 mstime_t mf_end; /* Manual failover time limit (ms unixtime). 106 It is zero if there is no MF in progress. */ 107 /* Manual failover state of master. */ 108 clusterNode *mf_slave; /* Slave performing the manual failover. */ 109 /* Manual failover state of slave. */ 110 long long mf_master_offset; /* Master offset the slave needs to start MF 111 or zero if stil not received. */ 112 int mf_can_start; /* If non-zero signal that the manual failover 113 can start requesting masters vote. */ 114 /* The followign fields are uesd by masters to take state on elections. */ 115 uint64_t last_vote_epoch; /* Epoch of the last vote granted. */ 116 int todo_before_sleep; /* Things to do in clusterBeforeSleep(). */ 117 long long stats_bus_messages_sent; /* Num of msg sent via cluster bus. */ 118 long long stats_bus_messages_received; /* Num of msg rcvd via cluster bus.*/ 119 } clusterState; 120 121 /* clusterState todo_before_sleep flags. */ 122 #define CLUSTER_TODO_HANDLE_FAILOVER (1<<0) 123 #define CLUSTER_TODO_UPDATE_STATE (1<<1) 124 #define CLUSTER_TODO_SAVE_CONFIG (1<<2) 125 #define CLUSTER_TODO_FSYNC_CONFIG (1<<3) 126 127 /* Redis cluster messages header */ 128 129 /* Note that the PING, PONG and MEET messages are actually the same exact 130 * kind of packet. PONG is the reply to ping, in the exact format as a PING, 131 * while MEET is a special PING that forces the receiver to add the sender 132 * as a node (if it is not already in the list). */ 133 #define CLUSTERMSG_TYPE_PING 0 /* Ping */ 134 #define CLUSTERMSG_TYPE_PONG 1 /* Pong (reply to Ping) */ 135 #define CLUSTERMSG_TYPE_MEET 2 /* Meet "let's join" message */ 136 #define CLUSTERMSG_TYPE_FAIL 3 /* Mark node xxx as failing */ 137 #define CLUSTERMSG_TYPE_PUBLISH 4 /* Pub/Sub Publish propagation */ 138 #define CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 5 /* May I failover? */ 139 #define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6 /* Yes, you have my vote */ 140 #define CLUSTERMSG_TYPE_UPDATE 7 /* Another node slots configuration */ 141 #define CLUSTERMSG_TYPE_MFSTART 8 /* Pause clients for manual failover */ 142 143 /* Initially we don't know our "name", but we'll find it once we connect 144 * to the first node, using the getsockname() function. Then we'll use this 145 * address for all the next messages. */ 146 typedef struct { 147 char nodename[REDIS_CLUSTER_NAMELEN]; 148 uint32_t ping_sent; 149 uint32_t pong_received; 150 char ip[REDIS_IP_STR_LEN]; /* IP address last time it was seen */ 151 uint16_t port; /* port last time it was seen */ 152 uint16_t flags; 153 uint32_t notused; /* for 64 bit alignment */ 154 } clusterMsgDataGossip; 155 156 typedef struct { 157 char nodename[REDIS_CLUSTER_NAMELEN]; 158 } clusterMsgDataFail; 159 160 typedef struct { 161 uint32_t channel_len; 162 uint32_t message_len; 163 unsigned char bulk_data[8]; /* defined as 8 just for alignment concerns. */ 164 } clusterMsgDataPublish; 165 166 typedef struct { 167 uint64_t configEpoch; /* Config epoch of the specified instance. */ 168 char nodename[REDIS_CLUSTER_NAMELEN]; /* Name of the slots owner. */ 169 unsigned char slots[REDIS_CLUSTER_SLOTS/8]; /* Slots bitmap. */ 170 } clusterMsgDataUpdate; 171 172 union clusterMsgData { 173 /* PING, MEET and PONG */ 174 struct { 175 /* Array of N clusterMsgDataGossip structures */ 176 clusterMsgDataGossip gossip[1]; 177 } ping; 178 179 /* FAIL */ 180 struct { 181 clusterMsgDataFail about; 182 } fail; 183 184 /* PUBLISH */ 185 struct { 186 clusterMsgDataPublish msg; 187 } publish; 188 189 /* UPDATE */ 190 struct { 191 clusterMsgDataUpdate nodecfg; 192 } update; 193 }; 194 195 196 typedef struct { 197 char sig[4]; /* Siganture "RCmb" (Redis Cluster message bus). */ 198 uint32_t totlen; /* Total length of this message */ 199 uint16_t ver; /* Protocol version, currently set to 0. */ 200 uint16_t notused0; /* 2 bytes not used. */ 201 uint16_t type; /* Message type */ 202 uint16_t count; /* Only used for some kind of messages. */ 203 uint64_t currentEpoch; /* The epoch accordingly to the sending node. */ 204 uint64_t configEpoch; /* The config epoch if it's a master, or the last 205 epoch advertised by its master if it is a 206 slave. */ 207 uint64_t offset; /* Master replication offset if node is a master or 208 processed replication offset if node is a slave. */ 209 char sender[REDIS_CLUSTER_NAMELEN]; /* Name of the sender node */ 210 unsigned char myslots[REDIS_CLUSTER_SLOTS/8]; 211 char slaveof[REDIS_CLUSTER_NAMELEN]; 212 char notused1[32]; /* 32 bytes reserved for future usage. */ 213 uint16_t port; /* Sender TCP base port */ 214 uint16_t flags; /* Sender node flags */ 215 unsigned char state; /* Cluster state from the POV of the sender */ 216 unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */ 217 union clusterMsgData data; 218 } clusterMsg; 219 220 #define CLUSTERMSG_MIN_LEN (sizeof(clusterMsg)-sizeof(union clusterMsgData)) 221 222 /* Message flags better specify the packet content or are used to 223 * provide some information about the node state. */ 224 #define CLUSTERMSG_FLAG0_PAUSED (1<<0) /* Master paused for manual failover. */ 225 #define CLUSTERMSG_FLAG0_FORCEACK (1<<1) /* Give ACK to AUTH_REQUEST even if 226 master is up. */ 227 228 /* ---------------------- API exported outside cluster.c -------------------- */ 229 clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask); 230 231 #endif /* __REDIS_CLUSTER_H */ 232