专业书籍精读 · DDIA · 第 12 章

数据系统的未来

Designing Data-Intensive Applications · Ch 12 · Martin Kleppmann · 2017

EN →

这一章讲什么?

你在淘宝上改一次收货地址,这个改动要传到好几套系统里:订单页读的那份、搜索框搜出来的那份、客服后台看的那份、晚上跑报表用的那份。前十一章讲的都是「一套系统内部怎么做好」,最后这一章,作者第一次把话说全:这么多套系统该怎么拼在一起,才不会互相打架?这不是总结,是他自己的主张

先说个怪事

常见做法是「一改就到处改」:程序改完主数据库,顺手把搜索那份也改了。听着天经地义,却有个隐蔽的毛病——两个人几乎同时改同一条数据时,主库可能先收到甲后收到乙,搜索那边偏偏先收到乙后收到甲。两边留下不同的最终结果,而且不会自己发现,更不会自己修好

难点不在「写不进去」,而在没人负责排顺序:每套系统只看见自己收到的那几笔,各按各的先后办事。就像一家公司十几个部门各记各的账本,单看每本都没错,凑一起就对不上。系统越多线越多——十套系统两两相连最多九十条。

这章的核心点子:先排队,再抄写

作者的答案朴素得有点意外:设一本唯一的流水账,所有改动先排队记进去,其他系统都只是这本账的「抄本」。顺序在账上定死一次,谁也别再自己发明;下游照着同一份顺序往下抄,快慢有别,但抄出来的内容一定一致

这一招还顺手解决两件老大难:加新系统不再可怕——想上一套新推荐系统,让它从第一页重抄一遍即可;改错了可以重来——用新逻辑重放一遍、算出一份新抄本,跑对了再切过去,旧的原地不动、随时能退回。作者说得更狠:我们熟悉的「数据库」不过是把存、建索引、查捆在一个盒子里卖;把盒子拆开、各交给最擅长的工具,中间用这本流水账串起来,就得到一个摊开在整个公司里的大数据库。

那「算错了」怎么办

还得保证一件事只算一次。用户付款时手抖点了两下,中间任何一层的去重都可能失灵。作者的答案是让最两头的人负责:下单时就给这笔操作发一个唯一「号码牌」,一路带着走,最后收单的地方认牌不认人,同一个号码只算第一次。

另一半答案更像生意人:不是所有规矩都得当场卡死。航空公司照样超售机票,做法是事后对账、发现了就赔偿改签——把「绝不出错」换成「出错能查出来、能补救」。这也正是这套架构诚实的代价:各个抄本天生有点滞后,换来可重建可扩展,付出的是「刚写完不一定马上到处可见」。全书最后作者还拐了个弯谈该不该做:算法拿历史数据做预测,容易把过去的偏见照抄进未来;攒下的用户数据与其当资产,不如当成随时可能炸的负债——不需要了就该删。

一句话记住

别让每套系统各写各的、各排各的顺序。设一本唯一的流水账,所有改动先排队进账,其他系统都当它的抄本;正确性别指望中间任何一层,靠两头认号码牌;实在卡不住的规矩,就事后对账、认错补偿。

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