cluster.h 12.8 KB
Newer Older
A
antirez 已提交
1 2
#ifndef __CLUSTER_H
#define __CLUSTER_H
3 4 5 6 7

/*-----------------------------------------------------------------------------
 * Redis cluster data structures, defines, exported API.
 *----------------------------------------------------------------------------*/

A
antirez 已提交
8 9 10 11 12
#define CLUSTER_SLOTS 16384
#define CLUSTER_OK 0          /* Everything looks ok */
#define CLUSTER_FAIL 1        /* The cluster can't work */
#define CLUSTER_NAMELEN 40    /* sha1 hex length */
#define CLUSTER_PORT_INCR 10000 /* Cluster port = baseport + PORT_INCR */
13

14
/* The following defines are amount of time, sometimes expressed as
15
 * multiplicators of the node timeout value (when ending with MULT). */
A
antirez 已提交
16 17 18 19 20 21 22 23 24 25
#define CLUSTER_DEFAULT_NODE_TIMEOUT 15000
#define CLUSTER_DEFAULT_SLAVE_VALIDITY 10 /* Slave max data age factor. */
#define CLUSTER_DEFAULT_REQUIRE_FULL_COVERAGE 1
#define CLUSTER_FAIL_REPORT_VALIDITY_MULT 2 /* Fail report validity. */
#define CLUSTER_FAIL_UNDO_TIME_MULT 2 /* Undo fail if master is back. */
#define CLUSTER_FAIL_UNDO_TIME_ADD 10 /* Some additional time. */
#define CLUSTER_FAILOVER_DELAY 5 /* Seconds */
#define CLUSTER_DEFAULT_MIGRATION_BARRIER 1
#define CLUSTER_MF_TIMEOUT 5000 /* Milliseconds to do a manual failover. */
#define CLUSTER_MF_PAUSE_MULT 2 /* Master pause manual failover mult. */
A
antirez 已提交
26
#define CLUSTER_SLAVE_MIGRATION_DELAY 5000 /* Delay for slave migration. */
27

28
/* Redirection errors returned by getNodeByQuery(). */
A
antirez 已提交
29 30 31 32 33 34 35
#define CLUSTER_REDIR_NONE 0          /* Node can serve the request. */
#define CLUSTER_REDIR_CROSS_SLOT 1    /* -CROSSSLOT request. */
#define CLUSTER_REDIR_UNSTABLE 2      /* -TRYAGAIN redirection required */
#define CLUSTER_REDIR_ASK 3           /* -ASK redirection required. */
#define CLUSTER_REDIR_MOVED 4         /* -MOVED redirection required. */
#define CLUSTER_REDIR_DOWN_STATE 5    /* -CLUSTERDOWN, global state. */
#define CLUSTER_REDIR_DOWN_UNBOUND 6  /* -CLUSTERDOWN, unbound slot. */
36

37 38 39 40
struct clusterNode;

/* clusterLink encapsulates everything needed to talk with a remote node. */
typedef struct clusterLink {
41
    mstime_t ctime;             /* Link creation time */
42 43 44 45 46 47
    int fd;                     /* TCP socket file descriptor */
    sds sndbuf;                 /* Packet send buffer */
    sds rcvbuf;                 /* Packet reception buffer */
    struct clusterNode *node;   /* Node related to this link if any, or NULL */
} clusterLink;

48
/* Cluster node flags and macros. */
A
antirez 已提交
49 50 51 52 53 54 55 56
#define CLUSTER_NODE_MASTER 1     /* The node is a master */
#define CLUSTER_NODE_SLAVE 2      /* The node is a slave */
#define CLUSTER_NODE_PFAIL 4      /* Failure? Need acknowledge */
#define CLUSTER_NODE_FAIL 8       /* The node is believed to be malfunctioning */
#define CLUSTER_NODE_MYSELF 16    /* This node is myself */
#define CLUSTER_NODE_HANDSHAKE 32 /* We have still to exchange the first ping */
#define CLUSTER_NODE_NOADDR   64  /* We don't know the address of this node */
#define CLUSTER_NODE_MEET 128     /* Send a MEET message to this node */
57
#define CLUSTER_NODE_MIGRATE_TO 256 /* Master elegible for replica migration. */
A
antirez 已提交
58
#define CLUSTER_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"
59

