BOOKS DEEP READ · SYSTEM DESIGN INTERVIEW VOL 1 · CH 6

Design a Key-Value Store

System Design Interview: An Insider's Guide · Ch 6 · Alex Xu · 2020

中文 →

What is this chapter about?

When you add an item to a shopping cart, the record of "what is in this cart right now" has to live somewhere. It is about as simple as data gets — one name, one piece of content, like an enormous address book. This chapter teaches you to turn that address book from "one notebook held by one person" into "something thousands of machines keep together, and that still works when several of them break."

Start with something odd

Amazon's early shopping cart had a famous quirk: an item you deleted would come back a little later. That was not a bug, it was a deliberate trade — better to occasionally carry one extra item than to let "add to cart" fail even once. The whole design in this chapter exists to buy one sentence: writes always go through.

Why the old world was hard

With a single keeper, everything is easy: you ask, they answer, and the answer is always current. But that person gets tired (cannot hold that much), calls in sick (the machine crashes), goes unreachable (the network cable breaks) — and in that moment the whole shop stops. Hand the job to a group instead, and a new problem arrives immediately: when you ask, whose copy did you get? What if that one is still the version from three minutes ago?

The core idea: keep three copies, get two signatures, ask two people

The fix is startlingly plain: give the same record to three keepers. When writing you do not wait for all three — two signatures counts as written. When reading you do not ask everyone either — ask any two, and believe whichever copy is dated later.

The beauty is this: pick two out of three to sign, then pick two out of three to ask, and at least one person must appear in both groups. That person signed for the newest copy with their own hand, and you happened to ask them. So "do not wait for everyone" and "always see the newest value" hold at the same time. The one who missed the write gets quietly caught up afterwards.

What if someone is out sick? Three moves, each heavier than the last. Gossip: nobody takes a central roll call — everyone chats with a few random colleagues and passes on what they heard, so within seconds the whole shop knows who is out and who is back. Ask the neighbour to hold it: if one of the three is missing, hand the item to the neighbour with a sticky note saying "holding this for so-and-so", and when they return the neighbour hands it over. Compare the table of contents: if they were out so long the note expired and the two ledgers have drifted badly, you do not check page by page — first compare only the table of contents; identical means everything is identical, done. Different means you go one level deeper, narrowing each time, until you carry over only the pages that genuinely disagree.

What it buys you, and when to pick it

What you get is a dial you can turn: how many signatures to wait for, how many people to ask — you decide, and waiting for more is safer but slower. Carts, like counts, user sessions — anything where "slightly off once in a while is fine" — suit it beautifully. But for an account balance, where a single cent matters, do not use this: by construction it lets you read a stale value in the worst case, and even lets deleted things come back.

Remember this one line

Give the same data to three keepers, treat two signatures as a write and two answers as a read, and lean on "the two groups must overlap" to guarantee you see the newest value. When someone is out, hand it to the neighbour with a note; when they are out too long, compare tables of contents to reconcile. You buy "writes always go through" and you pay in occasional stale reads.

Want the actual mechanisms, notation and diagrams? → Switch to the deep read