8000 [Cache] Use SCAN instead of KEYS with Redis >= 2.8 · symfony/symfony@aadeb11 · GitHub
[go: up one dir, main page]

Skip to content

Commit aadeb11

Browse files
[Cache] Use SCAN instead of KEYS with Redis >= 2.8
1 parent 49a2cb8 commit aadeb11

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

src/Symfony/Component/Cache/Adapter/RedisAdapter.php

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ protected function doClear($namespace)
165165
// When using a native Redis cluster, clearing the cache cannot work and always returns false.
166166
// Clearing the cache should then be done by any other means (e.g. by restarting the cluster).
167167

168+
$cleared = true;
168169
$hosts = array($this->redis);
169170
$evalArgs = array(array($namespace), 0);
170171

@@ -181,6 +182,7 @@ protected function doClear($namespace)
181182
return false;
182183
}
183184
} elseif ($this->redis instanceof \RedisArray) {
185+
$hosts = array();
184186
foreach ($this->redis->_hosts() as $host) {
185187
$hosts[] = $this->redis->_instance($host);
186188
}
@@ -189,17 +191,35 @@ protected function doClear($namespace)
189191
}
190192
foreach ($hosts as $host) {
191193
if (!isset($namespace[0])) {
192-
$host->flushDb();
193-
} else {
194+
$cleared = $host->flushDb() && $cleared;
195+
continue;
196+
}
197+
198+
$info = $host->info('Server');
199+
$info = isset($info['Server']) ? $info['Server'] : $info;
200+
201+
if (!version_compare($info['redis_version'], '2.8', '>=')) {
194202
// As documented in Redis documentation (http://redis.io/commands/keys) using KEYS
195203
// can hang your server when it is executed against large databases (millions of items).
196-
// Whenever you hit this scale, it is advised to deploy one Redis database per cache pool
197-
// instead of using namespaces, so that FLUSHDB is used instead.
198-
$host->eval("local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end", $evalArgs[0], $evalArgs[1]);
204+
// Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above.
205+
$cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $evalArgs[0], $evalArgs[1]) && $cleared;
206+
continue;
199207
}
208+
209+
$cursor = null;
210+
do {
211+
$keys = $host instanceof \Predis\Client ? $host->scan($cursor, 'MATCH', $namespace.'*', 'COUNT', 1000) : $host->scan($cursor, $namespace.'*', 1000);
212+
if (isset($keys[1]) && is_array($keys[1])) {
213+
$cursor = $keys[0];
214+
$keys = $keys[1];
215+
}
216+
if ($keys) {
217+
$host->del($keys);
218+
}
219+
} while ($cursor = (int) $cursor);
200220
}
201221

202-
return true;
222+
return $cleared;
203223
}
204224

205225
/**

0 commit comments

Comments
 (0)
0