summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-06-19 15:17:06 +0200
committerantirez <antirez@gmail.com>2014-06-19 15:17:06 +0200
commit41f12ac988e0e65e045bda9e90bc44a42ff58611 (patch)
tree4751d619be9a28af834b81b08118676c7b4c1956
parentf16ad11c712dae011463b563cab6b512f5c8169c (diff)
downloadredis-41f12ac988e0e65e045bda9e90bc44a42ff58611.tar.gz
Sentinel: send hello messages ASAP after config change.
Eventual configuration convergence is guaranteed by our periodic hello messages to all the instances, however when there are important notices to share, better make a phone call. With this commit we force an hello message to other Sentinal and Redis instances within the next 100 milliseconds of a config update, which is practically better than waiting a few seconds.
-rw-r--r--src/sentinel.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/src/sentinel.c b/src/sentinel.c
index ae447e172..7f81443bb 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -336,6 +336,7 @@ char *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char
void sentinelFlushConfig(void);
void sentinelGenerateInitialMonitorEvents(void);
int sentinelSendPing(sentinelRedisInstance *ri);
+int sentinelForceHelloUpdateForMaster(sentinelRedisInstance *master);
/* ========================= Dictionary types =============================== */
@@ -1921,6 +1922,7 @@ void sentinelRefreshInstanceInfo(sentinelRedisInstance *ri, const char *info) {
ri->master,"%@");
sentinelCallClientReconfScript(ri->master,SENTINEL_LEADER,
"start",ri->master->addr,ri->addr);
+ sentinelForceHelloUpdateForMaster(ri->master);
} else {
/* A slave turned into a master. We want to force our view and
* reconfigure as slave. Wait some time after the change before
@@ -2059,7 +2061,7 @@ void sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privd
r = reply;
/* Only update pub_time if we actually published our message. Otherwise
- * we'll retry against in 100 milliseconds. */
+ * we'll retry again in 100 milliseconds. */
if (r->type != REDIS_REPLY_ERROR)
ri->last_pub_time = mstime();
}
@@ -2225,6 +2227,38 @@ int sentinelSendHello(sentinelRedisInstance *ri) {
return REDIS_OK;
}
+/* Reset last_pub_time in all the instances in the specified dictionary
+ * in order to force the delivery of an Hello update ASAP. */
+void sentinelForceHelloUpdateDictOfRedisInstances(dict *instances) {
+ dictIterator *di;
+ dictEntry *de;
+
+ di = dictGetSafeIterator(instances);
+ while((de = dictNext(di)) != NULL) {
+ sentinelRedisInstance *ri = dictGetVal(de);
+ if (ri->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))
+ ri->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);
+ }
+ dictReleaseIterator(di);
+}
+
+/* This function forces the delivery of an "Hello" message (see
+ * sentinelSendHello() top comment for further information) to all the Redis
+ * and Sentinel instances related to the specified 'master'.
+ *
+ * It is technically not needed since we send an update to every instance
+ * with a period of SENTINEL_PUBLISH_PERIOD milliseconds, however when a
+ * Sentinel upgrades a configuration it is a good idea to deliever an update
+ * to the other Sentinels ASAP. */
+int sentinelForceHelloUpdateForMaster(sentinelRedisInstance *master) {
+ if (!(master->flags & SRI_MASTER)) return REDIS_ERR;
+ if (master->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))
+ master->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);
+ sentinelForceHelloUpdateDictOfRedisInstances(master->sentinels);
+ sentinelForceHelloUpdateDictOfRedisInstances(master->slaves);
+ return REDIS_OK;
+}
+
/* Send a PING to the specified instance and refresh the last_ping_time
* if it is zero (that is, if we received a pong for the previous ping).
*