diff --git a/src/redis.h b/src/redis.h index eafa93a0..8cb682fb 100644 --- a/src/redis.h +++ b/src/redis.h @@ -197,7 +197,7 @@ #define REDIS_CLIENT_LIMIT_CLASS_PUBSUB 2 #define REDIS_CLIENT_LIMIT_NUM_CLASSES 3 -/* Slave replication state - slave side */ +/* Slave replication state - from the point of view of the slave. */ #define REDIS_REPL_NONE 0 /* No active replication */ #define REDIS_REPL_CONNECT 1 /* Must connect to master */ #define REDIS_REPL_CONNECTING 2 /* Connecting to master */ @@ -205,17 +205,17 @@ #define REDIS_REPL_TRANSFER 4 /* Receiving .rdb from master */ #define REDIS_REPL_CONNECTED 5 /* Connected to master */ -/* Synchronous read timeout - slave side */ -#define REDIS_REPL_SYNCIO_TIMEOUT 5 - -/* Slave replication state - from the point of view of master - * Note that in SEND_BULK and ONLINE state the slave receives new updates +/* Slave replication state - from the point of view of the master. + * In SEND_BULK and ONLINE state the slave receives new updates * in its output queue. In the WAIT_BGSAVE state instead the server is waiting * to start the next background saving in order to send updates to it. */ -#define REDIS_REPL_WAIT_BGSAVE_START 3 /* master waits bgsave to start feeding it */ -#define REDIS_REPL_WAIT_BGSAVE_END 4 /* master waits bgsave to start bulk DB transmission */ -#define REDIS_REPL_SEND_BULK 5 /* master is sending the bulk DB */ -#define REDIS_REPL_ONLINE 6 /* bulk DB already transmitted, receive updates */ +#define REDIS_REPL_WAIT_BGSAVE_START 6 /* We need to produce a new RDB file. */ +#define REDIS_REPL_WAIT_BGSAVE_END 7 /* Waiting RDB file creation to finish. */ +#define REDIS_REPL_SEND_BULK 8 /* Sending RDB file to slave. */ +#define REDIS_REPL_ONLINE 9 /* RDB file transmitted, sending just updates. */ + +/* Synchronous read timeout - slave side */ +#define REDIS_REPL_SYNCIO_TIMEOUT 5 /* List related stuff */ #define REDIS_HEAD 0 diff --git a/src/replication.c b/src/replication.c index 71b2921f..ea9c0104 100644 --- a/src/replication.c +++ b/src/replication.c @@ -803,23 +803,23 @@ void replicationCron(void) { if (!(server.cronloops % (server.repl_ping_slave_period * server.hz))) { listIter li; listNode *ln; + robj *ping_argv[1]; + /* First, send PING */ + ping_argv[0] = createStringObject("PING",4); + replicationFeedSlaves(server.slaves, server.slaveseldb, ping_argv, 1); + decrRefCount(ping_argv[0]); + + /* Second, send a newline to all the slaves in pre-synchronization stage, + * that is, slaves waiting for the master to create the RDB file. + * The newline will be ignored by the slave but will refresh the + * last-io timer preventing a timeout. */ listRewind(server.slaves,&li); while((ln = listNext(&li))) { redisClient *slave = ln->value; - /* Don't ping slaves that are in the middle of a bulk transfer - * with the master for first synchronization. */ - if (slave->replstate == REDIS_REPL_SEND_BULK) continue; - if (slave->replstate == REDIS_REPL_ONLINE) { - /* If the slave is online send a normal ping */ - addReplySds(slave,sdsnew("*1\r\n$4\r\nPING\r\n")); - } else { - /* Otherwise we are in the pre-synchronization stage. - * Just a newline will do the work of refreshing the - * connection last interaction time, and at the same time - * we'll be sure that being a single char there are no - * short-write problems. */ + if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START || + slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) { if (write(slave->fd, "\n", 1) == -1) { /* Don't worry, it's just a ping. */ }