diff --git a/redis.conf b/redis.conf index a5062fda9..5f9eed7fe 100644 --- a/redis.conf +++ b/redis.conf @@ -1089,6 +1089,13 @@ replica-lazy-flush no lazyfree-lazy-user-del no +# FLUSHDB, FLUSHALL, and SCRIPT FLUSH support both asynchronous and synchronous +# deletion, which can be controlled by passing the [SYNC|ASYNC] flags into the +# commands. When neither flag is passed, this directive will be used to determine +# if the data should be deleted asynchronously. + +lazyfree-lazy-user-flush no + ################################ THREADED I/O ################################# # Redis is mostly single threaded, however there are certain threaded diff --git a/src/config.c b/src/config.c index 2e109dbae..2442ace8e 100644 --- a/src/config.c +++ b/src/config.c @@ -2385,6 +2385,7 @@ standardConfig configs[] = { createBoolConfig("lazyfree-lazy-expire", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_expire, 0, NULL, NULL), createBoolConfig("lazyfree-lazy-server-del", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_server_del, 0, NULL, NULL), createBoolConfig("lazyfree-lazy-user-del", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_user_del , 0, NULL, NULL), + createBoolConfig("lazyfree-lazy-user-flush", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_user_flush , 0, NULL, NULL), createBoolConfig("repl-disable-tcp-nodelay", NULL, MODIFIABLE_CONFIG, server.repl_disable_tcp_nodelay, 0, NULL, NULL), createBoolConfig("repl-diskless-sync", NULL, MODIFIABLE_CONFIG, server.repl_diskless_sync, 0, NULL, NULL), createBoolConfig("gopher-enabled", NULL, MODIFIABLE_CONFIG, server.gopher_enabled, 0, NULL, NULL), diff --git a/src/db.c b/src/db.c index 13126988f..29fef13fb 100644 --- a/src/db.c +++ b/src/db.c @@ -595,21 +595,23 @@ void signalFlushedDb(int dbid, int async) { /* Return the set of flags to use for the emptyDb() call for FLUSHALL * and FLUSHDB commands. * - * Currently the command just attempts to parse the "ASYNC" option. It - * also checks if the command arity is wrong. + * sync: flushes the database in an sync manner. + * async: flushes the database in an async manner. + * no option: determine sync or async according to the value of lazyfree-lazy-user-flush. * * On success C_OK is returned and the flags are stored in *flags, otherwise * C_ERR is returned and the function sends an error to the client. */ int getFlushCommandFlags(client *c, int *flags) { /* Parse the optional ASYNC option. */ - if (c->argc > 1) { - if (c->argc > 2 || strcasecmp(c->argv[1]->ptr,"async")) { - addReplyErrorObject(c,shared.syntaxerr); - return C_ERR; - } - *flags = EMPTYDB_ASYNC; - } else { + if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"sync")) { *flags = EMPTYDB_NO_FLAGS; + } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"async")) { + *flags = EMPTYDB_ASYNC; + } else if (c->argc == 1) { + *flags = server.lazyfree_lazy_user_flush ? EMPTYDB_ASYNC : EMPTYDB_NO_FLAGS; + } else { + addReplyErrorObject(c,shared.syntaxerr); + return C_ERR; } return C_OK; } diff --git a/src/lazyfree.c b/src/lazyfree.c index 8b9f0e2dc..f18b2027f 100644 --- a/src/lazyfree.c +++ b/src/lazyfree.c @@ -49,6 +49,14 @@ void lazyFreeTrackingTable(void *args[]) { atomicIncr(lazyfreed_objects,len); } +void lazyFreeLuaScripts(void *args[]) { + dict *lua_scripts = args[0]; + long long len = dictSize(lua_scripts); + dictRelease(lua_scripts); + atomicDecr(lazyfree_objects,len); + atomicIncr(lazyfreed_objects,len); +} + /* Return the number of currently pending objects to free. */ size_t lazyfreeGetPendingObjectsCount(void) { size_t aux; @@ -212,3 +220,13 @@ void freeTrackingRadixTreeAsync(rax *tracking) { atomicIncr(lazyfree_objects,tracking->numele); bioCreateLazyFreeJob(lazyFreeTrackingTable,1,tracking); } + +/* Free lua_scripts dict, if the dict is huge enough, free it in async way. */ +void freeLuaScriptsAsync(dict *lua_scripts) { + if (dictSize(lua_scripts) > LAZYFREE_THRESHOLD) { + atomicIncr(lazyfree_objects,dictSize(lua_scripts)); + bioCreateLazyFreeJob(lazyFreeLuaScripts,1,lua_scripts); + } else { + dictRelease(lua_scripts); + } +} diff --git a/src/scripting.c b/src/scripting.c index 75604e4d8..41469ee2e 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1282,14 +1282,17 @@ void scriptingInit(int setup) { /* Release resources related to Lua scripting. * This function is used in order to reset the scripting environment. */ -void scriptingRelease(void) { - dictRelease(server.lua_scripts); +void scriptingRelease(int async) { + if (async) + freeLuaScriptsAsync(server.lua_scripts); + else + dictRelease(server.lua_scripts); server.lua_scripts_mem = 0; lua_close(server.lua); } -void scriptingReset(void) { - scriptingRelease(); +void scriptingReset(int async) { + scriptingRelease(async); scriptingInit(0); } @@ -1711,8 +1714,12 @@ void scriptCommand(client *c) { " Set the debug mode for subsequent scripts executed.", "EXISTS [ ...]", " Return information about the existence of the scripts in the script cache.", -"FLUSH", +"FLUSH [ASYNC|SYNC]", " Flush the Lua scripts cache. Very dangerous on replicas.", +" When called without the optional mode argument, the behavior is determined by the", +" lazyfree-lazy-user-flush configuration directive. Valid modes are:", +" * ASYNC: Asynchronously flush the scripts cache.", +" * SYNC: Synchronously flush the scripts cache.", "KILL", " Kill the currently executing Lua script.", "LOAD