Disable RDB compression when diskless replication is used (#14575)
Some checks failed
CI / test-ubuntu-latest (push) Has been cancelled
CI / test-sanitizer-address (push) Has been cancelled
CI / build-debian-old (push) Has been cancelled
CI / build-macos-latest (push) Has been cancelled
CI / build-32bit (push) Has been cancelled
CI / build-libc-malloc (push) Has been cancelled
CI / build-centos-jemalloc (push) Has been cancelled
CI / build-old-chain-jemalloc (push) Has been cancelled
Codecov / code-coverage (push) Has been cancelled
External Server Tests / test-external-standalone (push) Has been cancelled
External Server Tests / test-external-cluster (push) Has been cancelled
External Server Tests / test-external-nodebug (push) Has been cancelled
Spellcheck / Spellcheck (push) Has been cancelled

Fixes #14538

If the master uses diskless synchronization and the replica uses
diskless load, we can disable RDB compression to reduce full sync time.
I tested on AWS and found we could reduce time by 20-40%.

In terms of implementation, when the replica can use diskless load, the
replica will send `replconf rdb-no-compress 1` to master to deliver a
RDB without compression.

If your network is slow, please disable repl-diskless-load, and maybe
even repl-diskless-sync

---------

Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
This commit is contained in:
Yuan Wang 2025-12-04 09:24:23 +08:00 committed by GitHub
parent 08b63b6ceb
commit cb71dec0c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 1 deletions

View file

@ -4010,6 +4010,10 @@ int rdbSaveToSlavesSockets(int req, rdbSaveInfo *rsi) {
redisSetProcTitle("redis-rdb-to-slaves");
redisSetCpuAffinity(server.bgsave_cpulist);
/* Disable RDB compression if requested. */
if (req & SLAVE_REQ_RDB_NO_COMPRESS)
server.rdb_compression = 0;
if (req & SLAVE_REQ_SLOTS_SNAPSHOT) {
/* Slots snapshot is required */
retval = slotSnapshotSaveRio(req, &rdb, NULL);

View file

@ -1461,6 +1461,18 @@ void replconfCommand(client *c) {
return;
}
c->main_ch_client_id = (uint64_t)client_id;
/* Inherit the rdb-no-compress request from the main channel. */
if (main_ch->slave_req & SLAVE_REQ_RDB_NO_COMPRESS)
c->slave_req |= SLAVE_REQ_RDB_NO_COMPRESS;
} else if (!strcasecmp(c->argv[j]->ptr, "rdb-no-compress")) {
long rdb_no_compress = 0;
if (getRangeLongFromObjectOrReply(c, c->argv[j + 1], 0, 1, &rdb_no_compress, NULL) != C_OK)
return;
if (rdb_no_compress == 1) {
c->slave_req |= SLAVE_REQ_RDB_NO_COMPRESS;
} else {
c->slave_req &= ~SLAVE_REQ_RDB_NO_COMPRESS;
}
} else {
addReplyErrorFormat(c,"Unrecognized REPLCONF option: %s",
(char*)c->argv[j]->ptr);
@ -2908,6 +2920,7 @@ void syncWithMaster(connection *conn) {
char tmpfile[256], *err = NULL;
int dfd = -1, maxtries = 5;
int psync_result;
static int replconf_rdb_no_compress = 0;
/* If this event fired after the user turned the instance into a master
* with SLAVEOF NO ONE we must just return ASAP. */
@ -3006,6 +3019,15 @@ void syncWithMaster(connection *conn) {
if (err) goto write_error;
}
/* If we are not going to save the RDB to disk, request that RDB
* compression be disabled, which speeds up RDB delivery. */
replconf_rdb_no_compress = 0;
if (useDisklessLoad()) {
replconf_rdb_no_compress = 1;
err = sendCommand(conn, "REPLCONF", "rdb-no-compress", "1", NULL);
if (err) goto write_error;
}
/* Inform the master of our (slave) capabilities.
*
* EOF: supports EOF-style RDB transfer for diskless replication.
@ -3056,7 +3078,7 @@ void syncWithMaster(connection *conn) {
}
if (server.repl_state == REPL_STATE_RECEIVE_IP_REPLY && !server.slave_announce_ip)
server.repl_state = REPL_STATE_RECEIVE_CAPA_REPLY;
server.repl_state = REPL_STATE_RECEIVE_COMP_REPLY;
/* Receive REPLCONF ip-address reply. */
if (server.repl_state == REPL_STATE_RECEIVE_IP_REPLY) {
@ -3069,6 +3091,24 @@ void syncWithMaster(connection *conn) {
"REPLCONF ip-address: %s", err);
}
sdsfree(err);
server.repl_state = REPL_STATE_RECEIVE_COMP_REPLY;
return;
}
if (server.repl_state == REPL_STATE_RECEIVE_COMP_REPLY && !replconf_rdb_no_compress)
server.repl_state = REPL_STATE_RECEIVE_CAPA_REPLY;
/* Receive REPLCONF rdb-no-compress reply. */
if (server.repl_state == REPL_STATE_RECEIVE_COMP_REPLY) {
err = receiveSynchronousResponse(conn);
if (err == NULL) goto no_response_error;
/* Ignore the error if any, not all the Redis versions support
* REPLCONF rdb-no-compress. */
if (err[0] == '-') {
serverLog(LL_NOTICE,"(Non critical) Master does not understand "
"REPLCONF rdb-no-compress: %s", err);
}
sdsfree(err);
server.repl_state = REPL_STATE_RECEIVE_CAPA_REPLY;
return;
}

View file

@ -516,6 +516,7 @@ typedef enum {
REPL_STATE_RECEIVE_AUTH_REPLY, /* Wait for AUTH reply */
REPL_STATE_RECEIVE_PORT_REPLY, /* Wait for REPLCONF reply */
REPL_STATE_RECEIVE_IP_REPLY, /* Wait for REPLCONF reply */
REPL_STATE_RECEIVE_COMP_REPLY, /* Wait for REPLCONF reply */
REPL_STATE_RECEIVE_CAPA_REPLY, /* Wait for REPLCONF reply */
REPL_STATE_SEND_PSYNC, /* Send PSYNC */
REPL_STATE_RECEIVE_PSYNC_REPLY, /* Wait for PSYNC reply */
@ -581,6 +582,7 @@ typedef enum {
#define SLAVE_REQ_RDB_EXCLUDE_FUNCTIONS (1 << 1) /* Exclude functions from RDB */
#define SLAVE_REQ_SLOTS_SNAPSHOT (1 << 2) /* Only slots snapshot is required */
#define SLAVE_REQ_RDB_CHANNEL (1 << 3) /* Use rdb channel replication, transfer RDB background */
#define SLAVE_REQ_RDB_NO_COMPRESS (1 << 4) /* Don't enable RDB compression */
/* Mask of all bits in the slave requirements bitfield that represent non-standard (filtered) RDB requirements */
#define SLAVE_REQ_RDB_MASK (SLAVE_REQ_RDB_EXCLUDE_DATA | SLAVE_REQ_RDB_EXCLUDE_FUNCTIONS | SLAVE_REQ_SLOTS_SNAPSHOT)

View file

@ -916,6 +916,7 @@ start_server {tags {"repl external:skip tsan:skip"} overrides {save ""}} {
# so that the whole rdb generation process is bound to that
set loglines [count_log_lines -2]
[lindex $replicas 0] config set repl-diskless-load swapdb
[lindex $replicas 1] config set repl-diskless-load swapdb
[lindex $replicas 0] config set key-load-delay 100 ;# 20k keys and 100 microseconds sleep means at least 2 seconds
[lindex $replicas 0] replicaof $master_host $master_port
[lindex $replicas 1] replicaof $master_host $master_port