summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2016-01-11 15:39:09 +0100
committerantirez <antirez@gmail.com>2016-01-25 15:21:27 +0100
commit49b1e7882075e2271276adf592d9b69044a6c717 (patch)
tree2be38207b651a4a99642567964088291f7d0e4cc
parent7942e7090e6c913c2de64a3e4040a14ef638051a (diff)
downloadredis-49b1e7882075e2271276adf592d9b69044a6c717.tar.gz
CLUSTER BUMPEPOCH initial implementation fixed.
-rw-r--r--src/cluster.c14
-rwxr-xr-xsrc/redis-trib.rb25
2 files changed, 25 insertions, 14 deletions
diff --git a/src/cluster.c b/src/cluster.c
index 6123a9fdb..7a1e48981 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -4027,13 +4027,6 @@ void clusterCommand(redisClient *c) {
}
clusterDelSlot(slot);
clusterAddSlot(n,slot);
- } else if (!strcasecmp(c->argv[3]->ptr,"bumpepoch") && c->argc == 2) {
- /* CLUSTER BUMPEPOCH */
- int retval = clusterBumpConfigEpochWithoutConsensus();
- sds reply = sdscatprintf(sdsempty(),"%s %llu\r\n",
- (retval == C_OK) ? "BUMPED" : "STILL",
- (unsigned long long) myself->configEpoch);
- addReplySds(c,reply);
} else {
addReplyError(c,
"Invalid CLUSTER SETSLOT action or number of arguments");
@@ -4041,6 +4034,13 @@ void clusterCommand(redisClient *c) {
}
clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|CLUSTER_TODO_UPDATE_STATE);
addReply(c,shared.ok);
+ } else if (!strcasecmp(c->argv[1]->ptr,"bumpepoch") && c->argc == 2) {
+ /* CLUSTER BUMPEPOCH */
+ int retval = clusterBumpConfigEpochWithoutConsensus();
+ sds reply = sdscatprintf(sdsempty(),"+%s %llu\r\n",
+ (retval == C_OK) ? "BUMPED" : "STILL",
+ (unsigned long long) myself->configEpoch);
+ addReplySds(c,reply);
} else if (!strcasecmp(c->argv[1]->ptr,"info") && c->argc == 2) {
/* CLUSTER INFO */
char *statestr[] = {"ok","fail","needhelp"};
diff --git a/src/redis-trib.rb b/src/redis-trib.rb
index bacbd0d33..112916d7a 100755
--- a/src/redis-trib.rb
+++ b/src/redis-trib.rb
@@ -499,13 +499,15 @@ class RedisTrib
end
# Return the owner of the specified slot
- def get_slot_owner(slot)
+ def get_slot_owners(slot)
+ owners = []
@nodes.each{|n|
+ next if n.has_flag?("slave")
n.slots.each{|s,_|
- return n if s == slot
+ owners << n if s == slot
}
}
- nil
+ owners
end
# Return the node, among 'nodes' with the greatest number of keys
@@ -532,7 +534,8 @@ class RedisTrib
# Try to obtain the current slot owner, according to the current
# nodes configuration.
- owner = get_slot_owner(slot)
+ owners = get_slot_owners(slot)
+ owner = owners[0] if owners.length == 1
migrating = []
importing = []
@@ -585,9 +588,17 @@ class RedisTrib
# Note that this case also covers multiple nodes having the slot
# in migrating state, since migrating is a valid state only for
# slot owners.
- #
- # TODO: Use CLUSTER BUMPEPOCH in order to make the
- # winner able to claim the slot over all the other nodes.
+ if owners.length > 1
+ owner = get_node_with_most_keys_in_slot(owners,slot)
+ owners.each{|n|
+ next if n == owner
+ n.r.cluster('delslots',slot)
+ n.r.cluster('setslot',slot,'importing',owner.info[:name])
+ importing.delete(n) # Avoid duplciates
+ importing << n
+ }
+ owner.r.cluster('bumpepoch')
+ end
# Case 1: The slot is in migrating state in one slot, and in
# importing state in 1 slot. That's trivial to address.