专业书籍精读 · System Design Interview 卷一 · 第 6 章

设计键值存储

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

EN →

这一章讲什么?

你往购物车里加一件商品,「购物车里现在有什么」这条记录得存在某处。它简单得不能再简单——一个名字对应一份内容,就像一本超大的通讯录。这一章教你把这本通讯录,从「一个人拿着的一个本子」,变成「几千台机器一起保管、坏掉几台照样能用」的东西。

先说个怪事

亚马逊早年的购物车有个著名毛病:你删掉的商品,隔一会儿自己又回来了。这不是 bug,是刻意的取舍——宁可偶尔多一件商品,也绝不让「加入购物车」失败一次。这一章的整套设计,就是为了换来这句话:永远写得进去。

旧世界为什么难

只有一个保管员时一切都好办:你问他、他答你,答案一定是最新的。可这个人会累(记不下那么多)、会请假(机器宕机)、会失联(网线断了)——那一刻整间店就停摆。换成一群人保管,新麻烦立刻来了:你去问,问到的是哪一份?万一他手里还是三分钟前的旧版本呢?

核心机制:抄三份,写等两个、读问两个

办法出奇地朴素:同一份记录抄给三个人保管。写的时候不用等三个人都签收,其中两个签收就算写成功;读的时候也不用问全部,随便问其中两个,谁手里的日期新就信谁。

妙就妙在:三个人里挑两个签收、再挑两个来问,这两拨人一定至少有一个是同一个——他既亲手签收过最新那份,又正好被你问到了。于是「不等所有人」和「一定读得到最新的」这两件看似矛盾的事同时成立了。剩下那个没签收的,事后会被悄悄补上。

那有人请假怎么办?三招,一招比一招重。互相打听:谁请假了、谁回来了没有中央点名的人,大家各自随机找几个同事聊两句、再把听来的传出去,几秒内全店都知道。找隔壁代管:三个人里少一个,就把东西交给隔壁,并贴张便条写清「这是替某某收的」,等他回来照条交还。比对总目录页:万一他请假太久、便条都过期了,两边账差一大截——这时不必一页页核对,先只比总目录页,一样就说明全都一样、直接收工;不一样再往下翻,一层层缩小,最后只搬真正对不上的那几页。

带来了什么 / 该怎么选

这套东西给你一个可以拧的旋钮:等几个人签收、问几个人,你自己定——等得越多越保险也越慢。购物车、点赞数、用户会话这类「偶尔差一点没关系」的东西非常适合它;而账户余额这种少一分都不行的,就别用这套——它天生允许你在极端情况下读到旧值,甚至让你删掉的东西自己回来。

一句话记住

把同一份数据抄给三个人,写只等两个签收、读只问两个,靠「两拨人必有重叠」保证读得到最新的;有人请假就找隔壁代管 + 留张便条,久了就比总目录页把账补齐。换来的是「永远写得进去」,代价是偶尔会读到旧值。

想进到具体机制、记号和示意图? → 切到精读版