diff options
author | xiaost <xiaost7@gmail.com> | 2014-09-09 17:53:30 +0800 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2014-09-10 09:58:20 +0200 |
commit | 8375a6d0aa3814bfbb1f00efedf0e8df36b048d7 (patch) | |
tree | f0613da79a06ee9a54bcdbed4548db6782a17d84 | |
parent | 55024e9a9a28eb8981b357e3ccac2c52c79704f7 (diff) | |
download | redis-8375a6d0aa3814bfbb1f00efedf0e8df36b048d7.tar.gz |
Limit the *SCAN command `dictScan` iterations
*SCAN will cause redis server to hang for seconds
after millions of keys was deleted by SCAN/DEL pairs
-rw-r--r-- | src/db.c | 9 |
1 files changed, 8 insertions, 1 deletions
@@ -483,6 +483,11 @@ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) { if (ht) { void *privdata[2]; + /* We set the max number of iterations to ten times the specified + * COUNT, so if the hash table is in a pathological state (very + * sparsely populated) we avoid to block too much time at the cost + * of returning no or very few elements. */ + long maxiterations = count*10; /* We pass two pointers to the callback: the list to which it will * add new elements, and the object containing the dictionary so that @@ -491,7 +496,9 @@ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) { privdata[1] = o; do { cursor = dictScan(ht, cursor, scanCallback, privdata); - } while (cursor && listLength(keys) < (unsigned long)count); + } while (cursor && + maxiterations-- && + listLength(keys) < (unsigned long)count); } else if (o->type == REDIS_SET) { int pos = 0; int64_t ll; |