A
antirez 已提交
60 61 62 63 64 65 66
#define nodeIsMaster(n) ((n)->flags & CLUSTER_NODE_MASTER)
#define nodeIsSlave(n) ((n)->flags & CLUSTER_NODE_SLAVE)
#define nodeInHandshake(n) ((n)->flags & CLUSTER_NODE_HANDSHAKE)
#define nodeHasAddr(n) (!((n)->flags & CLUSTER_NODE_NOADDR))
#define nodeWithoutAddr(n) ((n)->flags & CLUSTER_NODE_NOADDR)
#define nodeTimedOut(n) ((n)->flags & CLUSTER_NODE_PFAIL)
#define nodeFailed(n) ((n)->flags & CLUSTER_NODE_FAIL)
67

68
/* Reasons why a slave is not able to failover. */
A
antirez 已提交
69 70 71 72 73 74
#define CLUSTER_CANT_FAILOVER_NONE 0
#define CLUSTER_CANT_FAILOVER_DATA_AGE 1
#define CLUSTER_CANT_FAILOVER_WAITING_DELAY 2
#define CLUSTER_CANT_FAILOVER_EXPIRED 3
#define CLUSTER_CANT_FAILOVER_WAITING_VOTES 4
#define CLUSTER_CANT_FAILOVER_RELOG_PERIOD (60*5) /* seconds. */
75

76
/* This structure represent elements of node->fail_reports. */
A
antirez 已提交
77
typedef struct clusterNodeFailReport {
78
    struct clusterNode *node;  /* Node reporting the failure condition. */
79
    mstime_t time;             /* Time of the last report from this node. */
A
antirez 已提交
80
} clusterNodeFailReport;
81

