Add flush-before-load option for repl-diskless-load (#909)
A new option for diskless replication on the replica side. After a network failure, the replica may need to perform a full sync. The other option for diskless full sync is `swapdb`, but it uses twice as much memory, temporarily. In situations where this is not acceptable, and where losing data is acceptable, the `flush-before-load` can be useful. If the full sync fails, the old data is lost though. Therefore, the new option is marked as "dangerous". --------- Signed-off-by: kronwerk <ca11e5e22g@gmail.com> Signed-off-by: kronwerk <kronwerk@users.noreply.github.com> Co-authored-by: kronwerk <ca11e5e22g@gmail.com>
This commit is contained in:
parent
1892f8a731
commit
cd8de095c4
@ -107,6 +107,7 @@ configEnum repl_diskless_load_enum[] = {
|
|||||||
{"disabled", REPL_DISKLESS_LOAD_DISABLED},
|
{"disabled", REPL_DISKLESS_LOAD_DISABLED},
|
||||||
{"on-empty-db", REPL_DISKLESS_LOAD_WHEN_DB_EMPTY},
|
{"on-empty-db", REPL_DISKLESS_LOAD_WHEN_DB_EMPTY},
|
||||||
{"swapdb", REPL_DISKLESS_LOAD_SWAPDB},
|
{"swapdb", REPL_DISKLESS_LOAD_SWAPDB},
|
||||||
|
{"flush-before-load", REPL_DISKLESS_LOAD_FLUSH_BEFORE_LOAD},
|
||||||
{NULL, 0}};
|
{NULL, 0}};
|
||||||
|
|
||||||
configEnum tls_auth_clients_enum[] = {
|
configEnum tls_auth_clients_enum[] = {
|
||||||
|
@ -1943,6 +1943,7 @@ void restartAOFAfterSYNC(void) {
|
|||||||
static int useDisklessLoad(void) {
|
static int useDisklessLoad(void) {
|
||||||
/* compute boolean decision to use diskless load */
|
/* compute boolean decision to use diskless load */
|
||||||
int enabled = server.repl_diskless_load == REPL_DISKLESS_LOAD_SWAPDB ||
|
int enabled = server.repl_diskless_load == REPL_DISKLESS_LOAD_SWAPDB ||
|
||||||
|
server.repl_diskless_load == REPL_DISKLESS_LOAD_FLUSH_BEFORE_LOAD ||
|
||||||
(server.repl_diskless_load == REPL_DISKLESS_LOAD_WHEN_DB_EMPTY && dbTotalServerKeyCount() == 0);
|
(server.repl_diskless_load == REPL_DISKLESS_LOAD_WHEN_DB_EMPTY && dbTotalServerKeyCount() == 0);
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
@ -490,6 +490,7 @@ typedef enum {
|
|||||||
#define REPL_DISKLESS_LOAD_DISABLED 0
|
#define REPL_DISKLESS_LOAD_DISABLED 0
|
||||||
#define REPL_DISKLESS_LOAD_WHEN_DB_EMPTY 1
|
#define REPL_DISKLESS_LOAD_WHEN_DB_EMPTY 1
|
||||||
#define REPL_DISKLESS_LOAD_SWAPDB 2
|
#define REPL_DISKLESS_LOAD_SWAPDB 2
|
||||||
|
#define REPL_DISKLESS_LOAD_FLUSH_BEFORE_LOAD 3
|
||||||
|
|
||||||
/* TLS Client Authentication */
|
/* TLS Client Authentication */
|
||||||
#define TLS_CLIENT_AUTH_NO 0
|
#define TLS_CLIENT_AUTH_NO 0
|
||||||
|
@ -1478,6 +1478,63 @@ start_server {tags {"repl external:skip"}} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach dualchannel {yes no} {
|
||||||
|
test "replica actually flushes db if use diskless load with flush-before-load dual-channel-replication-enabled=$dualchannel" {
|
||||||
|
start_server {tags {"repl"}} {
|
||||||
|
set replica [srv 0 client]
|
||||||
|
set replica_log [srv 0 stdout]
|
||||||
|
start_server {} {
|
||||||
|
set master [srv 0 client]
|
||||||
|
set master_host [srv 0 host]
|
||||||
|
set master_port [srv 0 port]
|
||||||
|
|
||||||
|
# Fill both replica and master with data
|
||||||
|
$master debug populate 100 master 100000
|
||||||
|
$replica debug populate 201 replica 100000
|
||||||
|
assert_equal [$replica dbsize] 201
|
||||||
|
# Set up master
|
||||||
|
$master config set save ""
|
||||||
|
$master config set rdbcompression no
|
||||||
|
$master config set repl-diskless-sync yes
|
||||||
|
$master config set repl-diskless-sync-delay 0
|
||||||
|
$master config set dual-channel-replication-enabled $dualchannel
|
||||||
|
# Set master with a slow rdb generation, so that we can easily intercept loading
|
||||||
|
# 10ms per key, with 1000 keys is 10 seconds
|
||||||
|
$master config set rdb-key-save-delay 10000
|
||||||
|
# Set up replica
|
||||||
|
$replica config set save ""
|
||||||
|
$replica config set repl-diskless-load flush-before-load
|
||||||
|
$replica config set dual-channel-replication-enabled $dualchannel
|
||||||
|
# Start the replication process...
|
||||||
|
$replica replicaof $master_host $master_port
|
||||||
|
|
||||||
|
wait_for_condition 100 100 {
|
||||||
|
[s -1 loading] eq 1
|
||||||
|
} else {
|
||||||
|
fail "Replica didn't start loading"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure that next sync will not start immediately so that we can catch the replica in between syncs
|
||||||
|
$master config set repl-diskless-sync-delay 5
|
||||||
|
|
||||||
|
# Kill the replica connection on the master
|
||||||
|
set killed [$master client kill type replica]
|
||||||
|
|
||||||
|
wait_for_condition 100 100 {
|
||||||
|
[s -1 loading] eq 0
|
||||||
|
} else {
|
||||||
|
fail "Replica didn't disconnect"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal [$replica dbsize] 0
|
||||||
|
|
||||||
|
# Speed up shutdown
|
||||||
|
$master config set rdb-key-save-delay 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} {} {external:skip}
|
||||||
|
}
|
||||||
|
|
||||||
start_server {tags {"repl external:skip"}} {
|
start_server {tags {"repl external:skip"}} {
|
||||||
set replica [srv 0 client]
|
set replica [srv 0 client]
|
||||||
$replica set replica_key replica_value
|
$replica set replica_key replica_value
|
||||||
|
25
valkey.conf
25
valkey.conf
@ -667,17 +667,20 @@ repl-diskless-sync-max-replicas 0
|
|||||||
# fully loaded in memory, resulting in higher memory usage.
|
# fully loaded in memory, resulting in higher memory usage.
|
||||||
# For this reason we have the following options:
|
# For this reason we have the following options:
|
||||||
#
|
#
|
||||||
# "disabled" - Don't use diskless load (store the rdb file to the disk first)
|
# "disabled" - Don't use diskless load (store the rdb file to the disk first)
|
||||||
# "swapdb" - Keep current db contents in RAM while parsing the data directly
|
# "swapdb" - Keep current db contents in RAM while parsing the data directly
|
||||||
# from the socket. Replicas in this mode can keep serving current
|
# from the socket. Replicas in this mode can keep serving current
|
||||||
# dataset while replication is in progress, except for cases where
|
# dataset while replication is in progress, except for cases where
|
||||||
# they can't recognize primary as having a data set from same
|
# they can't recognize primary as having a data set from same
|
||||||
# replication history.
|
# replication history.
|
||||||
# Note that this requires sufficient memory, if you don't have it,
|
# Note that this requires sufficient memory, if you don't have it,
|
||||||
# you risk an OOM kill.
|
# you risk an OOM kill.
|
||||||
# "on-empty-db" - Use diskless load only when current dataset is empty. This is
|
# "on-empty-db" - Use diskless load only when current dataset is empty. This is
|
||||||
# safer and avoid having old and new dataset loaded side by side
|
# safer and avoid having old and new dataset loaded side by side
|
||||||
# during replication.
|
# during replication.
|
||||||
|
# "flush-before-load" - [dangerous] Flush all data before parsing. Note that if
|
||||||
|
# there's a problem before the replication succeeded you may
|
||||||
|
# lose all your data.
|
||||||
repl-diskless-load disabled
|
repl-diskless-load disabled
|
||||||
|
|
||||||
# This dual channel replication sync feature optimizes the full synchronization process
|
# This dual channel replication sync feature optimizes the full synchronization process
|
||||||
|
Loading…
x
Reference in New Issue
Block a user