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