diff --git a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php index 4bcaaddb01..0f541a2603 100644 --- a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php @@ -149,7 +149,11 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter { $lua = <<<'EOLUA' local v = redis.call('GET', KEYS[1]) - redis.call('DEL', KEYS[1]) + local e = redis.pcall('UNLINK', KEYS[1]) + + if type(e) ~= 'number' then + redis.call('DEL', KEYS[1]) + end if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then return '' diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 7910f95c40..f178669858 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Traits; +use Predis\Command\Redis\UNLINK; use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\RedisCluster; use Predis\Response\Status; @@ -363,7 +364,8 @@ trait RedisTrait // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS // can hang your server when it is executed against large databases (millions of items). // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above. - $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; + $unlink = version_compare($info['redis_version'], '4.0', '>=') ? 'UNLINK' : 'DEL'; + $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('$unlink',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $evalArgs[0], $evalArgs[1]) && $cleared; continue; } @@ -393,12 +395,27 @@ trait RedisTrait } if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { - $this->pipeline(function () use ($ids) { + static $del; + $del = $del ?? (class_exists(UNLINK::class) ? 'unlink' : 'del'); + + $this->pipeline(function () use ($ids, $del) { foreach ($ids as $id) { - yield 'del' => [$id]; + yield $del => [$id]; } })->rewind(); } else { + static $unlink = true; + + if ($unlink) { + try { + $this->redis->unlink($ids); + + return true; + } catch (\Throwable $e) { + $unlink = false; + } + } + $this->redis->del($ids); } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php index 180f63fdf7..756a48808e 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php @@ -89,6 +89,18 @@ class RedisSessionHandler extends AbstractSessionHandler */ protected function doDestroy(string $sessionId): bool { + static $unlink = true; + + if ($unlink) { + try { + $this->redis->unlink($this->prefix.$sessionId); + + return true; + } catch (\Throwable $e) { + $unlink = false; + } + } + $this->redis->del($this->prefix.$sessionId); return true; diff --git a/src/Symfony/Component/Messenger/Bridge/Redis/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Redis/Transport/Connection.php index 984b03f82c..45e301b170 100644 --- a/src/Symfony/Component/Messenger/Bridge/Redis/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Redis/Transport/Connection.php @@ -460,6 +460,19 @@ class Connection public function cleanup(): void { + static $unlink = true; + + if ($unlink) { + try { + $this->connection->unlink($this->stream); + $this->connection->unlink($this->queue); + + return; + } catch (\Throwable $e) { + $unlink = false; + } + } + $this->connection->del($this->stream); $this->connection->del($this->queue); }