A
antirez 已提交
82
typedef struct clusterNode {
83
    mstime_t ctime; /* Node object creation time. */
A
antirez 已提交
84 85
    char name[CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */
    int flags;      /* CLUSTER_NODE_... */
86
    uint64_t configEpoch; /* Last configEpoch observed for this node */
A
antirez 已提交
87
    unsigned char slots[CLUSTER_SLOTS/8]; /* slots handled by this node */
88 89 90
    int numslots;   /* Number of slots handled by this node */
    int numslaves;  /* Number of slave nodes, if this is a master */
    struct clusterNode **slaves; /* pointers to slave nodes */
91 92 93 94
    struct clusterNode *slaveof; /* pointer to the master node. Note that it
                                    may be NULL even if the node is a slave
                                    if we don't have the master node in our
                                    tables. */
95 96 97 98 99
    mstime_t ping_sent;      /* Unix time we sent latest ping */
    mstime_t pong_received;  /* Unix time we received the pong */
    mstime_t fail_time;      /* Unix time when FAIL flag was set */
    mstime_t voted_time;     /* Last time we voted for a slave of this master */
    mstime_t repl_offset_time;  /* Unix time we received offset for this node */
A
antirez 已提交
100
    mstime_t orphaned_time;     /* Starting time of orphaned master condition */
101
    long long repl_offset;      /* Last known repl offset for this node. */
A
antirez 已提交
102
    char ip[NET_IP_STR_LEN];  /* Latest known IP address of this node */
103 104 105
    int port;                   /* Latest known port of this node */
    clusterLink *link;          /* TCP/IP link with this node */
    list *fail_reports;         /* List of nodes signaling this as failing */
A
antirez 已提交
106
} clusterNode;
107 108 109 110

typedef struct clusterState {
    clusterNode *myself;  /* This node */
    uint64_t currentEpoch;
A
antirez 已提交
111
    int state;            /* CLUSTER_OK, CLUSTER_FAIL, ... */
112 113
    int size;             /* Num of master nodes with at least one slot */
    dict *nodes;          /* Hash table of name -> clusterNode structures */
114
    dict *nodes_black_list; /* Nodes we don't re-add for a few seconds. */
A
antirez 已提交
115 116 117
    clusterNode *migrating_slots_to[CLUSTER_SLOTS];
    clusterNode *importing_slots_from[CLUSTER_SLOTS];
    clusterNode *slots[CLUSTER_SLOTS];
118 119
    zskiplist *slots_to_keys;
    /* The following fields are used to take the slave state on elections. */
120
    mstime_t failover_auth_time; /* Time of previous or next election. */
121 122
    int failover_auth_count;    /* Number of votes received so far. */
    int failover_auth_sent;     /* True if we already asked for votes. */
123
    int failover_auth_rank;     /* This slave rank for current auth request. */
124
    uint64_t failover_auth_epoch; /* Epoch of the current election. */
125 126
    int cant_failover_reason;   /* Why a slave is currently not able to
                                   failover. See the CANT_FAILOVER_* macros. */
127 128 129 130 131 132 133 134 135 136
    /* Manual failover state in common. */
    mstime_t mf_end;            /* Manual failover time limit (ms unixtime).
                                   It is zero if there is no MF in progress. */
    /* Manual failover state of master. */
    clusterNode *mf_slave;      /* Slave performing the manual failover. */
    /* Manual failover state of slave. */
    long long mf_master_offset; /* Master offset the slave needs to start MF
                                   or zero if stil not received. */
    int mf_can_start;           /* If non-zero signal that the manual failover
                                   can start requesting masters vote. */
137
    /* The followign fields are used by masters to take state on elections. */
138
    uint64_t lastVoteEpoch;     /* Epoch of the last vote granted. */
139 140
    int todo_before_sleep; /* Things to do in clusterBeforeSleep(). */
    long long stats_bus_messages_sent;  /* Num of msg sent via cluster bus. */
141
    long long stats_bus_messages_received; /* Num of msg rcvd via cluster bus.*/
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
} clusterState;

/* clusterState todo_before_sleep flags. */
#define CLUSTER_TODO_HANDLE_FAILOVER (1<<0)
#define CLUSTER_TODO_UPDATE_STATE (1<<1)
#define CLUSTER_TODO_SAVE_CONFIG (1<<2)
#define CLUSTER_TODO_FSYNC_CONFIG (1<<3)

/* Redis cluster messages header */

/* Note that the PING, PONG and MEET messages are actually the same exact
 * kind of packet. PONG is the reply to ping, in the exact format as a PING,
 * while MEET is a special PING that forces the receiver to add the sender
 * as a node (if it is not already in the list). */
#define CLUSTERMSG_TYPE_PING 0          /* Ping */
#define CLUSTERMSG_TYPE_PONG 1          /* Pong (reply to Ping) */
#define CLUSTERMSG_TYPE_MEET 2          /* Meet "let's join" message */
#define CLUSTERMSG_TYPE_FAIL 3          /* Mark node xxx as failing */
#define CLUSTERMSG_TYPE_PUBLISH 4       /* Pub/Sub Publish propagation */
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 5 /* May I failover? */
162 163
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6     /* Yes, you have my vote */
#define CLUSTERMSG_TYPE_UPDATE 7        /* Another node slots configuration */
164
#define CLUSTERMSG_TYPE_MFSTART 8       /* Pause clients for manual failover */
165 166 167 168 169

/* Initially we don't know our "name", but we'll find it once we connect
 * to the first node, using the getsockname() function. Then we'll use this
 * address for all the next messages. */
typedef struct {
A
antirez 已提交
170
    char nodename[CLUSTER_NAMELEN];
171 172
    uint32_t ping_sent;
    uint32_t pong_received;
A
antirez 已提交
173
    char ip[NET_IP_STR_LEN];  /* IP address last time it was seen */
174 175 176 177
    uint16_t port;              /* port last time it was seen */
    uint16_t flags;             /* node->flags copy */
    uint16_t notused1;          /* Some room for future improvements. */
    uint32_t notused2;
178 179 180
} clusterMsgDataGossip;

typedef struct {
A
antirez 已提交
181
    char nodename[CLUSTER_NAMELEN];
182 183 184 185 186
} clusterMsgDataFail;

typedef struct {
    uint32_t channel_len;
    uint32_t message_len;
187 188 189 190
    /* We can't reclare bulk_data as bulk_data[] since this structure is
     * nested. The 8 bytes are removed from the count during the message
     * length computation. */
    unsigned char bulk_data[8];
191 192
} clusterMsgDataPublish;

193 194
typedef struct {
    uint64_t configEpoch; /* Config epoch of the specified instance. */
A
antirez 已提交
195 196
    char nodename[CLUSTER_NAMELEN]; /* Name of the slots owner. */
    unsigned char slots[CLUSTER_SLOTS/8]; /* Slots bitmap. */
197 198
} clusterMsgDataUpdate;

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
union clusterMsgData {
    /* PING, MEET and PONG */
    struct {
        /* Array of N clusterMsgDataGossip structures */
        clusterMsgDataGossip gossip[1];
    } ping;

    /* FAIL */
    struct {
        clusterMsgDataFail about;
    } fail;

    /* PUBLISH */
    struct {
        clusterMsgDataPublish msg;
    } publish;
215 216 217 218 219

    /* UPDATE */
    struct {
        clusterMsgDataUpdate nodecfg;
    } update;
220 221
};

222
#define CLUSTER_PROTO_VER 0 /* Cluster bus protocol version. */
223

224
typedef struct {
225
    char sig[4];        /* Siganture "RCmb" (Redis Cluster message bus). */
226
    uint32_t totlen;    /* Total length of this message */
227 228
    uint16_t ver;       /* Protocol version, currently set to 0. */
    uint16_t notused0;  /* 2 bytes not used. */
229 230 231
    uint16_t type;      /* Message type */
    uint16_t count;     /* Only used for some kind of messages. */
    uint64_t currentEpoch;  /* The epoch accordingly to the sending node. */
A
antirez 已提交
232 233 234
    uint64_t configEpoch;   /* The config epoch if it's a master, or the last
                               epoch advertised by its master if it is a
                               slave. */
235 236
    uint64_t offset;    /* Master replication offset if node is a master or
                           processed replication offset if node is a slave. */
A
antirez 已提交
237 238 239
    char sender[CLUSTER_NAMELEN]; /* Name of the sender node */
    unsigned char myslots[CLUSTER_SLOTS/8];
    char slaveof[CLUSTER_NAMELEN];
240 241 242 243
    char notused1[32];  /* 32 bytes reserved for future usage. */
    uint16_t port;      /* Sender TCP base port */
    uint16_t flags;     /* Sender node flags */
    unsigned char state; /* Cluster state from the POV of the sender */
244
    unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */
245 246 247 248 249
    union clusterMsgData data;
} clusterMsg;

#define CLUSTERMSG_MIN_LEN (sizeof(clusterMsg)-sizeof(union clusterMsgData))

250 251 252
/* Message flags better specify the packet content or are used to
 * provide some information about the node state. */
#define CLUSTERMSG_FLAG0_PAUSED (1<<0) /* Master paused for manual failover. */
253 254
#define CLUSTERMSG_FLAG0_FORCEACK (1<<1) /* Give ACK to AUTH_REQUEST even if
                                            master is up. */
255

A
antirez 已提交
256
/* ---------------------- API exported outside cluster.c -------------------- */
257 258 259
clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask);
int clusterRedirectBlockedClientIfNeeded(client *c);
void clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_code);
260

A
antirez 已提交
261
#endif /* __CLUSTER_H */