From 6a436b6f723f9b089d0a8bf64ab0da5f37524847 Mon Sep 17 00:00:00 2001 From: Yuan Wang Date: Thu, 8 May 2025 08:47:29 +0800 Subject: [PATCH] Redis-cli gets RDB by RDB channel (#13809) Now we have RDB channel in https://github.com/redis/redis/pull/13732, child process can transfer RDB in a background method, instead of handled by main thread. So when redis-cli gets RDB from server, we can adopt this way to reduce the main thread load. --------- Co-authored-by: Ozan Tezcan --- src/rdb.c | 2 +- src/replication.c | 16 +++++++++++----- src/server.h | 2 +- tests/integration/redis-cli.tcl | 9 +++++++++ tmp | Bin 0 -> 177 bytes 5 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 tmp diff --git a/src/rdb.c b/src/rdb.c index 153803939..3cee19788 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -3884,7 +3884,7 @@ int rdbSaveToSlavesSockets(int req, rdbSaveInfo *rsi) { listIter li; pid_t childpid; int pipefds[2], rdb_pipe_write = 0, safe_to_exit_pipe = 0; - int rdb_channel = (req & SLAVE_REQ_RDB_CHANNEL); + int rdb_channel = server.repl_rdb_channel && (req & SLAVE_REQ_RDB_CHANNEL); if (hasActiveChildProcess()) return C_ERR; diff --git a/src/replication.c b/src/replication.c index b90e84280..a18e74f11 100644 --- a/src/replication.c +++ b/src/replication.c @@ -782,7 +782,7 @@ int replicationSetupSlaveForFullResync(client *slave, long long offset) { /* Don't send this reply to slaves that approached us with * the old SYNC command. */ if (!(slave->flags & CLIENT_PRE_PSYNC)) { - if (slave->slave_req & SLAVE_REQ_RDB_CHANNEL) { + if (slave->flags & CLIENT_REPL_RDB_CHANNEL) { /* This slave is rdbchannel. Find its associated main channel and * change its state so we can deliver replication stream from now * on, in parallel to rdb. */ @@ -1356,8 +1356,16 @@ void replconfCommand(client *c) { if (getRangeLongFromObjectOrReply(c,c->argv[j+1], 0,1,&rdb_only,NULL) != C_OK) return; - if (rdb_only == 1) c->flags |= CLIENT_REPL_RDBONLY; - else c->flags &= ~CLIENT_REPL_RDBONLY; + if (rdb_only == 1) { + c->flags |= CLIENT_REPL_RDBONLY; + /* If replicas ask for RDB only, We can apply the background + * RDB transfer optimization based on the configurations. */ + if (server.repl_rdb_channel && server.repl_diskless_sync) + c->slave_req |= SLAVE_REQ_RDB_CHANNEL; + } else { + c->flags &= ~CLIENT_REPL_RDBONLY; + c->slave_req &= ~SLAVE_REQ_RDB_CHANNEL; + } } else if (!strcasecmp(c->argv[j]->ptr,"rdb-filter-only")) { /* REPLCONFG RDB-FILTER-ONLY is used to define "include" filters * for the RDB snapshot. Currently we only support a single @@ -1391,10 +1399,8 @@ void replconfCommand(client *c) { return; if (rdb_channel == 1) { c->flags |= CLIENT_REPL_RDB_CHANNEL; - c->slave_req |= SLAVE_REQ_RDB_CHANNEL; } else { c->flags &= ~CLIENT_REPL_RDB_CHANNEL; - c->slave_req &= ~SLAVE_REQ_RDB_CHANNEL; } } else if (!strcasecmp(c->argv[j]->ptr, "main-ch-client-id")) { /* REPLCONF main-ch-client-id is used to identify diff --git a/src/server.h b/src/server.h index 1fb999c7a..0d2350a6a 100644 --- a/src/server.h +++ b/src/server.h @@ -533,7 +533,7 @@ typedef enum { #define SLAVE_REQ_NONE 0 #define SLAVE_REQ_RDB_EXCLUDE_DATA (1 << 0) /* Exclude data from RDB */ #define SLAVE_REQ_RDB_EXCLUDE_FUNCTIONS (1 << 1) /* Exclude functions from RDB */ -#define SLAVE_REQ_RDB_CHANNEL (1 << 2) /* Use rdb channel replication */ +#define SLAVE_REQ_RDB_CHANNEL (1 << 2) /* Use rdb channel replication, transfer RDB background */ /* 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) diff --git a/tests/integration/redis-cli.tcl b/tests/integration/redis-cli.tcl index 590c5711f..399022b77 100644 --- a/tests/integration/redis-cli.tcl +++ b/tests/integration/redis-cli.tcl @@ -651,6 +651,9 @@ if {!$::tls} { ;# fake_redis_node doesn't support TLS r flushdb r function flush + if {!$::external} { + set lines [count_log_lines 0] + } set dir [lindex [r config get dir] 1] assert_equal "OK" [r debug populate 100000 key 1000] @@ -663,6 +666,12 @@ if {!$::tls} { ;# fake_redis_node doesn't support TLS catch {run_cli {*}$args} output assert_match {*Transfer finished with success*} $output + # If server enabled diskless sync, it should transfer the RDB by RDB channel + # since server will automatically apply this optimization for rdb-only. + if {[r config get repl-diskless-sync] == "yes" && !$::external} { + verify_log_message 0 "*replicas sockets (rdb-channel)*" $lines + } + file delete "$dir/dump.rdb" file rename "$dir/cli.rdb" "$dir/dump.rdb" diff --git a/tmp b/tmp new file mode 100644 index 0000000000000000000000000000000000000000..b9eeb6841b869a8eac89a1c2a1bf08d44e52f324 GIT binary patch literal 177 zcmXYoJqp4w7(nYF)>b@+2$3Y1ST_+Jx)ntir~G`CfT5C9Z{lfON>3$ORI0;!!-Kcm zZt^|GgodF5Z9KYzODSWsKOy;LX=>lBLSNO!Li<=h&mq2f(8z*qi`OU$V+Yp@^0fnD zk(Nyq23;|Fk`Z7SFH|;HQgfl{S9D3V%rs`46DC9^u;L-@j;bs@)Xg-+qAHOT9-8Rg K9*f=~KP4Xo@IRIS literal 0 HcmV?d00001