Handbooks / System Design Case Studies / Chapter 3
Design a Distributed Key-Value Store
12 pages · ~18 min✓ Reviewed
Builds on Design a Rate Limiter. Next up: Design Search Autocomplete.
Problem, Scope and Requirements
1. Scope and API
Running example: a Distributed KV Store, a Dynamo-style store of opaque values behind put and get.
- In v1:
put(key, value)andget(key) - Values up to 400 KB
deletewrites a tombstone, it does not erase at once- Each request picks a consistency level: ONE, QUORUM or ALL
- No joins
- No multi-key transactions
- No secondary indexes in v1
put(key, value, consistency=QUORUM)
get(key, consistency=ONE)
delete(key, consistency=QUORUM) # tombstoneConsistency is chosen per request
2. Scale and Latency Targets
| Estimate | Total | Per node (100 nodes) |
|---|---|---|
| Hot data | 10 TB | ~100 GB |
| Reads | 1M/s | ~10K/s |
| Writes | 200K/s | ~2K/s (6K/s replica writes at N=3) |
- p99 read under 10 ms
High-Level Architecture (Distributed KV Store)
1. Peer-to-Peer Ring
- Every node runs the same software and has the same role
- No master: no leader election, no single point of failure
- Any node can act as coordinator for any key
- Coordinator is per request, not per key: the node the client hit
- Scale: 100 nodes, ~100 GB each, serving 1M reads/s + 200K writes/s
2. Request Path
- Clientput / get
- Coordinatorany node
- N=3 replicassent in parallel
- Quorum acksW or R met
- Respondto client
Partitioning with Consistent Hashing
Running example: a 100-node Dynamo-style KV store holding 10 TB, ~100 GB per node.
1. Ring and Owner
- Job: map each key to an owner node with minimal data movement on join or leave
- Hash the key with
MD5orMurmur3onto a 2^128 ring - Owner = the first node clockwise from the key's position
- 1keyuser:42
- 2hash(key)Murmur3 / MD5
- 3ring position0 to 2^128
- 4walk clockwisefirst token
- 5owner nodestores the key
Replication and Preference List
1. Responsibility and Placement
- Store each key on N=3 nodes so data survives node and zone loss
- Preference list = coordinator + next N-1 distinct nodes clockwise
- Skip vnodes of the same host, so 3 tokens never mean 3 copies on one box
- Zone-aware: 3 replicas in 3 AZs, so one AZ outage loses at most 1 of 3 copies
- 1Node A (AZ-1)coordinator, first clockwise
- 2Node B (AZ-2)next distinct node, new zone
- 3Node C (AZ-3)next distinct node, new zone
Tunable Consistency with Quorums
1. The Quorum Rule and Settings
- R + W > N means every read set overlaps the latest successful write set
- Standard: N=3, R=2, W=2, so any 2 replicas read must include 1 that acked the write
- Tune R and W per workload to trade read latency against write latency
| Setting | R | W | Effect |
|---|---|---|---|
| Standard |
Conflict Resolution: Vector Clocks vs LWW
1. Vector Clocks (Distributed KV Store)
- A vector clock is a list of (node, counter) pairs attached to each version
- Version A descends B if every counter in A is ≥ B's
- If neither version descends the other, they are concurrent
- Concurrent versions are kept as siblings and returned to the client to merge
2. Example: One Key, Three Writers
- 1D1 [(A,1)]first write via A
- 2D2 [(A,2)]write via A; descends D1
- 3D3 [(A,2),(B,1)]concurrent write via B
- 4D4 [(A,2),(C,1)]concurrent write via C
Failure Handling: Hinted Handoff
1. Responsibility and Sloppy Quorum
Running example: Dynamo-style Distributed Key-Value Store, N=3, W=2, 200K writes/s over 100 nodes.
- Hinted handoff keeps writes available while a preference-list replica is temporarily down
- Preference list for key k: A, B, C; B is down
- Sloppy quorum: write goes to the first N healthy nodes on the ring
- So node D (next clockwise) stands in for B and the W=2 acks still arrive
Anti-Entropy with Merkle Trees
1. Job and Tree
Background repair of replica divergence in the Distributed KV Store (100 nodes, ~100 GB each, N=3).
- Fixes divergence that read repair and hinted handoff missed (expired hint, dead stand-in, cold keys)
- Must find differences without scanning all data
- Leaf = hash of one key range
- Parent = hash of its children's hashes
- Root = one hash that summarizes the whole token range
Gossip and Failure Detection
1. Responsibility and Gossip
- Decentralized membership and liveness: no central coordinator
- Every node learns who is alive from its peers, never from a master
- Every 1 s each node exchanges state with 1-3 random peers
- Information reaches all N nodes in O(log N) rounds
- 100 nodes: about 7 rounds, so roughly 7 s to converge
- Pick peers1-3 random, every 1 s
- Send digestmy view of all nodes
- Mergekeep higher heartbeat
- Spreadpeers repeat next round
Storage Engine and Write Path
1. Write Path
Per-replica storage in the Distributed KV Store: 200K writes/s x N=3 over 100 nodes is ~6K local writes/s per node, all durable.
- Commit logappend, sequential disk
- Memtablein-memory, sorted
- Ackto coordinator
- Flushat ~128 MB
- Job: make local writes fast and durable on each replica
- The commit log is append-only, so the disk does sequential writes, no seeks
- Ack after the log append and the memtable insert, never after a flush
Scaling, Trade-offs and Interview Questions
1. Scale Out (Distributed KV Store)
- 1D joinsseed node hands it the ring
- 2Claims tokens128-256 taken from neighbors
- 3Bootstrapstreams ~1/N of data (~100 GB)
- 4Serves trafficno downtime, no reshuffle
- Add a node: it takes tokens from neighbors, not from the whole ring
- Bootstrap streams only ~1/N of the data;
hash mod Nwould move ~(N-1)/N - Old owners keep serving until the stream ends, so no downtime
2. Trade-offs and Comparison
Check yourself
N=3 and a QUORUM write needs W=2. Two of the three preference-list replicas are down. What happens, and what changes with a sloppy quorum?
- Strict quorum: only 1 ack is possible, so the write fails (or times out).
- Sloppy quorum: the write goes to the next healthy nodes on the ring, with hints naming the real owners, so it succeeds.
- The cost: those stand-ins are not in the preference list, so R + W > N no longer guarantees a read sees this write.
- Consistency level ONE would also succeed, because one ack is enough.