The idea: N copies, wait for W on a write, ask R on a read
A leaderless store like Dynamo, Cassandra or Riak keeps each key on N replicas, here N = 3: A, B and C, the key's preference list on the hash ring. Any node can act as the coordinator of a request. A write is sent to all N replicas, but the coordinator tells the client OK as soon as W of them have acknowledged it. A read asks R replicas and returns the newest value among their replies.
The page plays the worst case that W and R allow, so every run is the same. A write lands on only the first W replicas in the order A, B, C; the other PUTs are drawn as lost (red ✗). A read asks the first R replicas in the order C, B, A, the ones the write reached last. Real networks usually deliver the other PUTs a moment later, but the guarantee has to hold even when they don't.
Versions: the highest one wins
Every value carries a version. Here it is a number the coordinator picks for each write, like a timestamp, so the replica boxes show x = 20, version 2. When R replies come back with different versions, the coordinator keeps the highest one. Green replicas hold the newest version written so far, orange ones are stale. The history table marks a read STALE when it returns something older than the newest write the client was told succeeded.
Why R + W > N works
A write that succeeded is on at least W replicas. A read asks R replicas. If R + W > N, the two sets cannot be disjoint: they share at least one replica, and that replica has the new version, which is the highest one in the replies (Demo 1: W = 2, R = 2). With W = 1, R = 1 the write can sit on A while the read asks C (Demo 2: a stale read). The cost is availability and latency: a bigger W or R needs more live replicas and waits for a slower one.
| N = 3 | R + W > N? | writes work with | reads work with | typical use |
|---|---|---|---|---|
| W = 1, R = 1 | no (2): stale reads | 2 replicas down | 2 replicas down | fastest; caches, metrics |
| W = 2, R = 2 | yes (4) | 1 replica down | 1 replica down | the usual quorum (Cassandra QUORUM) |
| W = 3, R = 1 | yes (4) | no replica down | 2 replicas down | read-heavy data |
| W = 1, R = 3 | yes (4) | 2 replicas down | no replica down | write-heavy data |
Read repair
When the replies disagree, the coordinator already knows which replicas are behind: the ones that answered with an older version. After answering the client, it sends them the newest version. This is read repair. In Demo 3 a write with W = 1 reaches only A. A read with R = 3 sees versions 1, 1 and 2, returns version 2 and repairs B and C, so a later read with R = 1 from C is up to date. Read repair only fixes keys that are read; anti-entropy (replicas comparing Merkle trees in the background) fixes the rest.
A replica goes down
With C down, a write with W = 2 still succeeds on A and B, and a read with R = 2 asks B and A (Demo 4). With W = 3 only two acks can come back, so the write fails (Demo 5). But A and B keep the new version: the coordinator does not roll it back. A later read may return a value whose write the client was told had failed.
Sloppy quorum and hinted handoff
Dynamo prefers to accept the write. With a sloppy quorum, a write meant for a down C goes to D, the next healthy node on the ring, with a hint: "this belongs to C". D's ack counts toward W, so W = 3 succeeds with C down. When C comes back, D sends it the write and deletes the hint: hinted handoff (Demo 6).
The price: the W nodes that acked are no longer the key's own replicas, so R + W > N no longer promises overlap. A read that asks A, B and C only can miss a write whose third copy sits on D. Cassandra does not count hints toward the consistency level (except ANY); Riak lets the client require primaries with pw and pr.
Quorums are not linearizability
Even with R + W > N a quorum store is not a single copy. A failed write can stay on the replicas that took it (Demo 5). Two clients can write the same key at once; with versions picked by clock, one acknowledged write silently loses (last write wins), and Dynamo and Riak keep both as siblings with vector clocks instead (the CAP page shows both). A read can also race with a write in progress: one reader sees the new value, a later one the old. For linearizable reads and writes a store needs consensus, as in Raft.
In real systems
| system | W and R | versions and repair |
|---|---|---|
| Cassandra | consistency level per request: ONE, QUORUM, ALL, LOCAL_QUORUM | timestamp per cell (last write wins), read repair, hints, Merkle-tree repair |
| Riak | n_val, w, r, pw, pr per bucket or request | vector clocks / dotted version vectors, siblings, read repair, active anti-entropy |
| Dynamo (2007 paper) | N, R, W per application, typically (3, 2, 2) | vector clocks, sloppy quorum, hinted handoff, Merkle trees |
See also The CAP Theorem (quorums during a partition), Consistency Patterns (eventual, causal and strong), Consistent Hashing (how the preference list and the next node D are chosen), Merkle Trees and Anti-Entropy (repairing replicas nobody reads), CRDTs (merging concurrent writes without siblings), Lamport and Vector Clocks (ordering versions) and Primary–Replica Replication (the leader-based alternative).
See also Leader-based vs Leaderless Replication: the same 3 replicas next to a single-leader cluster, with a leader failover pause and a lost acknowledged write.
See also Object Storage: instead of N full copies, an object store cuts each object into 4 data + 2 parity shards and rebuilds lost ones on read.
What the page leaves out
Timing: real PUTs and GETs arrive at different moments and the page always shows the worst case instead. More than one key, concurrent writers and vector clocks, digest reads (Cassandra asks one replica for the data and the others only for a hash), speculative retries, read repair that runs in the background or not at all, failure detection (how the coordinator learns C is down), hints that expire, more than one node failing, and data centers (LOCAL_QUORUM, EACH_QUORUM).
References
DeCandia et al., Dynamo: Amazon's Highly Available Key-value Store (SOSP 2007)
Apache Cassandra documentation: Dynamo (replication, tunable consistency, hints, read repair)
Riak KV documentation: Replication Properties (n_val, r, w, pr, pw)
Martin Kleppmann, Designing Data-Intensive Applications, chapter 5: Leaderless Replication