diff options
-rw-r--r-- | src/aof.c | 31 | ||||
-rw-r--r-- | src/server.c | 1 | ||||
-rw-r--r-- | src/server.h | 3 | ||||
-rw-r--r-- | tests/unit/wait.tcl | 42 |
4 files changed, 64 insertions, 13 deletions
@@ -758,6 +758,7 @@ void aofOpenIfNeededOnServerStart(void) { } server.aof_last_incr_size = getAppendOnlyFileSize(aof_name, NULL); + server.aof_last_incr_fsync_offset = server.aof_last_incr_size; if (incr_aof_len) { serverLog(LL_NOTICE, "Opening AOF incr file %s on server start", aof_name); @@ -832,13 +833,14 @@ int openNewIncrAofForAppend(void) { * is already synced at this point so fsync doesn't matter. */ if (server.aof_fd != -1) { aof_background_fsync_and_close(server.aof_fd); - server.aof_fsync_offset = server.aof_current_size; server.aof_last_fsync = server.unixtime; } server.aof_fd = newfd; /* Reset the aof_last_incr_size. */ server.aof_last_incr_size = 0; + /* Reset the aof_last_incr_fsync_offset. */ + server.aof_last_incr_fsync_offset = 0; /* Update `server.aof_manifest`. */ if (temp_am) aofManifestFreeAndUpdate(temp_am); return C_OK; @@ -952,7 +954,6 @@ void stopAppendOnly(void) { if (redis_fsync(server.aof_fd) == -1) { serverLog(LL_WARNING,"Fail to fsync the AOF file: %s",strerror(errno)); } else { - server.aof_fsync_offset = server.aof_current_size; server.aof_last_fsync = server.unixtime; } close(server.aof_fd); @@ -962,6 +963,7 @@ void stopAppendOnly(void) { server.aof_state = AOF_OFF; server.aof_rewrite_scheduled = 0; server.aof_last_incr_size = 0; + server.aof_last_incr_fsync_offset = 0; server.fsynced_reploff = -1; atomicSet(server.fsynced_reploff_pending, 0); killAppendOnlyChild(); @@ -1083,10 +1085,19 @@ void flushAppendOnlyFile(int force) { * stop write commands before fsync called in one second, * the data in page cache cannot be flushed in time. */ if (server.aof_fsync == AOF_FSYNC_EVERYSEC && - server.aof_fsync_offset != server.aof_current_size && + server.aof_last_incr_fsync_offset != server.aof_last_incr_size && server.unixtime > server.aof_last_fsync && !(sync_in_progress = aofFsyncInProgress())) { goto try_fsync; + + /* Check if we need to do fsync even the aof buffer is empty, + * the reason is described in the previous AOF_FSYNC_EVERYSEC block, + * and AOF_FSYNC_ALWAYS is also checked here to handle a case where + * aof_fsync is changed from everysec to always. */ + } else if (server.aof_fsync == AOF_FSYNC_ALWAYS && + server.aof_last_incr_fsync_offset != server.aof_last_incr_size) + { + goto try_fsync; } else { return; } @@ -1253,14 +1264,14 @@ try_fsync: } latencyEndMonitor(latency); latencyAddSampleIfNeeded("aof-fsync-always",latency); - server.aof_fsync_offset = server.aof_current_size; + server.aof_last_incr_fsync_offset = server.aof_last_incr_size; server.aof_last_fsync = server.unixtime; atomicSet(server.fsynced_reploff_pending, server.master_repl_offset); - } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC && - server.unixtime > server.aof_last_fsync)) { + } else if (server.aof_fsync == AOF_FSYNC_EVERYSEC && + server.unixtime > server.aof_last_fsync) { if (!sync_in_progress) { aof_background_fsync(server.aof_fd); - server.aof_fsync_offset = server.aof_current_size; + server.aof_last_incr_fsync_offset = server.aof_last_incr_size; } server.aof_last_fsync = server.unixtime; } @@ -1766,7 +1777,6 @@ int loadAppendOnlyFiles(aofManifest *am) { * executed early, but that shouldn't be a problem since everything will be * fine after the first AOFRW. */ server.aof_rewrite_base_size = base_size; - server.aof_fsync_offset = server.aof_current_size; cleanup: stopLoading(ret == AOF_OK || ret == AOF_TRUNCATED); @@ -2666,13 +2676,10 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { /* We can safely let `server.aof_manifest` point to 'temp_am' and free the previous one. */ aofManifestFreeAndUpdate(temp_am); - if (server.aof_fd != -1) { + if (server.aof_state != AOF_OFF) { /* AOF enabled. */ - server.aof_selected_db = -1; /* Make sure SELECT is re-issued */ server.aof_current_size = getAppendOnlyFileSize(new_base_filename, NULL) + server.aof_last_incr_size; server.aof_rewrite_base_size = server.aof_current_size; - server.aof_fsync_offset = server.aof_current_size; - server.aof_last_fsync = server.unixtime; } /* We don't care about the return value of `aofDelHistoryFiles`, because the history diff --git a/src/server.c b/src/server.c index 4e77d2f6d..4855ee1a8 100644 --- a/src/server.c +++ b/src/server.c @@ -2018,6 +2018,7 @@ void initServerConfig(void) { server.aof_selected_db = -1; /* Make sure the first time will not match */ server.aof_flush_postponed_start = 0; server.aof_last_incr_size = 0; + server.aof_last_incr_fsync_offset = 0; server.active_defrag_running = 0; server.notify_keyspace_events = 0; server.blocked_clients = 0; diff --git a/src/server.h b/src/server.h index 1a68071f1..43d85008a 100644 --- a/src/server.h +++ b/src/server.h @@ -1742,7 +1742,8 @@ struct redisServer { off_t aof_rewrite_base_size; /* AOF size on latest startup or rewrite. */ off_t aof_current_size; /* AOF current size (Including BASE + INCRs). */ off_t aof_last_incr_size; /* The size of the latest incr AOF. */ - off_t aof_fsync_offset; /* AOF offset which is already synced to disk. */ + off_t aof_last_incr_fsync_offset; /* AOF offset which is already requested to be synced to disk. + * Compare with the aof_last_incr_size. */ int aof_flush_sleep; /* Micros to sleep before flush. (used by tests) */ int aof_rewrite_scheduled; /* Rewrite once BGSAVE terminates. */ sds aof_buf; /* AOF buffer, written before entering the event loop */ diff --git a/tests/unit/wait.tcl b/tests/unit/wait.tcl index 08a7a71f6..af13a3374 100644 --- a/tests/unit/wait.tcl +++ b/tests/unit/wait.tcl @@ -175,7 +175,49 @@ tags {"wait aof network external:skip"} { $replica config set appendfsync everysec test {WAITAOF replica copy everysec} { + $replica config set appendfsync everysec + waitForBgrewriteaof $replica ;# Make sure there is no AOFRW + + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + } + + test {WAITAOF replica copy everysec with AOFRW} { + $replica config set appendfsync everysec + + # When we trigger an AOFRW, a fsync is triggered when closing the old INCR file, + # so with the everysec, we will skip that second of fsync, and in the next second + # after that, we will eventually do the fsync. + $replica bgrewriteaof + waitForBgrewriteaof $replica + + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + } + + test {WAITAOF replica copy everysec with slow AOFRW} { + $replica config set appendfsync everysec + $replica config set rdb-key-save-delay 1000000 ;# 1 sec + + $replica bgrewriteaof + + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + + $replica config set rdb-key-save-delay 0 + waitForBgrewriteaof $replica + } + + test {WAITAOF replica copy everysec->always with AOFRW} { + $replica config set appendfsync everysec + + # Try to fit all of them in the same round second, although there's no way to guarantee + # that, it can be done on fast machine. In any case, the test shouldn't fail either. + $replica bgrewriteaof $master incr foo + waitForBgrewriteaof $replica + $replica config set appendfsync always + assert_equal [$master waitaof 0 1 0] {1 1} } |