Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
digilist opened this issue Sep 5, 2023 · 0 comments · Fixed by #51598
Closed

Comments

@digilist
Copy link
Contributor

digilist commented Sep 5, 2023

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.

@digilist digilist added the Bug label Sep 5, 2023
nicolas-grekas added a commit that referenced this issue Sep 14, 2023
…irst one is not resolvable (digilist)

This PR was merged into the 5.4 branch.

Discussion
----------

[Cache] fix using multiple Redis Sentinel hosts when the first one is not resolvable

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #51570
| License       | MIT
| Doc PR        |

See ticket #51570 for details on this bugfix.

As mentioned in the ticket, I am not sure if it's wise to catch all exceptions or if it would be better to only check for specific ones. But since I cannot think about any reasons other than an unreachable host to raise any exception, I decided to catch all exceptions for now.

Commits
-------

578a152 [Cache] fix using multiple Redis Sentinel hosts when the first one is not resolvable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants