From 54cae05ea736340b4afe463eb750f5acdfe07590 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Fri, 16 Mar 2018 00:44:50 +0800 Subject: [PATCH 1/2] rdb: incremental fsync when redis saves rdb --- src/aof.c | 10 +++++----- src/bio.c | 2 +- src/config.c | 12 ++++++++++++ src/config.h | 6 +++--- src/rdb.c | 4 ++++ src/rio.c | 2 +- src/server.c | 3 ++- src/server.h | 6 ++++-- 8 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/aof.c b/src/aof.c index 4a7d749d..7712a779 100644 --- a/src/aof.c +++ b/src/aof.c @@ -228,7 +228,7 @@ static void killAppendOnlyChild(void) { void stopAppendOnly(void) { serverAssert(server.aof_state != AOF_OFF); flushAppendOnlyFile(1); - aof_fsync(server.aof_fd); + redis_fsync(server.aof_fd); close(server.aof_fd); server.aof_fd = -1; @@ -476,10 +476,10 @@ void flushAppendOnlyFile(int force) { /* Perform the fsync if needed. */ if (server.aof_fsync == AOF_FSYNC_ALWAYS) { - /* aof_fsync is defined as fdatasync() for Linux in order to avoid + /* redis_fsync is defined as fdatasync() for Linux in order to avoid * flushing metadata. */ latencyStartMonitor(latency); - aof_fsync(server.aof_fd); /* Let's try to get this data on the disk */ + redis_fsync(server.aof_fd); /* Let's try to get this data on the disk */ latencyEndMonitor(latency); latencyAddSampleIfNeeded("aof-fsync-always",latency); server.aof_last_fsync = server.unixtime; @@ -1241,7 +1241,7 @@ int rewriteAppendOnlyFile(char *filename) { rioInitWithFile(&aof,fp); if (server.aof_rewrite_incremental_fsync) - rioSetAutoSync(&aof,AOF_AUTOSYNC_BYTES); + rioSetAutoSync(&aof,REDIS_AUTOSYNC_BYTES); if (server.aof_use_rdb_preamble) { int error; @@ -1609,7 +1609,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { oldfd = server.aof_fd; server.aof_fd = newfd; if (server.aof_fsync == AOF_FSYNC_ALWAYS) - aof_fsync(newfd); + redis_fsync(newfd); else if (server.aof_fsync == AOF_FSYNC_EVERYSEC) aof_background_fsync(newfd); server.aof_selected_db = -1; /* Make sure SELECT is re-issued */ diff --git a/src/bio.c b/src/bio.c index da11f7b8..0c92d053 100644 --- a/src/bio.c +++ b/src/bio.c @@ -187,7 +187,7 @@ void *bioProcessBackgroundJobs(void *arg) { if (type == BIO_CLOSE_FILE) { close((long)job->arg1); } else if (type == BIO_AOF_FSYNC) { - aof_fsync((long)job->arg1); + redis_fsync((long)job->arg1); } else if (type == BIO_LAZY_FREE) { /* What we free changes depending on what arguments are set: * arg1 -> free the object at pointer. diff --git a/src/config.c b/src/config.c index eddfe1f1..f4187633 100644 --- a/src/config.c +++ b/src/config.c @@ -483,6 +483,13 @@ void loadServerConfigFromString(char *config) { yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } + } else if (!strcasecmp(argv[0],"rdb-save-incremental-fsync") && + argc == 2) + { + if ((server.rdb_save_incremental_fsync = + yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } } else if (!strcasecmp(argv[0],"aof-load-truncated") && argc == 2) { if ((server.aof_load_truncated = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; @@ -999,6 +1006,8 @@ void configSetCommand(client *c) { "cluster-require-full-coverage",server.cluster_require_full_coverage) { } config_set_bool_field( "aof-rewrite-incremental-fsync",server.aof_rewrite_incremental_fsync) { + } config_set_bool_field( + "rdb-save-incremental-fsync",server.rdb_save_incremental_fsync) { } config_set_bool_field( "aof-load-truncated",server.aof_load_truncated) { } config_set_bool_field( @@ -1311,6 +1320,8 @@ void configGetCommand(client *c) { server.repl_diskless_sync); config_get_bool_field("aof-rewrite-incremental-fsync", server.aof_rewrite_incremental_fsync); + config_get_bool_field("rdb-save-incremental-fsync", + server.rdb_save_incremental_fsync); config_get_bool_field("aof-load-truncated", server.aof_load_truncated); config_get_bool_field("aof-use-rdb-preamble", @@ -2044,6 +2055,7 @@ int rewriteConfig(char *path) { rewriteConfigClientoutputbufferlimitOption(state); rewriteConfigNumericalOption(state,"hz",server.hz,CONFIG_DEFAULT_HZ); rewriteConfigYesNoOption(state,"aof-rewrite-incremental-fsync",server.aof_rewrite_incremental_fsync,CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC); + rewriteConfigYesNoOption(state,"rdb-save-incremental-fsync",server.rdb_save_incremental_fsync,CONFIG_DEFAULT_RDB_SAVE_INCREMENTAL_FSYNC); rewriteConfigYesNoOption(state,"aof-load-truncated",server.aof_load_truncated,CONFIG_DEFAULT_AOF_LOAD_TRUNCATED); rewriteConfigYesNoOption(state,"aof-use-rdb-preamble",server.aof_use_rdb_preamble,CONFIG_DEFAULT_AOF_USE_RDB_PREAMBLE); rewriteConfigEnumOption(state,"supervised",server.supervised_mode,supervised_mode_enum,SUPERVISED_NONE); diff --git a/src/config.h b/src/config.h index c23f1c78..ee3ad508 100644 --- a/src/config.h +++ b/src/config.h @@ -87,11 +87,11 @@ #endif #endif -/* Define aof_fsync to fdatasync() in Linux and fsync() for all the rest */ +/* Define redis_fsync to fdatasync() in Linux and fsync() for all the rest */ #ifdef __linux__ -#define aof_fsync fdatasync +#define redis_fsync fdatasync #else -#define aof_fsync fsync +#define redis_fsync fsync #endif /* Define rdb_fsync_range to sync_file_range() on Linux, otherwise we use diff --git a/src/rdb.c b/src/rdb.c index 8f896983..c824ab20 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -1060,6 +1060,10 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) { } rioInitWithFile(&rdb,fp); + + if (server.rdb_save_incremental_fsync) + rioSetAutoSync(&rdb,REDIS_AUTOSYNC_BYTES); + if (rdbSaveRio(&rdb,&error,RDB_SAVE_NONE,rsi) == C_ERR) { errno = error; goto werr; diff --git a/src/rio.c b/src/rio.c index 23b90706..c9c76b8f 100644 --- a/src/rio.c +++ b/src/rio.c @@ -116,7 +116,7 @@ static size_t rioFileWrite(rio *r, const void *buf, size_t len) { r->io.file.buffered >= r->io.file.autosync) { fflush(r->io.file.fp); - aof_fsync(fileno(r->io.file.fp)); + redis_fsync(fileno(r->io.file.fp)); r->io.file.buffered = 0; } return retval; diff --git a/src/server.c b/src/server.c index 1a6f3038..f4d6e95a 100644 --- a/src/server.c +++ b/src/server.c @@ -1416,6 +1416,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_rewrite_incremental_fsync = CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC; + server.rdb_save_incremental_fsync = CONFIG_DEFAULT_RDB_SAVE_INCREMENTAL_FSYNC; server.aof_load_truncated = CONFIG_DEFAULT_AOF_LOAD_TRUNCATED; server.aof_use_rdb_preamble = CONFIG_DEFAULT_AOF_USE_RDB_PREAMBLE; server.pidfile = NULL; @@ -2585,7 +2586,7 @@ int prepareForShutdown(int flags) { /* Append only file: flush buffers and fsync() the AOF at exit */ serverLog(LL_NOTICE,"Calling fsync() on the AOF file."); flushAppendOnlyFile(1); - aof_fsync(server.aof_fd); + redis_fsync(server.aof_fd); } /* Create a new RDB file before exiting. */ diff --git a/src/server.h b/src/server.h index 29919f5e..d2561324 100644 --- a/src/server.h +++ b/src/server.h @@ -143,6 +143,7 @@ typedef long long mstime_t; /* millisecond time type. */ #define CONFIG_DEFAULT_AOF_USE_RDB_PREAMBLE 0 #define CONFIG_DEFAULT_ACTIVE_REHASHING 1 #define CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC 1 +#define CONFIG_DEFAULT_RDB_SAVE_INCREMENTAL_FSYNC 1 #define CONFIG_DEFAULT_MIN_SLAVES_TO_WRITE 0 #define CONFIG_DEFAULT_MIN_SLAVES_MAX_LAG 10 #define NET_IP_STR_LEN 46 /* INET6_ADDRSTRLEN is 46, but we need to be sure */ @@ -183,7 +184,7 @@ typedef long long mstime_t; /* millisecond time type. */ #define PROTO_INLINE_MAX_SIZE (1024*64) /* Max size of inline reads */ #define PROTO_MBULK_BIG_ARG (1024*32) #define LONG_STR_SIZE 21 /* Bytes needed for long -> str + '\0' */ -#define AOF_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */ +#define REDIS_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */ /* When configuring the server eventloop, we setup it so that the total number * of file descriptors we can handle are server.maxclients + RESERVED_FDS + @@ -1021,7 +1022,8 @@ struct redisServer { time_t aof_rewrite_time_start; /* Current AOF rewrite start time. */ int aof_lastbgrewrite_status; /* C_OK or C_ERR */ unsigned long aof_delayed_fsync; /* delayed AOF fsync() counter */ - int aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */ + int aof_rewrite_incremental_fsync;/* fsync incrementally while aof rewriting? */ + int rdb_save_incremental_fsync; /* fsync incrementally while rdb saving? */ int aof_last_write_status; /* C_OK or C_ERR */ int aof_last_write_errno; /* Valid if aof_last_write_status is ERR */ int aof_load_truncated; /* Don't stop on unexpected AOF EOF. */ From fd0c4c027713d1d34a8dd5ef62556b9ac0940d45 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Fri, 16 Mar 2018 00:48:59 +0800 Subject: [PATCH 2/2] add rdb-save-incremental-fsync option in redis.conf --- redis.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/redis.conf b/redis.conf index 1e1f5313..427fc7dd 100644 --- a/redis.conf +++ b/redis.conf @@ -1193,6 +1193,12 @@ hz 10 # big latency spikes. aof-rewrite-incremental-fsync yes +# When redis saves RDB file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +rdb-save-incremental-fsync yes + # Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good # idea to start with the default settings and only change them after investigating # how to improve the performances and how the keys LFU change over time, which