mirror of
https://github.com/fluencelabs/redis
synced 2025-03-18 16:40:50 +00:00
Cluster: masters don't vote for a slave with stale config.
When a slave requests our vote, the configEpoch he claims for its master and the set of served slots must be greater or equal to the configEpoch of the nodes serving these slots in the current configuraiton of the master granting its vote. In other terms, masters don't vote for slaves having a stale configuration for the slots they want to serve.
This commit is contained in:
parent
f7d6ad4366
commit
ae2763f564
@ -1567,7 +1567,10 @@ void clusterSendFailoverAuth(clusterNode *node) {
|
||||
/* Vote for the node asking for our vote if there are the conditions. */
|
||||
void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) {
|
||||
clusterNode *master = node->slaveof;
|
||||
uint64_t requestEpoch = ntohu64(request->currentEpoch);
|
||||
uint64_t requestCurrentEpoch = ntohu64(request->currentEpoch);
|
||||
uint64_t requestConfigEpoch = ntohu64(request->configEpoch);
|
||||
unsigned char *claimed_slots = request->myslots;
|
||||
int j;
|
||||
|
||||
/* IF we are not a master serving at least 1 slot, we don't have the
|
||||
* right to vote, as the cluster size in Redis Cluster is the number
|
||||
@ -1576,7 +1579,7 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) {
|
||||
if (server.cluster->myself->numslots == 0) return;
|
||||
|
||||
/* Request epoch must be >= our currentEpoch. */
|
||||
if (requestEpoch < server.cluster->currentEpoch) return;
|
||||
if (requestCurrentEpoch < server.cluster->currentEpoch) return;
|
||||
|
||||
/* I already voted for this epoch? Return ASAP. */
|
||||
if (server.cluster->last_vote_epoch == server.cluster->currentEpoch) return;
|
||||
@ -1592,6 +1595,19 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) {
|
||||
if (server.unixtime - node->slaveof->voted_time <
|
||||
server.cluster_node_timeout * 2) return;
|
||||
|
||||
/* The slave requesting the vote must have a configEpoch for the claimed slots
|
||||
* that is >= the one of the masters currently serving the same slots in the
|
||||
* current configuration. */
|
||||
for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
|
||||
if (bitmapTestBit(claimed_slots, j) == 0) continue;
|
||||
if (server.cluster->slots[j] == NULL ||
|
||||
server.cluster->slots[j]->configEpoch <= requestConfigEpoch) continue;
|
||||
/* If we reached this point we found a slot that in our current slots
|
||||
* is served by a master with a greater configEpoch than the one claimed
|
||||
* by the slave requesting our vote. Refuse to vote for this slave. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can vote for this slave. */
|
||||
clusterSendFailoverAuth(node);
|
||||
server.cluster->last_vote_epoch = server.cluster->currentEpoch;
|
||||
@ -1910,7 +1926,7 @@ void clusterDoBeforeSleep(int flags) {
|
||||
* Slots management
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Test bit 'pos' in a generic bitmap. Return 1 if the bit is zet,
|
||||
/* Test bit 'pos' in a generic bitmap. Return 1 if the bit is set,
|
||||
* otherwise 0. */
|
||||
int bitmapTestBit(unsigned char *bitmap, int pos) {
|
||||
off_t byte = pos/8;
|
||||
|
Loading…
x
Reference in New Issue
Block a user