Commit 6fa9b1a4 authored by antirez's avatar antirez
Browse files

Merge branch 'bettercluster' into unstable

parents 0150c70b ae2763f5
This diff is collapsed.
...@@ -61,4 +61,14 @@ uint64_t intrev64(uint64_t v); ...@@ -61,4 +61,14 @@ uint64_t intrev64(uint64_t v);
#define intrev64ifbe(v) intrev64(v) #define intrev64ifbe(v) intrev64(v)
#endif #endif
/* The functions htonu64() and ntohu64() convert the specified value to
* network byte ordering and back. In big endian systems they are no-ops. */
#if (BYTE_ORDER == BIG_ENDIAN)
#define htonu64(v) (v)
#define ntohu64(v) (v)
#else
#define htonu64(v) intrev64(v)
#define ntohu64(v) intrev64(v)
#endif
#endif #endif
...@@ -118,8 +118,8 @@ class ClusterNode ...@@ -118,8 +118,8 @@ class ClusterNode
nodes.each{|n| nodes.each{|n|
# name addr flags role ping_sent ping_recv link_status slots # name addr flags role ping_sent ping_recv link_status slots
split = n.split split = n.split
name,addr,flags,role,ping_sent,ping_recv,link_status = split[0..6] name,addr,flags,role,ping_sent,ping_recv,config_epoch,link_status = split[0..6]
slots = split[7..-1] slots = split[8..-1]
info = { info = {
:name => name, :name => name,
:addr => addr, :addr => addr,
...@@ -230,7 +230,7 @@ class ClusterNode ...@@ -230,7 +230,7 @@ class ClusterNode
config = [] config = []
@r.cluster("nodes").each_line{|l| @r.cluster("nodes").each_line{|l|
s = l.split s = l.split
slots = s[7..-1].select {|x| x[0..0] != "["} slots = s[8..-1].select {|x| x[0..0] != "["}
next if slots.length == 0 next if slots.length == 0
config << s[0]+":"+(slots.sort.join(",")) config << s[0]+":"+(slots.sort.join(","))
} }
......
...@@ -1203,6 +1203,9 @@ void beforeSleep(struct aeEventLoop *eventLoop) { ...@@ -1203,6 +1203,9 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
/* Write the AOF buffer on disk */ /* Write the AOF buffer on disk */
flushAppendOnlyFile(0); flushAppendOnlyFile(0);
/* Call the Redis Cluster before sleep function. */
if (server.cluster_enabled) clusterBeforeSleep();
} }
/* =========================== Server initialization ======================== */ /* =========================== Server initialization ======================== */
......
...@@ -368,6 +368,8 @@ ...@@ -368,6 +368,8 @@
* Data types * Data types
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
typedef long long mstime_t; /* millisecond time type. */
/* A redis object, that is a type able to hold a string / list / set */ /* A redis object, that is a type able to hold a string / list / set */
/* The actual Redis Object */ /* The actual Redis Object */
...@@ -581,7 +583,7 @@ typedef struct redisOpArray { ...@@ -581,7 +583,7 @@ typedef struct redisOpArray {
#define REDIS_CLUSTER_FAIL_UNDO_TIME_MULT 2 /* Undo fail if master is back. */ #define REDIS_CLUSTER_FAIL_UNDO_TIME_MULT 2 /* Undo fail if master is back. */
#define REDIS_CLUSTER_FAIL_UNDO_TIME_ADD 10 /* Some additional time. */ #define REDIS_CLUSTER_FAIL_UNDO_TIME_ADD 10 /* Some additional time. */
#define REDIS_CLUSTER_SLAVE_VALIDITY_MULT 10 /* Slave data validity. */ #define REDIS_CLUSTER_SLAVE_VALIDITY_MULT 10 /* Slave data validity. */
#define REDIS_CLUSTER_FAILOVER_AUTH_RETRY_MULT 1 /* Auth request retry time. */ #define REDIS_CLUSTER_FAILOVER_AUTH_RETRY_MULT 4 /* Auth request retry time. */
#define REDIS_CLUSTER_FAILOVER_DELAY 5 /* Seconds */ #define REDIS_CLUSTER_FAILOVER_DELAY 5 /* Seconds */
struct clusterNode; struct clusterNode;
...@@ -617,6 +619,7 @@ struct clusterNode { ...@@ -617,6 +619,7 @@ struct clusterNode {
time_t ctime; /* Node object creation time. */ time_t ctime; /* Node object creation time. */
char name[REDIS_CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */ char name[REDIS_CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */
int flags; /* REDIS_NODE_... */ int flags; /* REDIS_NODE_... */
uint64_t configEpoch; /* Last configEpoch observed for this node */
unsigned char slots[REDIS_CLUSTER_SLOTS/8]; /* slots handled by this node */ unsigned char slots[REDIS_CLUSTER_SLOTS/8]; /* slots handled by this node */
int numslots; /* Number of slots handled by this node */ int numslots; /* Number of slots handled by this node */
int numslaves; /* Number of slave nodes, if this is a master */ int numslaves; /* Number of slave nodes, if this is a master */
...@@ -625,6 +628,7 @@ struct clusterNode { ...@@ -625,6 +628,7 @@ struct clusterNode {
time_t ping_sent; /* Unix time we sent latest ping */ time_t ping_sent; /* Unix time we sent latest ping */
time_t pong_received; /* Unix time we received the pong */ time_t pong_received; /* Unix time we received the pong */
time_t fail_time; /* Unix time when FAIL flag was set */ time_t fail_time; /* Unix time when FAIL flag was set */
time_t voted_time; /* Last time we voted for a slave of this master */
char ip[REDIS_IP_STR_LEN]; /* Latest known IP address of this node */ char ip[REDIS_IP_STR_LEN]; /* Latest known IP address of this node */
int port; /* Latest known port of this node */ int port; /* Latest known port of this node */
clusterLink *link; /* TCP/IP link with this node */ clusterLink *link; /* TCP/IP link with this node */
...@@ -634,6 +638,7 @@ typedef struct clusterNode clusterNode; ...@@ -634,6 +638,7 @@ typedef struct clusterNode clusterNode;
typedef struct { typedef struct {
clusterNode *myself; /* This node */ clusterNode *myself; /* This node */
uint64_t currentEpoch;
int state; /* REDIS_CLUSTER_OK, REDIS_CLUSTER_FAIL, ... */ int state; /* REDIS_CLUSTER_OK, REDIS_CLUSTER_FAIL, ... */
int size; /* Num of master nodes with at least one slot */ int size; /* Num of master nodes with at least one slot */
dict *nodes; /* Hash table of name -> clusterNode structures */ dict *nodes; /* Hash table of name -> clusterNode structures */
...@@ -641,10 +646,24 @@ typedef struct { ...@@ -641,10 +646,24 @@ typedef struct {
clusterNode *importing_slots_from[REDIS_CLUSTER_SLOTS]; clusterNode *importing_slots_from[REDIS_CLUSTER_SLOTS];
clusterNode *slots[REDIS_CLUSTER_SLOTS]; clusterNode *slots[REDIS_CLUSTER_SLOTS];
zskiplist *slots_to_keys; zskiplist *slots_to_keys;
int failover_auth_time; /* Time at which we sent the AUTH request. */ /* The following fields are used to take the slave state on elections. */
int failover_auth_count; /* Number of authorizations received. */ mstime_t failover_auth_time;/* Time at which we'll try to get elected in ms*/
int failover_auth_count; /* Number of votes received so far. */
int failover_auth_sent; /* True if we already asked for votes. */
uint64_t failover_auth_epoch; /* Epoch of the current election. */
/* The followign fields are uesd by masters to take state on elections. */
uint64_t last_vote_epoch; /* Epoch of the last vote granted. */
int todo_before_sleep; /* Things to do in clusterBeforeSleep(). */
long long stats_bus_messages_sent; /* Num of msg sent via cluster bus. */
long long stats_bus_messages_received; /* Num of msg received via cluster bus. */
} clusterState; } 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 */ /* Redis cluster messages header */
/* Note that the PING, PONG and MEET messages are actually the same exact /* Note that the PING, PONG and MEET messages are actually the same exact
...@@ -704,9 +723,9 @@ typedef struct { ...@@ -704,9 +723,9 @@ typedef struct {
uint32_t totlen; /* Total length of this message */ uint32_t totlen; /* Total length of this message */
uint16_t type; /* Message type */ uint16_t type; /* Message type */
uint16_t count; /* Only used for some kind of messages. */ uint16_t count; /* Only used for some kind of messages. */
uint64_t time; /* Time at which this request was sent (in milliseconds), uint64_t currentEpoch; /* The epoch accordingly to the sending node. */
this field is copied in reply messages so that the uint64_t configEpoch; /* The config epoch if it's a master, or the last epoch
original sender knows how old the reply is. */ advertised by its master if it is a slave. */
char sender[REDIS_CLUSTER_NAMELEN]; /* Name of the sender node */ char sender[REDIS_CLUSTER_NAMELEN]; /* Name of the sender node */
unsigned char myslots[REDIS_CLUSTER_SLOTS/8]; unsigned char myslots[REDIS_CLUSTER_SLOTS/8];
char slaveof[REDIS_CLUSTER_NAMELEN]; char slaveof[REDIS_CLUSTER_NAMELEN];
...@@ -1367,6 +1386,7 @@ void clusterCron(void); ...@@ -1367,6 +1386,7 @@ void clusterCron(void);
clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask); clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask);
void clusterPropagatePublish(robj *channel, robj *message); void clusterPropagatePublish(robj *channel, robj *message);
void migrateCloseTimedoutSockets(void); void migrateCloseTimedoutSockets(void);
void clusterBeforeSleep(void);
/* Sentinel */ /* Sentinel */
void initSentinelConfig(void); void initSentinelConfig(void);
......
...@@ -343,7 +343,7 @@ int masterTryPartialResynchronization(redisClient *c) { ...@@ -343,7 +343,7 @@ int masterTryPartialResynchronization(redisClient *c) {
/* Run id "?" is used by slaves that want to force a full resync. */ /* Run id "?" is used by slaves that want to force a full resync. */
if (master_runid[0] != '?') { if (master_runid[0] != '?') {
redisLog(REDIS_NOTICE,"Partial resynchronization not accepted: " redisLog(REDIS_NOTICE,"Partial resynchronization not accepted: "
"Runid mismatch (Client asked for '%s', I'm '%s')", "Runid mismatch (Client asked for runid '%s', my runid is '%s')",
master_runid, server.runid); master_runid, server.runid);
} else { } else {
redisLog(REDIS_NOTICE,"Full resync requested by slave."); redisLog(REDIS_NOTICE,"Full resync requested by slave.");
......
...@@ -43,8 +43,6 @@ extern char **environ; ...@@ -43,8 +43,6 @@ extern char **environ;
/* ======================== Sentinel global state =========================== */ /* ======================== Sentinel global state =========================== */
typedef long long mstime_t; /* millisecond time type. */
/* Address object, used to describe an ip:port pair. */ /* Address object, used to describe an ip:port pair. */
typedef struct sentinelAddr { typedef struct sentinelAddr {
char *ip; char *ip;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment