]> git.saurik.com Git - redis.git/commitdiff
More incremental active expired keys collection process.
authorantirez <antirez@gmail.com>
Fri, 11 May 2012 17:17:31 +0000 (19:17 +0200)
committerantirez <antirez@gmail.com>
Sat, 12 May 2012 07:33:24 +0000 (09:33 +0200)
If a large amonut of keys are all expiring about at the same time, the
"active" expired keys collection cycle used to block as far as the
percentage of already expired keys was >= 25% of the total population of
keys with an expire set.

This could block the server even for many seconds in order to reclaim
memory ASAP. The new algorithm uses at max a small amount of
milliseconds per cycle, even if this means reclaiming the memory less
promptly it also means a more responsive server.

src/redis.c
src/redis.h

index 0a12ccd2e2ee38f2696ca3f4380d67fd39909475..4cc378e24a40d2de7d4955e6bd303147c1a1a548 100644 (file)
@@ -609,9 +609,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%
@@ -640,6 +641,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);
     }
 }
index 281c087878908b028e69acc9a67e4b979359a9e8..b842b5f79057772f5d1b4e2e64f8724ac3e127d6 100644 (file)
@@ -43,6 +43,7 @@
 #define REDIS_DEFAULT_DBNUM     16
 #define REDIS_CONFIGLINE_MAX    1024
 #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_SHARED_SELECT_CMDS 10
 #define REDIS_SHARED_INTEGERS 10000