summaryrefslogtreecommitdiff
path: root/src/replication.c
diff options
context:
space:
mode:
authorTian <skylypig@gmail.com>2022-06-21 00:17:23 +0800
committerGitHub <noreply@github.com>2022-06-20 19:17:23 +0300
commit99a425d0f3b7b00896cb855d5de4ae93be1fe3f0 (patch)
treee786f79d71c642c36e9f48965f830e097a4ef8eb /src/replication.c
parent4c72a09b78f6adcc3657b0d1b7ce64f2dd028c72 (diff)
downloadredis-99a425d0f3b7b00896cb855d5de4ae93be1fe3f0.tar.gz
Fsync directory while persisting AOF manifest, RDB file, and config file (#10737)
The current process to persist files is `write` the data, `fsync` and `rename` the file, but a underlying problem is that the rename may be lost when a sudden crash like power outage and the directory hasn't been persisted. The article [Ensuring data reaches disk](https://lwn.net/Articles/457667/) mentions a safe way to update file should be: 1. create a new temp file (on the same file system!) 2. write data to the temp file 3. fsync() the temp file 4. rename the temp file to the appropriate name 5. fsync() the containing directory This commit handles CONFIG REWRITE, AOF manifest, and RDB file (both for persistence, and the one the replica gets from the master). It doesn't handle (yet), ACL SAVE and Cluster configs, since these don't yet follow this pattern.
Diffstat (limited to 'src/replication.c')
-rw-r--r--src/replication.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/replication.c b/src/replication.c
index 8a40a8197..b929b0460 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -2151,6 +2151,16 @@ void readSyncBulkPayload(connection *conn) {
/* Close old rdb asynchronously. */
if (old_rdb_fd != -1) bioCreateCloseJob(old_rdb_fd);
+ /* Sync the directory to ensure rename is persisted */
+ if (fsyncFileDir(server.rdb_filename) == -1) {
+ serverLog(LL_WARNING,
+ "Failed trying to sync DB directory %s in "
+ "MASTER <-> REPLICA synchronization: %s",
+ server.rdb_filename, strerror(errno));
+ cancelReplicationHandshake(1);
+ return;
+ }
+
if (rdbLoad(server.rdb_filename,&rsi,RDBFLAGS_REPLICATION) != C_OK) {
serverLog(LL_WARNING,
"Failed trying to load the MASTER synchronization "