Lesson 0006 · Replication & scaling
Copying a primary to survive a dead machine — and the writes that async replication can lose.
Lesson 0005 made your data survive a restart. But a restart isn't the machine dying — a failed disk or a vanished cloud instance takes the whole process with it. Replication is the answer: keep a live copy on another machine. It's also where your idea from last lesson — "offload the snapshot to a replica" — comes true. The catch, and the whole point of this lesson, is that Redis replication is asynchronous by default, which buys speed at the price of a narrow window where an acknowledged write can vanish.
Redis uses "leader follower (master-replica) replication… It allows replica Redis instances to be exact copies of master instances." One primary, many replicas; a replica can even have its own sub-replicas (cascading). — Redis Docs — Replication
replica-read-only yes):
"Read-only replicas will reject all write commands." Writes go to the primary; reads
can fan out across replicas for throughput.Every primary has a replication ID and an offset that
increments for every byte of the replication stream — together they "identify an exact
version of the dataset." When a replica connects it runs PSYNC with its last
ID + offset, and one of two things happens:
| Resync | When | What happens |
|---|---|---|
| Partial | Brief disconnect; the primary still has the missed bytes in its backlog buffer. | Primary ships just the missing slice of the stream. Cheap. |
| Full | First sync, or the backlog no longer covers the gap. | Primary does a BGSAVE → RDB, streams it, then replays buffered writes. Expensive. |
Notice the callback to Lesson 0005: a full
resync is literally an RDB snapshot (with its fork() cost) streamed to the replica.
Diskless replication (repl-diskless-sync) optimizes this — "the
child process directly sends the RDB over the wire to replicas, without using the disk as
intermediate storage."
— Redis Docs — Replication
By default replication is asynchronous: "low latency and high performance… the natural replication mode for the vast majority of Redis use cases." The primary applies a write and acknowledges it to the client immediately — it does not wait for replicas to confirm. Replication happens in the background. — Redis Docs
Because the ack comes before replicas confirm, "acknowledged writes can still be lost during a failover." Picture it: the client gets OK → the primary crashes a millisecond later → a replica that never received that write is promoted to primary. The write is simply gone. "There is always a window for data loss." This is why Redis is not a strongly-consistent (CP) system. — Redis Docs
You can't eliminate the window, but you can narrow it:
| Tool | What it does | Guarantee |
|---|---|---|
WAIT n timeout |
Blocks until the current connection's writes are acknowledged by ≥ n replicas (or timeout). |
Best-effort — "does not make Redis a strongly consistent store." |
min-replicas-to-write +min-replicas-max-lag |
Primary refuses writes unless ≥ N replicas are connected with lag < M seconds. | Restricts the loss window to ~M seconds; still not a hard guarantee. |
WAIT is best-effort by design: "it is possible to still lose a write
synchronously replicated to multiple replicas."
— Redis Docs — WAIT
Replicas don't expire keys on their own — "they wait for masters to expire the
keys," which the primary sends as a synthesized DEL. To avoid handing back a
logically-dead value, a replica uses its clock to report the key missing on reads. And once a
replica is promoted to primary, "it will start to expire keys independently."
— Redis Docs
Answer from memory — effortful recall builds retention. Two questions revisit earlier lessons (spacing).
By default, when the primary acknowledges a write to the client, replicas have:
A replica reconnects after a blip and the backlog still covers the gap. It gets a:
WAIT 2 1000 returning 2 guarantees your write is:
To shrink the data-loss window, min-replicas-to-write makes the primary:
Interleave — a full resync makes the primary produce and stream a:
Interleave — a replica that hasn't been promoted expires a key by:
You need two local Redis instances. Start a second on port 6380:
redis-server --port 6380 (leave your default 6379 as the primary).
redis-cli -p 6379 SET k "from-primary"
redis-cli -p 6380 REPLICAOF 127.0.0.1 6379 # make 6380 a replica of 6379
redis-cli -p 6380 GET k # -> "from-primary" (synced)
redis-cli -p 6379 INFO replication | grep -E 'role|connected_slaves|master_repl_offset'
redis-cli -p 6380 INFO replication | grep -E 'role|master_link_status|slave_repl_offset'
redis-cli -p 6380 SET x 1 # -> (error) READONLY You can't write against a read only replica.
redis-cli -p 6379 SET y 2
redis-cli -p 6379 WAIT 1 1000 # -> 1 (one replica acknowledged within 1s)
Before step 2: what does the replica return for a SET, and why? And if you ran
WAIT 2 500 with only one replica attached, what number comes back after 500 ms?
Commit, then check. Detach later with REPLICAOF NO ONE (promotes 6380 to primary).
Bring your WAIT 2 500 result and the master_repl_offset vs
slave_repl_offset gap to your teacher.
Redis Docs — Replication
is the authoritative page: the async model, PSYNC/partial resync, read-only replicas,
min-replicas-*, and the data-loss window. Pair it with
WAIT for the consistency caveats.