summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2019-08-05 17:38:15 +0200
committerantirez <antirez@gmail.com>2019-09-25 11:49:28 +0200
commit7ab62d4b925581180f9e80639154536872b8edae (patch)
treef2ed4b822e93c3c347d0f9ac747fe3e01db1a6fa
parent495dd0da54664c5447ed8ee6634903dae5c8bde6 (diff)
downloadredis-7ab62d4b925581180f9e80639154536872b8edae.tar.gz
Replication: clarify why repl_put_online_on_ack exists at all.
-rw-r--r--src/replication.c42
-rw-r--r--src/server.h2
2 files changed, 34 insertions, 10 deletions
diff --git a/src/replication.c b/src/replication.c
index 95ee30cc5..f8951ad14 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -823,7 +823,9 @@ void replconfCommand(client *c) {
c->repl_ack_time = server.unixtime;
/* If this was a diskless replication, we need to really put
* the slave online when the first ACK is received (which
- * confirms slave is online and ready to get more data). */
+ * confirms slave is online and ready to get more data). This
+ * allows for simpler and less CPU intensive EOF detection
+ * when streaming RDB files. */
if (c->repl_put_online_on_ack && c->replstate == SLAVE_STATE_ONLINE)
putSlaveOnline(c);
/* Note: this command does not reply anything! */
@@ -842,18 +844,20 @@ void replconfCommand(client *c) {
addReply(c,shared.ok);
}
-/* This function puts a slave in the online state, and should be called just
- * after a slave received the RDB file for the initial synchronization, and
+/* This function puts a replica in the online state, and should be called just
+ * after a replica received the RDB file for the initial synchronization, and
* we are finally ready to send the incremental stream of commands.
*
* It does a few things:
*
- * 1) Put the slave in ONLINE state (useless when the function is called
- * because state is already ONLINE but repl_put_online_on_ack is true).
+ * 1) Put the slave in ONLINE state. Note that the function may also be called
+ * for a replicas that are already in ONLINE state, but having the flag
+ * repl_put_online_on_ack set to true: we still have to install the write
+ * handler in that case. This function will take care of that.
* 2) Make sure the writable event is re-installed, since calling the SYNC
* command disables it, so that we can accumulate output buffer without
- * sending it to the slave.
- * 3) Update the count of good slaves. */
+ * sending it to the replica.
+ * 3) Update the count of "good replicas". */
void putSlaveOnline(client *slave) {
slave->replstate = SLAVE_STATE_ONLINE;
slave->repl_put_online_on_ack = 0;
@@ -965,11 +969,31 @@ void updateSlavesWaitingBgsave(int bgsaveerr, int type) {
serverLog(LL_NOTICE,
"Streamed RDB transfer with replica %s succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming",
replicationGetSlaveName(slave));
- /* Note: we wait for a REPLCONF ACK message from slave in
+ /* Note: we wait for a REPLCONF ACK message from the replica in
* order to really put it online (install the write handler
* so that the accumulated data can be transferred). However
* we change the replication state ASAP, since our slave
- * is technically online now. */
+ * is technically online now.
+ *
+ * So things work like that:
+ *
+ * 1. We end trasnferring the RDB file via socket.
+ * 2. The replica is put ONLINE but the write handler
+ * is not installed.
+ * 3. The replica however goes really online, and pings us
+ * back via REPLCONF ACK commands.
+ * 4. Now we finally install the write handler, and send
+ * the buffers accumulated so far to the replica.
+ *
+ * But why we do that? Because the replica, when we stream
+ * the RDB directly via the socket, must detect the RDB
+ * EOF (end of file), that is a special random string at the
+ * end of the RDB (for streamed RDBs we don't know the length
+ * in advance). Detecting such final EOF string is much
+ * simpler and less CPU intensive if no more data is sent
+ * after such final EOF. So we don't want to glue the end of
+ * the RDB trasfer with the start of the other replication
+ * data. */
slave->replstate = SLAVE_STATE_ONLINE;
slave->repl_put_online_on_ack = 1;
slave->repl_ack_time = server.unixtime; /* Timeout otherwise. */
diff --git a/src/server.h b/src/server.h
index d315b2d6d..aa0ec37e9 100644
--- a/src/server.h
+++ b/src/server.h
@@ -748,7 +748,7 @@ typedef struct client {
int flags; /* Client flags: CLIENT_* macros. */
int authenticated; /* When requirepass is non-NULL. */
int replstate; /* Replication state if this is a slave. */
- int repl_put_online_on_ack; /* Install slave write handler on ACK. */
+ int repl_put_online_on_ack; /* Install slave write handler on first ACK. */
int repldbfd; /* Replication DB file descriptor. */
off_t repldboff; /* Replication DB file offset. */
off_t repldbsize; /* Replication DB file size. */