Skip to content

[Cache] Redis Sentinel only attempting connection via first host with PHP Redis extension #51570

@digilist

Description

@digilist

Symfony version(s) affected

>= 5.4

Description

#47003 added support for using multiple Redis Sentinel hosts. However, if the first Sentinel host cannot be resolved (e.g. because a DNS name cannot be resolved or because the server is not responding), a \RedisException is thrown and the code does not try to connect to the other Sentinel hosts.

In this code block, it tries to connect to Sentinel and resolve the master address:

$sentinel = new $sentinelClass($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra);
if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) {
[$host, $port] = $address;
}

The call to getMasterAddrByName() is throwing the RedisException and will prevent any attempt to connect to other Sentinel hosts.

This exception is thrown if the hostname cannot be resolved:

 RedisException {#407 ▼
  #message: "Redis server sentinel1:26379 went away"
  #code: 0
  #file: "/srv/www/vendor/symfony/cache/Traits/RedisTrait.php"
  #line: 231
  -previous: ErrorException {#408 ▼
    #message: "Warning: RedisSentinel::getMasterAddrByName(): php_network_getaddresses: getaddrinfo for sentinel1 failed: Name or service not known"
    #code: 0
    #file: "/srv/www/vendor/symfony/cache/Traits/RedisTrait.php"
    #line: 231
    #severity: E_WARNING
    trace: {▶}
  }
  trace: {▶}
}

And this exception if the server port is invalid (no previous exception in this case):

 RedisException {#408 ▼
  #message: "Redis server redis:16379 went away"
  #code: 0
  #file: "/srv/www/vendor/symfony/cache/Traits/RedisTrait.php"
  #line: 231
  trace: {▶}
}

How to reproduce

You could use this environment variable / DSN to observe the behavior with invalid host names at first and valid host names afterwards:

REDIS_DSN=redis:?host[sentinel1:26379]&host[sentinel2:26379]&host[sentinel3:26379]&redis_sentinel=db

If you have a Redis Sentinel instance running, just add the host as second (or later) and observe that nothing is written into your Redis instance.

If you do not have a Redis Sentinel instance running, the same behavior can be verified by adding an exit statement after the if-block from the code snippet above. The code will not terminate, since it never reaches that statement.

Possible Solution

The call to getMasterAddrByName() could be wrapped in a simple try...catch to suppress any error.

I am not sure if there are valid errors that should not be caught. In that case, the exception message could be checked for specific errors.

Additional Context

I haven't investigated how this behaves with Relay.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy