mirror of
https://github.com/fluencelabs/redis
synced 2025-06-13 01:01:22 +00:00
AOF auto rewrite backported to 2.4
This commit is contained in:
20
redis.conf
20
redis.conf
@ -292,6 +292,26 @@ appendfsync everysec
|
|||||||
# "no" that is the safest pick from the point of view of durability.
|
# "no" that is the safest pick from the point of view of durability.
|
||||||
no-appendfsync-on-rewrite no
|
no-appendfsync-on-rewrite no
|
||||||
|
|
||||||
|
# Automatic rewrite of the append only file.
|
||||||
|
# Redis is able to automatically rewrite the log file implicitly calling
|
||||||
|
# BGREWRITEAOF when the AOF log size will growth by the specified percentage.
|
||||||
|
#
|
||||||
|
# This is how it works: Redis remembers the size of the AOF file after the
|
||||||
|
# latest rewrite (or if no rewrite happened since the restart, the size of
|
||||||
|
# the AOF at startup is used).
|
||||||
|
#
|
||||||
|
# This base size is compared to the current size. If the current size is
|
||||||
|
# bigger than the specified percentage, the rewrite is triggered. Also
|
||||||
|
# you need to specify a minimal size for the AOF file to be rewritten, this
|
||||||
|
# is useful to avoid rewriting the AOF file even if the percentage increase
|
||||||
|
# is reached but it is still pretty small.
|
||||||
|
#
|
||||||
|
# Specify a precentage of zero in order to disable the automatic AOF
|
||||||
|
# rewrite feature.
|
||||||
|
|
||||||
|
auto-aof-rewrite-percentage 100
|
||||||
|
auto-aof-rewrite-min-size 64mb
|
||||||
|
|
||||||
################################ VIRTUAL MEMORY ###############################
|
################################ VIRTUAL MEMORY ###############################
|
||||||
|
|
||||||
### WARNING! Virtual Memory is deprecated in Redis 2.4
|
### WARNING! Virtual Memory is deprecated in Redis 2.4
|
||||||
|
36
src/aof.c
36
src/aof.c
@ -8,6 +8,8 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
void aofUpdateCurrentSize(void);
|
||||||
|
|
||||||
/* Called when the user switches from "appendonly yes" to "appendonly no"
|
/* Called when the user switches from "appendonly yes" to "appendonly no"
|
||||||
* at runtime using the CONFIG command. */
|
* at runtime using the CONFIG command. */
|
||||||
void stopAppendOnly(void) {
|
void stopAppendOnly(void) {
|
||||||
@ -19,15 +21,15 @@ void stopAppendOnly(void) {
|
|||||||
server.appendseldb = -1;
|
server.appendseldb = -1;
|
||||||
server.appendonly = 0;
|
server.appendonly = 0;
|
||||||
/* rewrite operation in progress? kill it, wait child exit */
|
/* rewrite operation in progress? kill it, wait child exit */
|
||||||
if (server.bgsavechildpid != -1) {
|
if (server.bgrewritechildpid != -1) {
|
||||||
int statloc;
|
int statloc;
|
||||||
|
|
||||||
if (kill(server.bgsavechildpid,SIGKILL) != -1)
|
if (kill(server.bgrewritechildpid,SIGKILL) != -1)
|
||||||
wait3(&statloc,0,NULL);
|
wait3(&statloc,0,NULL);
|
||||||
/* reset the buffer accumulating changes while the child saves */
|
/* reset the buffer accumulating changes while the child saves */
|
||||||
sdsfree(server.bgrewritebuf);
|
sdsfree(server.bgrewritebuf);
|
||||||
server.bgrewritebuf = sdsempty();
|
server.bgrewritebuf = sdsempty();
|
||||||
server.bgsavechildpid = -1;
|
server.bgrewritechildpid = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +84,7 @@ void flushAppendOnlyFile(void) {
|
|||||||
}
|
}
|
||||||
sdsfree(server.aofbuf);
|
sdsfree(server.aofbuf);
|
||||||
server.aofbuf = sdsempty();
|
server.aofbuf = sdsempty();
|
||||||
|
server.appendonly_current_size += nwritten;
|
||||||
|
|
||||||
/* Don't Fsync if no-appendfsync-on-rewrite is set to yes and we have
|
/* Don't Fsync if no-appendfsync-on-rewrite is set to yes and we have
|
||||||
* childs performing heavy I/O on disk. */
|
* childs performing heavy I/O on disk. */
|
||||||
@ -221,6 +224,7 @@ int loadAppendOnlyFile(char *filename) {
|
|||||||
long loops = 0;
|
long loops = 0;
|
||||||
|
|
||||||
if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {
|
if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {
|
||||||
|
server.appendonly_current_size = 0;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
@ -311,6 +315,8 @@ int loadAppendOnlyFile(char *filename) {
|
|||||||
freeFakeClient(fakeClient);
|
freeFakeClient(fakeClient);
|
||||||
server.appendonly = appendonly;
|
server.appendonly = appendonly;
|
||||||
stopLoading();
|
stopLoading();
|
||||||
|
aofUpdateCurrentSize();
|
||||||
|
server.auto_aofrewrite_base_size = server.appendonly_current_size;
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
|
|
||||||
readerr:
|
readerr:
|
||||||
@ -633,9 +639,10 @@ int rewriteAppendOnlyFileBackground(void) {
|
|||||||
void bgrewriteaofCommand(redisClient *c) {
|
void bgrewriteaofCommand(redisClient *c) {
|
||||||
if (server.bgrewritechildpid != -1) {
|
if (server.bgrewritechildpid != -1) {
|
||||||
addReplyError(c,"Background append only file rewriting already in progress");
|
addReplyError(c,"Background append only file rewriting already in progress");
|
||||||
return;
|
} else if (server.bgsavechildpid != -1) {
|
||||||
}
|
server.aofrewrite_scheduled = 1;
|
||||||
if (rewriteAppendOnlyFileBackground() == REDIS_OK) {
|
addReplyStatus(c,"Background append only file rewriting scheduled");
|
||||||
|
} else if (rewriteAppendOnlyFileBackground() == REDIS_OK) {
|
||||||
addReplyStatus(c,"Background append only file rewriting started");
|
addReplyStatus(c,"Background append only file rewriting started");
|
||||||
} else {
|
} else {
|
||||||
addReply(c,shared.err);
|
addReply(c,shared.err);
|
||||||
@ -649,6 +656,21 @@ void aofRemoveTempFile(pid_t childpid) {
|
|||||||
unlink(tmpfile);
|
unlink(tmpfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the server.appendonly_current_size filed explicitly using stat(2)
|
||||||
|
* to check the size of the file. This is useful after a rewrite or after
|
||||||
|
* a restart, normally the size is updated just adding the write length
|
||||||
|
* to the current lenght, that is much faster. */
|
||||||
|
void aofUpdateCurrentSize(void) {
|
||||||
|
struct redis_stat sb;
|
||||||
|
|
||||||
|
if (redis_fstat(server.appendfd,&sb) == -1) {
|
||||||
|
redisLog(REDIS_WARNING,"Unable to check the AOF length: %s",
|
||||||
|
strerror(errno));
|
||||||
|
} else {
|
||||||
|
server.appendonly_current_size = sb.st_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* A background append only file rewriting (BGREWRITEAOF) terminated its work.
|
/* A background append only file rewriting (BGREWRITEAOF) terminated its work.
|
||||||
* Handle this. */
|
* Handle this. */
|
||||||
void backgroundRewriteDoneHandler(int statloc) {
|
void backgroundRewriteDoneHandler(int statloc) {
|
||||||
@ -692,6 +714,8 @@ void backgroundRewriteDoneHandler(int statloc) {
|
|||||||
if (server.appendfsync != APPENDFSYNC_NO) aof_fsync(fd);
|
if (server.appendfsync != APPENDFSYNC_NO) aof_fsync(fd);
|
||||||
server.appendseldb = -1; /* Make sure it will issue SELECT */
|
server.appendseldb = -1; /* Make sure it will issue SELECT */
|
||||||
redisLog(REDIS_NOTICE,"The new append only file was selected for future appends.");
|
redisLog(REDIS_NOTICE,"The new append only file was selected for future appends.");
|
||||||
|
aofUpdateCurrentSize();
|
||||||
|
server.auto_aofrewrite_base_size = server.appendonly_current_size;
|
||||||
} else {
|
} else {
|
||||||
/* If append only is disabled we just generate a dump in this
|
/* If append only is disabled we just generate a dump in this
|
||||||
* format. Why not? */
|
* format. Why not? */
|
||||||
|
28
src/config.c
28
src/config.c
@ -232,6 +232,18 @@ void loadServerConfig(char *filename) {
|
|||||||
err = "argument must be 'no', 'always' or 'everysec'";
|
err = "argument must be 'no', 'always' or 'everysec'";
|
||||||
goto loaderr;
|
goto loaderr;
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(argv[0],"auto-aof-rewrite-percentage") &&
|
||||||
|
argc == 2)
|
||||||
|
{
|
||||||
|
server.auto_aofrewrite_perc = atoi(argv[1]);
|
||||||
|
if (server.auto_aofrewrite_perc < 0) {
|
||||||
|
err = "Invalid negative percentage for AOF auto rewrite";
|
||||||
|
goto loaderr;
|
||||||
|
}
|
||||||
|
} else if (!strcasecmp(argv[0],"auto-aof-rewrite-min-size") &&
|
||||||
|
argc == 2)
|
||||||
|
{
|
||||||
|
server.auto_aofrewrite_min_size = memtoll(argv[1],NULL);
|
||||||
} else if (!strcasecmp(argv[0],"requirepass") && argc == 2) {
|
} else if (!strcasecmp(argv[0],"requirepass") && argc == 2) {
|
||||||
server.requirepass = zstrdup(argv[1]);
|
server.requirepass = zstrdup(argv[1]);
|
||||||
} else if (!strcasecmp(argv[0],"pidfile") && argc == 2) {
|
} else if (!strcasecmp(argv[0],"pidfile") && argc == 2) {
|
||||||
@ -406,6 +418,12 @@ void configSetCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-percentage")) {
|
||||||
|
if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
|
||||||
|
server.auto_aofrewrite_perc = ll;
|
||||||
|
} else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-min-size")) {
|
||||||
|
if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;
|
||||||
|
server.auto_aofrewrite_min_size = ll;
|
||||||
} else if (!strcasecmp(c->argv[2]->ptr,"save")) {
|
} else if (!strcasecmp(c->argv[2]->ptr,"save")) {
|
||||||
int vlen, j;
|
int vlen, j;
|
||||||
sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen);
|
sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen);
|
||||||
@ -592,6 +610,16 @@ void configGetCommand(redisClient *c) {
|
|||||||
sdsfree(buf);
|
sdsfree(buf);
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
|
if (stringmatch(pattern,"auto-aof-rewrite-percentage",0)) {
|
||||||
|
addReplyBulkCString(c,"auto-aof-rewrite-percentage");
|
||||||
|
addReplyBulkLongLong(c,server.auto_aofrewrite_perc);
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
if (stringmatch(pattern,"auto-aof-rewrite-min-size",0)) {
|
||||||
|
addReplyBulkCString(c,"auto-aof-rewrite-min-size");
|
||||||
|
addReplyBulkLongLong(c,server.auto_aofrewrite_min_size);
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
if (stringmatch(pattern,"slave-serve-stale-data",0)) {
|
if (stringmatch(pattern,"slave-serve-stale-data",0)) {
|
||||||
addReplyBulkCString(c,"slave-serve-stale-data");
|
addReplyBulkCString(c,"slave-serve-stale-data");
|
||||||
addReplyBulkCString(c,server.repl_serve_stale_data ? "yes" : "no");
|
addReplyBulkCString(c,server.repl_serve_stale_data ? "yes" : "no");
|
||||||
|
6
src/db.c
6
src/db.c
@ -298,9 +298,9 @@ void saveCommand(redisClient *c) {
|
|||||||
void bgsaveCommand(redisClient *c) {
|
void bgsaveCommand(redisClient *c) {
|
||||||
if (server.bgsavechildpid != -1) {
|
if (server.bgsavechildpid != -1) {
|
||||||
addReplyError(c,"Background save already in progress");
|
addReplyError(c,"Background save already in progress");
|
||||||
return;
|
} else if (server.bgrewritechildpid != -1) {
|
||||||
}
|
addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");
|
||||||
if (rdbSaveBackground(server.dbfilename) == REDIS_OK) {
|
} else if (rdbSaveBackground(server.dbfilename) == REDIS_OK) {
|
||||||
addReplyStatus(c,"Background saving started");
|
addReplyStatus(c,"Background saving started");
|
||||||
} else {
|
} else {
|
||||||
addReply(c,shared.err);
|
addReply(c,shared.err);
|
||||||
|
41
src/redis.c
41
src/redis.c
@ -589,6 +589,14 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
|||||||
if ((server.maxidletime && !(loops % 100)) || server.bpop_blocked_clients)
|
if ((server.maxidletime && !(loops % 100)) || server.bpop_blocked_clients)
|
||||||
closeTimedoutClients();
|
closeTimedoutClients();
|
||||||
|
|
||||||
|
/* Start a scheduled AOF rewrite if this was requested by the user while
|
||||||
|
* a BGSAVE was in progress. */
|
||||||
|
if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1 &&
|
||||||
|
server.aofrewrite_scheduled)
|
||||||
|
{
|
||||||
|
rewriteAppendOnlyFileBackground();
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if a background saving or AOF rewrite in progress terminated */
|
/* Check if a background saving or AOF rewrite in progress terminated */
|
||||||
if (server.bgsavechildpid != -1 || server.bgrewritechildpid != -1) {
|
if (server.bgsavechildpid != -1 || server.bgrewritechildpid != -1) {
|
||||||
int statloc;
|
int statloc;
|
||||||
@ -603,9 +611,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
|||||||
updateDictResizePolicy();
|
updateDictResizePolicy();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
/* If there is not a background saving in progress check if
|
/* If there is not a background saving in progress check if
|
||||||
* we have to save now */
|
* we have to save now */
|
||||||
time_t now = time(NULL);
|
|
||||||
for (j = 0; j < server.saveparamslen; j++) {
|
for (j = 0; j < server.saveparamslen; j++) {
|
||||||
struct saveparam *sp = server.saveparams+j;
|
struct saveparam *sp = server.saveparams+j;
|
||||||
|
|
||||||
@ -617,6 +626,21 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Trigger an AOF rewrite if needed */
|
||||||
|
if (server.bgsavechildpid == -1 &&
|
||||||
|
server.bgrewritechildpid == -1 &&
|
||||||
|
server.auto_aofrewrite_perc &&
|
||||||
|
server.appendonly_current_size > server.auto_aofrewrite_min_size)
|
||||||
|
{
|
||||||
|
int base = server.auto_aofrewrite_base_size ?
|
||||||
|
server.auto_aofrewrite_base_size : 1;
|
||||||
|
long long growth = (server.appendonly_current_size*100/base);
|
||||||
|
if (growth >= server.auto_aofrewrite_perc) {
|
||||||
|
redisLog(REDIS_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth);
|
||||||
|
rewriteAppendOnlyFileBackground();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expire a few keys per cycle, only if this is a master.
|
/* Expire a few keys per cycle, only if this is a master.
|
||||||
@ -780,6 +804,10 @@ void initServerConfig() {
|
|||||||
server.appendonly = 0;
|
server.appendonly = 0;
|
||||||
server.appendfsync = APPENDFSYNC_EVERYSEC;
|
server.appendfsync = APPENDFSYNC_EVERYSEC;
|
||||||
server.no_appendfsync_on_rewrite = 0;
|
server.no_appendfsync_on_rewrite = 0;
|
||||||
|
server.auto_aofrewrite_perc = REDIS_AUTO_AOFREWRITE_PERC;
|
||||||
|
server.auto_aofrewrite_min_size = REDIS_AUTO_AOFREWRITE_MIN_SIZE;
|
||||||
|
server.auto_aofrewrite_base_size = 0;
|
||||||
|
server.aofrewrite_scheduled = 0;
|
||||||
server.lastfsync = time(NULL);
|
server.lastfsync = time(NULL);
|
||||||
server.appendfd = -1;
|
server.appendfd = -1;
|
||||||
server.appendseldb = -1; /* Make sure the first time will not match */
|
server.appendseldb = -1; /* Make sure the first time will not match */
|
||||||
@ -1255,6 +1283,17 @@ sds genRedisInfoString(void) {
|
|||||||
server.vm_enabled != 0,
|
server.vm_enabled != 0,
|
||||||
server.masterhost == NULL ? "master" : "slave"
|
server.masterhost == NULL ? "master" : "slave"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (server.appendonly) {
|
||||||
|
info = sdscatprintf(info,
|
||||||
|
"aof_current_size:%lld\r\n"
|
||||||
|
"aof_base_size:%lld\r\n"
|
||||||
|
"aof_pending_rewrite:%d\r\n",
|
||||||
|
(long long) server.appendonly_current_size,
|
||||||
|
(long long) server.auto_aofrewrite_base_size,
|
||||||
|
server.aofrewrite_scheduled);
|
||||||
|
}
|
||||||
|
|
||||||
if (server.masterhost) {
|
if (server.masterhost) {
|
||||||
info = sdscatprintf(info,
|
info = sdscatprintf(info,
|
||||||
"master_host:%s\r\n"
|
"master_host:%s\r\n"
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
#define REDIS_SHARED_INTEGERS 10000
|
#define REDIS_SHARED_INTEGERS 10000
|
||||||
#define REDIS_REPLY_CHUNK_BYTES (5*1500) /* 5 TCP packets with default MTU */
|
#define REDIS_REPLY_CHUNK_BYTES (5*1500) /* 5 TCP packets with default MTU */
|
||||||
#define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */
|
#define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */
|
||||||
|
#define REDIS_AUTO_AOFREWRITE_PERC 100
|
||||||
|
#define REDIS_AUTO_AOFREWRITE_MIN_SIZE (1024*1024)
|
||||||
|
|
||||||
/* Hash table parameters */
|
/* Hash table parameters */
|
||||||
#define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */
|
#define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */
|
||||||
@ -410,6 +412,11 @@ struct redisServer {
|
|||||||
int appendonly;
|
int appendonly;
|
||||||
int appendfsync;
|
int appendfsync;
|
||||||
int no_appendfsync_on_rewrite;
|
int no_appendfsync_on_rewrite;
|
||||||
|
int auto_aofrewrite_perc; /* Rewrite AOF if % growth is > M and... */
|
||||||
|
off_t auto_aofrewrite_min_size; /* the AOF file is at least N bytes. */
|
||||||
|
off_t auto_aofrewrite_base_size;/* AOF size on latest startup or rewrite. */
|
||||||
|
off_t appendonly_current_size; /* AOF current size. */
|
||||||
|
int aofrewrite_scheduled; /* Rewrite once BGSAVE terminates. */
|
||||||
int shutdown_asap;
|
int shutdown_asap;
|
||||||
time_t lastfsync;
|
time_t lastfsync;
|
||||||
int appendfd;
|
int appendfd;
|
||||||
|
Reference in New Issue
Block a user