Replication, Sentinel and Cluster
Three different things that all get called “Redis HA”, solving three different problems. Naming which one you mean is most of the answer.
| Solves | |
|---|---|
| Replication | read scaling, and a warm copy |
| Sentinel | automatic failover of one primary |
| Cluster | sharding across many primaries |
Replication is asynchronous, and that is the whole story
A primary streams writes to replicas without waiting for them. So a replica is behind by some amount, and a failover promotes a replica that may be missing the last writes — acknowledged writes, already returned to the client.
redis-cli INFO replication
# master_repl_offset:88431
# slave0:...,offset=88402,lag=0 <- 29 bytes behindWAIT numreplicas timeout blocks until N replicas have acknowledged, which
narrows the window without closing it. It is not a transaction and it is not a
guarantee — if the timeout expires it returns the count it reached and the
write still stands.
Replicas are read-only by default. Reading from them scales reads and buys stale data, which is the same trade as Replication and Logical Decoding.
Sentinel: failover without sharding
Sentinel processes monitor the primary and agree, by quorum, when it is gone. One replica is promoted, the others reconfigured, and clients are told the new address.
sentinel monitor mymaster 10.0.0.1 6379 2 # 2 sentinels must agree
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000Two facts that decide whether it works:
- Run at least three Sentinels, on separate hosts. Two cannot form a majority when one dies, which is the entire point.
- The client must be Sentinel-aware. It asks a Sentinel for the current primary rather than holding an address:
from redis.sentinel import Sentinel
sentinel = Sentinel([("s1", 26379), ("s2", 26379), ("s3", 26379)])
r = sentinel.master_for("mymaster", socket_timeout=0.5)A client configured with the primary’s IP does not fail over. It reconnects
happily to a demoted replica and every write fails with READONLY.
Cluster: sharding, and the constraints it imposes
Cluster shards the keyspace across 16,384 hash slots, each owned by one
primary. CRC16(key) mod 16384 picks the slot, the client caches the map, and
a moved slot answers MOVED so the client refreshes.
The constraint that changes your code: multi-key operations only work when the keys are in the same slot.
# CROSSSLOT error — three keys, probably three slots.
r.mget("user:1", "user:2", "user:3")
# Hash tags: only the braces are hashed, so these co-locate.
r.mget("user:{1}:name", "user:{1}:email")The same applies to transactions, Lua scripts touching several keys, and
SUNION. Hash tags fix it and create the next problem — everything tagged
{tenant_42} lives on one node, so a large tenant becomes a hot shard.
Gotcha: Cluster is not the default answer to “we need more Redis”. A single instance handles very high throughput, and Cluster costs you multi-key operations, cross-slot transactions and operational complexity. Reach for it when the dataset exceeds one machine’s memory, not when throughput feels high.
Failing over well
What actually determines the outcome:
- Client timeouts must be short.
socket_timeoutin seconds, not tens of seconds — a failover completes in under a minute and the client should notice in one second, not thirty. - Retry on connection errors, or every in-flight request during the window surfaces to users as an error while the cluster is already healthy.
- The application must survive Redis being gone. A cache-aside read that raises rather than falling through to the database turns a cache blip into an outage.
r = redis.Redis(
socket_timeout=1, socket_connect_timeout=1,
retry=Retry(ExponentialBackoff(), retries=3),
retry_on_error=[ConnectionError, TimeoutError],
)That third point is the senior answer, and it is the one people leave out.
Related
Interview angle 6
- “How do you make Redis highly available?” - name which problem: replication for read scaling and a warm copy, Sentinel for automatic failover of a single primary, Cluster for sharding across primaries. They are three different things and only Cluster shards.
- “What can you lose in a failover?” - acknowledged writes. Replication is asynchronous, so a promoted replica may be behind.
WAITnarrows the window by blocking until N replicas acknowledge, but it is not a guarantee and it still returns after a timeout. - “How many Sentinels?” - at least three, on separate hosts, because two cannot form a majority when one fails. And the client must be Sentinel-aware; one pointed at the primary’s IP reconnects to a demoted replica and every write fails
READONLY. - “What breaks when you move to Cluster?” - multi-key operations across slots.
MGET, transactions and multi-key Lua all fail withCROSSSLOTunless hash tags co-locate the keys — and hash tags then concentrate one tenant on one node. - “When do you actually need Cluster?” - when the dataset exceeds one machine’s memory. Not for throughput: a single instance sustains very high command rates, and Cluster costs you multi-key operations and real operational complexity.
- “A failover completes in 30 seconds and users saw errors for five minutes. Why?” - the client. Long socket timeouts and no retry on connection errors mean it keeps a dead connection long after the cluster recovered.