summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-06-17 11:03:21 +0200
committerantirez <antirez@gmail.com>2014-06-17 11:03:21 +0200
commit2c175912249ffabb2ffb60bae618701e8476a7b8 (patch)
treefc021edc4e9a02c31dca14ea8dacff4248d1467f
parentbb2011d992cebbfaa94d099c043c55f2342690cb (diff)
downloadredis-2c175912249ffabb2ffb60bae618701e8476a7b8.tar.gz
Sentinel: send SLAVEOF with MULTI, CLIENT KILL, CONFIG REWRITE.
This implements the new Sentinel-Client protocol for the Sentinel part: now instances are reconfigured using a transaction that ensures that the config is rewritten in the target instance, and that clients lose the connection with the instance, in order to be forced to: ask Sentinel, reconnect to the instance, and verify the instance role with the new ROLE command.
-rw-r--r--src/sentinel.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/src/sentinel.c b/src/sentinel.c
index b1d843667..25efdf6f3 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -3203,21 +3203,53 @@ int sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port) {
ll2string(portstr,sizeof(portstr),port);
+ /* If host is NULL we send SLAVEOF NO ONE that will turn the instance
+ * into a master. */
if (host == NULL) {
host = "NO";
memcpy(portstr,"ONE",4);
}
+ /* In order to send SLAVEOF in a safe way, we send a transaction performing
+ * the following tasks:
+ * 1) Reconfigure the instance according to the specified host/port params.
+ * 2) Rewrite the configuraiton.
+ * 3) Disconnect all clients (but this one sending the commnad) in order
+ * to trigger the ask-master-on-reconnection protocol for connected
+ * clients.
+ *
+ * Note that we don't check the replies returned by commands, since we
+ * will observe instead the effects in the next INFO output. */
+ retval = redisAsyncCommand(ri->cc,
+ sentinelDiscardReplyCallback, NULL, "MULTI");
+ if (retval == REDIS_ERR) return retval;
+ ri->pending_commands++;
+
retval = redisAsyncCommand(ri->cc,
sentinelDiscardReplyCallback, NULL, "SLAVEOF %s %s", host, portstr);
if (retval == REDIS_ERR) return retval;
+ ri->pending_commands++;
+ retval = redisAsyncCommand(ri->cc,
+ sentinelDiscardReplyCallback, NULL, "CONFIG REWRITE");
+ if (retval == REDIS_ERR) return retval;
ri->pending_commands++;
- if (redisAsyncCommand(ri->cc,
- sentinelDiscardReplyCallback, NULL, "CONFIG REWRITE") == REDIS_OK)
- {
- ri->pending_commands++;
- }
+
+ /* CLIENT KILL TYPE <type> is only supported starting from Redis 2.8.12,
+ * however sending it to an instance not understanding this command is not
+ * an issue because CLIENT is variadic command, so Redis will not
+ * recognized as a syntax error, and the transaction will not fail (but
+ * only the unsupported command will fail). */
+ retval = redisAsyncCommand(ri->cc,
+ sentinelDiscardReplyCallback, NULL, "CLIENT KILL TYPE normal");
+ if (retval == REDIS_ERR) return retval;
+ ri->pending_commands++;
+
+ retval = redisAsyncCommand(ri->cc,
+ sentinelDiscardReplyCallback, NULL, "EXEC");
+ if (retval == REDIS_ERR) return retval;
+ ri->pending_commands++;
+
return REDIS_OK;
}