Add REPLPING command for use during replication (#329)

* added replping command for initiating replication

* backwards compatibility for replping (retry if not recognized)

* don't allow ping during loading (load balancer fix)

* changed replping warning to notice

Former-commit-id: d7f6bc16145206e96ffeb9941398d564c3dba6a9
This commit is contained in:
Christian Legge 2021-07-29 15:50:30 -04:00 committed by GitHub
parent 31e2a22b6f
commit 9e562f1fe5
3 changed files with 18 additions and 5 deletions

View File

@ -2759,18 +2759,19 @@ void syncWithMaster(connection *conn) {
goto error; goto error;
} }
retry_connect:
/* Send a PING to check the master is able to reply without errors. */ /* Send a PING to check the master is able to reply without errors. */
if (mi->repl_state == REPL_STATE_CONNECTING) { if (mi->repl_state == REPL_STATE_CONNECTING || mi->repl_state == REPL_STATE_RETRY_NOREPLPING) {
serverLog(LL_NOTICE,"Non blocking connect for SYNC fired the event."); serverLog(LL_NOTICE,"Non blocking connect for SYNC fired the event.");
/* Delete the writable event so that the readable event remains /* Delete the writable event so that the readable event remains
* registered and we can wait for the PONG reply. */ * registered and we can wait for the PONG reply. */
connSetReadHandler(conn, syncWithMaster); connSetReadHandler(conn, syncWithMaster);
connSetWriteHandler(conn, NULL); connSetWriteHandler(conn, NULL);
mi->repl_state = REPL_STATE_RECEIVE_PING_REPLY;
/* Send the PING, don't check for errors at all, we have the timeout /* Send the PING, don't check for errors at all, we have the timeout
* that will take care about this. */ * that will take care about this. */
err = sendCommand(conn,"PING",NULL); err = sendCommand(conn,mi->repl_state == REPL_STATE_RETRY_NOREPLPING ? "PING" : "REPLPING",NULL);
if (err) goto write_error; if (err) goto write_error;
mi->repl_state = REPL_STATE_RECEIVE_PING_REPLY;
return; return;
} }
@ -2783,7 +2784,13 @@ void syncWithMaster(connection *conn) {
* Note that older versions of Redis replied with "operation not * Note that older versions of Redis replied with "operation not
* permitted" instead of using a proper error code, so we test * permitted" instead of using a proper error code, so we test
* both. */ * both. */
if (err[0] != '+' && if (strncmp(err,"-ERR unknown command",20) == 0) {
serverLog(LL_NOTICE,"Master does not support REPLPING, sending PING instead...");
mi->repl_state = REPL_STATE_RETRY_NOREPLPING;
sdsfree(err);
err = NULL;
goto retry_connect;
} else if (err[0] != '+' &&
strncmp(err,"-NOAUTH",7) != 0 && strncmp(err,"-NOAUTH",7) != 0 &&
strncmp(err,"-NOPERM",7) != 0 && strncmp(err,"-NOPERM",7) != 0 &&
strncmp(err,"-ERR operation not permitted",28) != 0) strncmp(err,"-ERR operation not permitted",28) != 0)

View File

@ -753,6 +753,10 @@ struct redisCommand redisCommandTable[] = {
"ok-stale ok-loading fast @connection @replication", "ok-stale ok-loading fast @connection @replication",
0,NULL,0,0,0,0,0,0}, 0,NULL,0,0,0,0,0,0},
{"replping",pingCommand,-1,
"ok-stale fast @connection @replication",
0,NULL,0,0,0,0,0,0},
{"echo",echoCommand,2, {"echo",echoCommand,2,
"fast @connection", "fast @connection",
0,NULL,0,0,0,0,0,0}, 0,NULL,0,0,0,0,0,0},
@ -2768,6 +2772,7 @@ void createSharedObjects(void) {
shared.lastid = makeObjectShared("LASTID",6); shared.lastid = makeObjectShared("LASTID",6);
shared.default_username = makeObjectShared("default",7); shared.default_username = makeObjectShared("default",7);
shared.ping = makeObjectShared("ping",4); shared.ping = makeObjectShared("ping",4);
shared.replping = makeObjectShared("replping", 8);
shared.setid = makeObjectShared("SETID",5); shared.setid = makeObjectShared("SETID",5);
shared.keepttl = makeObjectShared("KEEPTTL",7); shared.keepttl = makeObjectShared("KEEPTTL",7);
shared.load = makeObjectShared("LOAD",4); shared.load = makeObjectShared("LOAD",4);

View File

@ -505,6 +505,7 @@ typedef enum {
REPL_STATE_NONE = 0, /* No active replication */ REPL_STATE_NONE = 0, /* No active replication */
REPL_STATE_CONNECT, /* Must connect to master */ REPL_STATE_CONNECT, /* Must connect to master */
REPL_STATE_CONNECTING, /* Connecting to master */ REPL_STATE_CONNECTING, /* Connecting to master */
REPL_STATE_RETRY_NOREPLPING, /* Master does not support REPLPING, retry with PING */
/* --- Handshake states, must be ordered --- */ /* --- Handshake states, must be ordered --- */
REPL_STATE_RECEIVE_PING_REPLY, /* Wait for PING reply */ REPL_STATE_RECEIVE_PING_REPLY, /* Wait for PING reply */
REPL_STATE_SEND_HANDSHAKE, /* Send handshake sequance to master */ REPL_STATE_SEND_HANDSHAKE, /* Send handshake sequance to master */
@ -1283,7 +1284,7 @@ struct sharedObjectsStruct {
*emptyscan, *multi, *exec, *left, *right, *hset, *srem, *xgroup, *xclaim, *emptyscan, *multi, *exec, *left, *right, *hset, *srem, *xgroup, *xclaim,
*script, *replconf, *eval, *persist, *set, *pexpireat, *pexpire, *script, *replconf, *eval, *persist, *set, *pexpireat, *pexpire,
*time, *pxat, *px, *retrycount, *force, *justid, *time, *pxat, *px, *retrycount, *force, *justid,
*lastid, *ping, *setid, *keepttl, *load, *createconsumer, *lastid, *ping, *replping, *setid, *keepttl, *load, *createconsumer,
*getack, *special_asterick, *special_equals, *default_username, *getack, *special_asterick, *special_equals, *default_username,
*hdel, *zrem, *mvccrestore, *pexpirememberat, *hdel, *zrem, *mvccrestore, *pexpirememberat,
*select[PROTO_SHARED_SELECT_CMDS], *select[PROTO_SHARED_SELECT_CMDS],