Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
7c4b8f29
Commit
7c4b8f29
authored
Sep 26, 2013
by
antirez
Browse files
Cluster: react faster when a slave wins an election.
parent
42fa46e4
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/cluster.c
View file @
7c4b8f29
...
@@ -53,6 +53,7 @@ int clusterDelSlot(int slot);
...
@@ -53,6 +53,7 @@ int clusterDelSlot(int slot);
int clusterDelNodeSlots(clusterNode *node);
int clusterDelNodeSlots(clusterNode *node);
int clusterNodeSetSlotBit(clusterNode *n, int slot);
int clusterNodeSetSlotBit(clusterNode *n, int slot);
void clusterSetMaster(clusterNode *n);
void clusterSetMaster(clusterNode *n);
void clusterHandleSlaveFailover(void);
int bitmapTestBit(unsigned char *bitmap, int pos);
int bitmapTestBit(unsigned char *bitmap, int pos);
/* -----------------------------------------------------------------------------
/* -----------------------------------------------------------------------------
...
@@ -1191,6 +1192,9 @@ int clusterProcessPacket(clusterLink *link) {
...
@@ -1191,6 +1192,9 @@ int clusterProcessPacket(clusterLink *link) {
senderCurrentEpoch == server.cluster->currentEpoch)
senderCurrentEpoch == server.cluster->currentEpoch)
{
{
server.cluster->failover_auth_count++;
server.cluster->failover_auth_count++;
/* Maybe we reached a quorum here, set a flag to make sure
* we check ASAP. */
server.cluster->handle_slave_failover_asap++;
}
}
} else {
} else {
redisLog(REDIS_WARNING,"Received unknown packet type: %d", type);
redisLog(REDIS_WARNING,"Received unknown packet type: %d", type);
...
@@ -1291,7 +1295,11 @@ void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -1291,7 +1295,11 @@ void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
}
}
}
}
/* Put stuff into the send buffer. */
/* Put stuff into the send buffer.
*
* It is guaranteed that this function will never have as a side effect
* the link to be invalidated, so it is safe to call this function
* from event handlers that will do stuff with the same link later. */
void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {
void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {
if (sdslen(link->sndbuf) == 0 && msglen != 0)
if (sdslen(link->sndbuf) == 0 && msglen != 0)
aeCreateFileEvent(server.el,link->fd,AE_WRITABLE,
aeCreateFileEvent(server.el,link->fd,AE_WRITABLE,
...
@@ -1301,7 +1309,11 @@ void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {
...
@@ -1301,7 +1309,11 @@ void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {
}
}
/* Send a message to all the nodes that are part of the cluster having
/* Send a message to all the nodes that are part of the cluster having
* a connected link. */
* a connected link.
*
* It is guaranteed that this function will never have as a side effect
* some node->link to be invalidated, so it is safe to call this function
* from event handlers that will do stuff with node links later. */
void clusterBroadcastMessage(void *buf, size_t len) {
void clusterBroadcastMessage(void *buf, size_t len) {
dictIterator *di;
dictIterator *di;
dictEntry *de;
dictEntry *de;
...
@@ -1416,10 +1428,11 @@ void clusterSendPing(clusterLink *link, int type) {
...
@@ -1416,10 +1428,11 @@ void clusterSendPing(clusterLink *link, int type) {
clusterSendMessage(link,buf,totlen);
clusterSendMessage(link,buf,totlen);
}
}
/* Send a PONG packet to every connected node that's not in handshake state.
/* Send a PONG packet to every connected node that's not in handshake state
* and for which we have a valid link.
*
*
* In Redis Cluster p
i
ngs are not
j
us
t used
for failure detection, but also
* In Redis Cluster p
o
ngs are not us
ed just
for failure detection, but also
* to carry important configuration information
s
. So broadcasting a pong is
* to carry important configuration information. So broadcasting a pong is
* useful when something changes in the configuration and we want to make
* useful when something changes in the configuration and we want to make
* the cluster aware ASAP (for instance after a slave promotion). */
* the cluster aware ASAP (for instance after a slave promotion). */
void clusterBroadcastPong(void) {
void clusterBroadcastPong(void) {
...
@@ -1430,6 +1443,7 @@ void clusterBroadcastPong(void) {
...
@@ -1430,6 +1443,7 @@ void clusterBroadcastPong(void) {
while((de = dictNext(di)) != NULL) {
while((de = dictNext(di)) != NULL) {
clusterNode *node = dictGetVal(de);
clusterNode *node = dictGetVal(de);
if (!node->link) continue;
if (node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE)) continue;
if (node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE)) continue;
clusterSendPing(node->link,CLUSTERMSG_TYPE_PONG);
clusterSendPing(node->link,CLUSTERMSG_TYPE_PONG);
}
}
...
@@ -1591,6 +1605,15 @@ void clusterHandleSlaveFailover(void) {
...
@@ -1591,6 +1605,15 @@ void clusterHandleSlaveFailover(void) {
int needed_quorum = (server.cluster->size / 2) + 1;
int needed_quorum = (server.cluster->size / 2) + 1;
int j;
int j;
/* Pre conditions to run the function:
* 1) We are a slave.
* 2) Our master is flagged as FAIL.
* 3) It is serving slots. */
if (!(server.cluster->myself->flags & REDIS_NODE_SLAVE) ||
server.cluster->myself->slaveof == NULL ||
!(server.cluster->myself->slaveof->flags & REDIS_NODE_FAIL) ||
server.cluster->myself->slaveof->numslots == 0) return;
/* Remove the node timeout from the data age as it is fine that we are
/* Remove the node timeout from the data age as it is fine that we are
* disconnected from our master at least for the time it was down to be
* disconnected from our master at least for the time it was down to be
* flagged as FAIL, that's the baseline. */
* flagged as FAIL, that's the baseline. */
...
@@ -1834,17 +1857,19 @@ void clusterCron(void) {
...
@@ -1834,17 +1857,19 @@ void clusterCron(void) {
server.cluster->myself->slaveof->port);
server.cluster->myself->slaveof->port);
}
}
/* If we are a slave and our master is down, but is serving slots,
clusterHandleSlaveFailover();
* call the function that handles the failover. */
if (update_state) clusterUpdateState();
if
(
server
.
cluster
->
myself
->
flags
&
REDIS_NODE_SLAVE
&&
}
server
.
cluster
->
myself
->
slaveof
&&
server
.
cluster
->
myself
->
slaveof
->
flags
&
REDIS_NODE_FAIL
&&
/* This function is called before the event handler returns to sleep for
server
.
cluster
->
myself
->
slaveof
->
numslots
!=
0
)
* events. It is useful to perform operations that must be done ASAP in
{
* reaction to events fired but that are not safe to perform inside event
* handlers. */
void clusterBeforeSleep(void) {
if (server.cluster->handle_slave_failover_asap) {
clusterHandleSlaveFailover();
clusterHandleSlaveFailover();
server.cluster->handle_slave_failover_asap = 0;
}
}
if
(
update_state
)
clusterUpdateState
();
}
}
/* -----------------------------------------------------------------------------
/* -----------------------------------------------------------------------------
...
...
src/redis.c
View file @
7c4b8f29
...
@@ -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 ======================== */
...
...
src/redis.h
View file @
7c4b8f29
...
@@ -647,12 +647,13 @@ typedef struct {
...
@@ -647,12 +647,13 @@ typedef struct {
clusterNode
*
slots
[
REDIS_CLUSTER_SLOTS
];
clusterNode
*
slots
[
REDIS_CLUSTER_SLOTS
];
zskiplist
*
slots_to_keys
;
zskiplist
*
slots_to_keys
;
/* The following fields are used to take the slave state on elections. */
/* The following fields are used to take the slave state on elections. */
mstime_t
failover_auth_time
;
/* Time at which we'll try to get elected in ms
.
*/
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_count
;
/* Number of votes received so far. */
int
failover_auth_sent
;
/* True if we already asked for votes. */
int
failover_auth_sent
;
/* True if we already asked for votes. */
uint64_t
failover_auth_epoch
;
/* Epoch of the current election. */
uint64_t
failover_auth_epoch
;
/* Epoch of the current election. */
/* The followign fields are uesd by masters to take state on elections. */
/* The followign fields are uesd by masters to take state on elections. */
uint64_t
last_vote_epoch
;
/* Epoch of the last vote granted. */
uint64_t
last_vote_epoch
;
/* Epoch of the last vote granted. */
int
handle_slave_failover_asap
;
/* Call clusterHandleSlaveFailover() ASAP. */
}
clusterState
;
}
clusterState
;
/* Redis cluster messages header */
/* Redis cluster messages header */
...
@@ -1380,6 +1381,7 @@ void clusterCron(void);
...
@@ -1380,6 +1381,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
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment