Skip to content

Proposal: Native multi-host support for RedisSentinel #2819

@nikamodis

Description

@nikamodis

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

  1. On construction, connect to the first available Sentinel from the host array
  2. If the connected Sentinel becomes unreachable during a command, iterate through the remaining hosts and reconnect
  3. If no Sentinel is reachable, throw RedisException (same as current behavior with a single unreachable host)
  4. When host is 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 in host, store the host list
  • sentinel_library.c - add a sentinel_connect_next() helper that iterates through hosts
  • REDIS_PROCESS_KW_CMD macro path - wrap command execution with retry-on-disconnect logic that calls sentinel_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

  1. Is overloading the host option (string vs array-of-arrays) acceptable, or would you prefer a separate option like hosts?
  2. Should retry behavior be configurable (e.g. retryInterval, maxRetries) or is simple iterate-and-fail sufficient?
  3. Any concerns with the general approach?

Happy to submit a PR once we align on the design. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions