Skip to content

Commit

Permalink
feature #31437 [Cache] Add Redis Sentinel support (StephenClouse)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 4.4-dev branch (closes #31437).

Discussion
----------

[Cache] Add Redis Sentinel support

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        | symfony/symfony-docs#11545

This change adds support for Redis Sentinel clusters to the Cache component Redis adapter.

The DSN format is syntactically equivalent to cluster support, but adds a new parameter `redis_sentinel` that should be set to the sentinel service name.

This support requires the use of predis as the underlying connection library. The redis extension does not support sentinel at this time.

Commits
-------

80e8b21 [Cache] Add Redis Sentinel support
  • Loading branch information
nicolas-grekas committed May 22, 2019
2 parents 5239873 + 80e8b21 commit 63d7309
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Symfony/Component/Cache/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

4.4.0
-----

* added support for connecting to Redis Sentinel clusters

4.3.0
-----

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Cache\Tests\Adapter;

use Symfony\Component\Cache\Adapter\AbstractAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;

class RedisAdapterSentinelTest extends AbstractRedisAdapterTest
{
public static function setupBeforeClass()
{
if (!class_exists('Predis\Client')) {
self::markTestSkipped('The Predis\Client class is required.');
}
if (!$hosts = getenv('REDIS_SENTINEL_HOSTS')) {
self::markTestSkipped('REDIS_SENTINEL_HOSTS env var is not defined.');
}
if (!$service = getenv('REDIS_SENTINEL_SERVICE')) {
self::markTestSkipped('REDIS_SENTINEL_SERVICE env var is not defined.');
}

self::$redis = AbstractAdapter::createConnection('redis:?host['.str_replace(' ', ']&host[', $hosts).']', ['redis_sentinel' => $service]);
}

/**
* @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException
* @expectedExceptionMessage Invalid Redis DSN: cannot use both redis_cluster and redis_sentinel at the same time
*/
public function testInvalidDSNHasBothClusterAndSentinel()
{
$dsn = 'redis:?host[redis1]&host[redis2]&host[redis3]&redis_cluster=1&redis_sentinel=mymaster';
RedisAdapter::createConnection($dsn);
}
}
16 changes: 15 additions & 1 deletion src/Symfony/Component/Cache/Traits/RedisTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ trait RedisTrait
'tcp_keepalive' => 0,
'lazy' => null,
'redis_cluster' => false,
'redis_sentinel' => null,
'dbindex' => 0,
'failover' => 'none',
];
Expand Down Expand Up @@ -146,9 +147,13 @@ public static function createConnection($dsn, array $options = [])
throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn));
}

if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class)) {
throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package: %s', $dsn));
}

$params += $query + $options + self::$defaultConnectionOptions;

if (null === $params['class'] && \extension_loaded('redis')) {
if (null === $params['class'] && !isset($params['redis_sentinel']) && \extension_loaded('redis')) {
$class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class);
} else {
$class = null === $params['class'] ? \Predis\Client::class : $params['class'];
Expand Down Expand Up @@ -246,6 +251,12 @@ public static function createConnection($dsn, array $options = [])
} elseif (is_a($class, \Predis\Client::class, true)) {
if ($params['redis_cluster']) {
$params['cluster'] = 'redis';
if (isset($params['redis_sentinel'])) {
throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: %s', $dsn));
}
} elseif (isset($params['redis_sentinel'])) {
$params['replication'] = 'sentinel';
$params['service'] = $params['redis_sentinel'];
}
$params += ['parameters' => []];
$params['parameters'] += [
Expand All @@ -268,6 +279,9 @@ public static function createConnection($dsn, array $options = [])
}

$redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions));
if (isset($params['redis_sentinel'])) {
$redis->getConnection()->setSentinelTimeout($params['timeout']);
}
} elseif (class_exists($class, false)) {
throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster" nor "Predis\Client".', $class));
} else {
Expand Down

0 comments on commit 63d7309

Please sign in to comment.