-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
Summary
Currently, RedisSentinel accepts only a single host, requiring users to manually implement failover logic across multiple Sentinel instances. This defeats the purpose of Sentinel as a high-availability solution, since a single Sentinel node is itself a single point of failure.
This was previously raised in #2132, where the maintainer confirmed: "current implementation doesn't imply multiple sentinel nodes so you have to manage them by yourself."
I'd like to propose a concrete implementation and would appreciate feedback on the API design before opening a PR.
Proposed API
Backward-compatible — the current single-host usage continues to work unchanged.
// Current (unchanged)
$sentinel = new RedisSentinel(['host' => '10.0.0.1', 'port' => 26379]);
// New: multiple hosts with automatic failover
$sentinel = new RedisSentinel([
'host' => [
['host' => '10.0.0.1', 'port' => 26379],
['host' => '10.0.0.2', 'port' => 26379],
['host' => '10.0.0.3', 'port' => 26379],
],
'timeout' => 0.1,
'password' => 'secret',
]);
// Automatically tries the next Sentinel if the current one is unreachable
$master = $sentinel->getMasterAddrByName('mymaster');Proposed behavior
- On construction, connect to the first available Sentinel from the
hostarray - If the connected Sentinel becomes unreachable during a command, iterate through the remaining hosts and reconnect
- If no Sentinel is reachable, throw
RedisException(same as current behavior with a single unreachable host) - When
hostis a string (current usage), behavior is identical to today - no BC break
Implementation approach
Changes would be limited to:
redis_sentinel.c(__construct) - detect array-of-arrays inhost, store the host listsentinel_library.c- add asentinel_connect_next()helper that iterates through hostsREDIS_PROCESS_KW_CMDmacro path - wrap command execution with retry-on-disconnect logic that callssentinel_connect_next()
The existing redis_sock_create / redis_sock_connect / redis_sock_disconnect infrastructure can be reused - no new socket-level code needed.
Estimated scope: ~150-250 lines of C code + tests.
Why this matters
- predis supports multi-host Sentinel natively - it's the primary reason many users stay on predis instead of phpredis (as noted in Support for multiple Redis Sentinels #2132)
- Frameworks like Laravel could then offer phpredis + Sentinel as a first-class option
- The laravel-redis-sentinel package exists solely to work around this limitation at the PHP level
Questions for maintainers
- Is overloading the
hostoption (string vs array-of-arrays) acceptable, or would you prefer a separate option likehosts? - Should retry behavior be configurable (e.g.
retryInterval,maxRetries) or is simple iterate-and-fail sufficient? - Any concerns with the general approach?
Happy to submit a PR once we align on the design. Thanks!