diff --git a/src/sentinel.c b/src/sentinel.c index ae447e1720ad671d74b394f56895c7dddeaead41..7f81443bbf2dffd0448368e037f2a8b9368ed805 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). *