diff --git a/src/redis.c b/src/redis.c index 9e3ab66e..4a2e0fdb 100644 --- a/src/redis.c +++ b/src/redis.c @@ -480,9 +480,10 @@ void updateDictResizePolicy(void) { * keys that can be removed from the keyspace. */ void activeExpireCycle(void) { int j; + long long start = mstime(); for (j = 0; j < server.dbnum; j++) { - int expired; + int expired, iteration = 0; redisDb *db = server.db+j; /* Continue to expire if at the end of the cycle more than 25% @@ -511,6 +512,12 @@ void activeExpireCycle(void) { server.stat_expiredkeys++; } } + /* We can't block forever here even if there are many keys to + * expire. So after a given amount of milliseconds return to the + * caller waiting for the other active expire cycle. */ + iteration++; + if ((iteration & 0xff) == 0 && /* & 0xff is the same as % 255 */ + (mstime()-start) > REDIS_EXPIRELOOKUPS_TIME_LIMIT) return; } while (expired > REDIS_EXPIRELOOKUPS_PER_CRON/4); } } diff --git a/src/redis.h b/src/redis.h index f5e55f3a..86e78cac 100644 --- a/src/redis.h +++ b/src/redis.h @@ -45,6 +45,7 @@ #define REDIS_CONFIGLINE_MAX 1024 #define REDIS_MAX_SYNC_TIME 60 /* Slave can't take more to sync */ #define REDIS_EXPIRELOOKUPS_PER_CRON 10 /* lookup 10 expires per loop */ +#define REDIS_EXPIRELOOKUPS_TIME_LIMIT 25 /* Time limit in milliseconds */ #define REDIS_MAX_WRITE_PER_EVENT (1024*64) #define REDIS_REQUEST_MAX_SIZE (1024*1024*256) /* max bytes in inline command */ #define REDIS_SHARED_SELECT_CMDS 10