专业书籍精读 · Database Internals · 第 11 章

复制与一致性

Database Internals · Ch 11 · Alex Petrov · 2019

EN →

这一章讲什么?

你在微信里换了头像,刷新一下还是旧的那张;过两秒再刷,新的出来了。《Database Internals》(《数据库系统内幕》)第 11 章讲的就是这两秒里发生了什么——你的数据其实同时存了好几份,而它们并不总是一样。这一章要给出的,是一套说清「读到的到底是哪一份」的语言。

先说个怪事

把数据想成一份要紧的文件,抄成三份交给三个人保管——这样任何一个人请假,文件都不会丢。但麻烦跟着来了:你改了甲手里那份,乙和丙手里还是旧的。此时有人去问乙,拿到的就是旧答案。更怪的是:先问甲得到新答案,再问乙得到旧答案——在提问者看来,数据「往回退了」。

旧世界为什么难

最直觉的解法是「改的时候让三个人同时改完,谁都别抢跑」。可这意味着每次改动都要等最慢那个人点头。同城机房打个来回约 1 毫秒,跨国要几十毫秒——把「保证读到最新」做到极致,代价就是每次读写都多等好几趟问询,而且只要有一个人联系不上,谁都别想改了。反过来图快,就得接受偶尔读到旧数据:这是绕不过去的取舍。

一致性不是开关,是一排档位

这一章最重要的观念:「一致不一致」不是是非题,而是一排明码标价的承诺档位,从贵到便宜——

挑哪一档,取决于读到旧值会怎样:转账余额和点赞数,显然不该买同一档。

还有一类数据根本不用商量

这一章末尾有个漂亮的点子:有些数据可以被设计成「怎么合都合得上」。比如统计点赞,让每台机器只记自己收到的那部分,合并时按机器逐项取各自的最大值再相加——重复、乱序、重发都不影响结果。这类数据压根不用商量谁说了算,自己就会收敛。代价是:只有一部分数据类型能这么设计,而且「合上了」不等于「合出来的是人想要的」。

一句话记住

存多份是为了不丢,但多份之间一定有先后差。所以别问「数据一致吗」,要问「我愿意为哪一档承诺付多少延迟」——从「永远读到最新」到「终究会一样」,中间还有好几档很划算的选择。

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