diff --git a/redis.conf b/redis.conf index 4760f291..2b4b6479 100644 --- a/redis.conf +++ b/redis.conf @@ -93,6 +93,21 @@ save 900 1 save 300 10 save 60 10000 +# By default Redis will stop accepting writes if RDB snapshots are enabled +# (at least one save point) and the latest background save failed. +# This will make the user aware (in an hard way) that data is not persisting +# on disk properly, otherwise chances are that no one will notice and some +# distater will happen. +# +# If the background saving process will start working again Redis will +# automatically allow writes again. +# +# However if you have setup your proper monitoring of the Redis server +# and persistence, you may want to disable this feature so that Redis will +# continue to work as usually even if there are problems with disk, +# permissions, and so forth. +stop-writes-on-bgsave-error yes + # Compress string objects using LZF when dump .rdb databases? # For default that's set to 'yes' as it's almost always a win. # If you want to save some CPU in the saving child set it to 'no' but diff --git a/src/config.c b/src/config.c index 9d28d678..6befca8f 100644 --- a/src/config.c +++ b/src/config.c @@ -336,6 +336,11 @@ void loadServerConfigFromString(char *config) { server.client_obuf_limits[class].hard_limit_bytes = hard; server.client_obuf_limits[class].soft_limit_bytes = soft; server.client_obuf_limits[class].soft_limit_seconds = soft_seconds; + } else if (!strcasecmp(argv[0],"stop-writes-on-bgsave-error") && + argc == 2) { + if ((server.stop_writes_on_bgsave_err = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } } else { err = "Bad directive or wrong number of arguments"; goto loaderr; } @@ -604,7 +609,11 @@ void configSetCommand(redisClient *c) { server.client_obuf_limits[class].soft_limit_seconds = soft_seconds; } sdsfreesplitres(v,vlen); + } else if (!strcasecmp(c->argv[2]->ptr,"stop-writes-on-bgsave-error")) { + int yn = yesnotoi(o->ptr); + if (yn == -1) goto badfmt; + server.stop_writes_on_bgsave_err = yn; } else { addReplyErrorFormat(c,"Unsupported CONFIG parameter: %s", (char*)c->argv[2]->ptr); @@ -822,6 +831,11 @@ void configGetCommand(redisClient *c) { sdsfree(buf); matches++; } + if (stringmatch(pattern,"stop-writes-on-bgsave-error",0)) { + addReplyBulkCString(c,"stop-writes-on-bgsave-error"); + addReplyBulkCString(c,server.stop_writes_on_bgsave_err ? "yes" : "no"); + matches++; + } setDeferredMultiBulkLength(c,replylen,matches*2); } diff --git a/src/redis.c b/src/redis.c index 3dfef024..01ec0531 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1091,6 +1091,7 @@ void initServer() { server.stat_rejected_conn = 0; server.unixtime = time(NULL); server.lastbgsave_status = REDIS_OK; + server.stop_writes_on_bgsave_err = 1; aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL); if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE, acceptTcpHandler,NULL) == AE_ERR) oom("creating file event"); @@ -1378,7 +1379,9 @@ int processCommand(redisClient *c) { } /* Don't accept write commands if there are problems persisting on disk. */ - if (server.saveparamslen > 0 && server.lastbgsave_status == REDIS_ERR && + if (server.stop_writes_on_bgsave_err && + server.saveparamslen > 0 + && server.lastbgsave_status == REDIS_ERR && c->cmd->flags & REDIS_CMD_WRITE) { addReply(c, shared.bgsaveerr); diff --git a/src/redis.h b/src/redis.h index daaf362f..fdf7f08d 100644 --- a/src/redis.h +++ b/src/redis.h @@ -637,6 +637,7 @@ struct redisServer { int rdb_compression; /* Use compression in RDB? */ time_t lastsave; /* Unix time of last save succeeede */ int lastbgsave_status; /* REDIS_OK or REDIS_ERR */ + int stop_writes_on_bgsave_err; /* Don't allow writes if can't BGSAVE */ /* Propagation of commands in AOF / replication */ redisOpArray also_propagate; /* Additional command to propagate. */ /* Logging */