附加章八:数据一致性
复习
- 副本:同一份数据可能被复制到多个位置保存
- 网络通信:网络中的通信可能延迟、丢失或乱序
TL;DR
- 一致性描述多个副本对数据状态达成怎样的约定
- 并发写入会带来冲突,需要规则化解
- 强一致更可靠但往往更慢,最终一致更快但会短暂不一致
- 一致性、可用性与分区容忍,很难同时全部满足
正文
为了让数据更可靠、访问更快,我们常常把它复制到多个地方:多块磁盘、多台服务器、多个机房。可副本一多,新问题就来了:当有人修改数据时,这些副本怎样才能保持一致?
这就是数据一致性(data consistency)要回答的问题。
副本带来的麻烦
单个副本时,读写都对着同一份数据,没什么好争的。可一旦有多个副本,情况立刻复杂起来:
- 一个副本刚更新,另一个还是旧值,读它们会得到不同结果
- 两个人几乎同时改写同一份数据,谁说了算
- 更新还没同步完,网络就断了,副本之间开始“各说各话”
于是,我们必须为“一致”定一个明确的含义:到底什么情况下,系统才允许你对某个副本的读取,与整体状态相符?
强一致与最终一致
一致性不是一个“有或没有”的开关,而是一条光谱。两端常被拿来对比:
- 强一致:任何时刻读到的都是最新写入的值,像是只有一份数据。安全,但往往要等待多数副本确认,延迟高、可用性差
- 最终一致:先允许短暂的不一致,但保证经过一段时间后,所有副本会收敛到同一个值。响应快、可用性高,但中间可能读到旧数据
选哪一端,取决于业务。银行转账往往要强一致,宁可慢一点也不能算错;社交平台的点赞数晚几秒更新,通常无伤大雅。
并发冲突怎么解
当多个操作同时作用于同一份数据,就会产生冲突。常见的化解手段有:
- 事务:把一组操作打包成“要么全做、要么全不做”,并保证彼此隔离
- 版本与时间戳:给每次修改编号,冲突时按规则取舍
这些机制的目的,都是让“同时发生”的操作有一个可预期的结果,而不是听天由命。
三者不可兼得
分布式系统里有一条著名的经验——CAP:一致性(Consistency)、可用性(Availability)、分区容忍(Partition tolerance)三者,最多同时满足两个。
由于网络分区几乎无法避免,现实系统通常被迫在“一致”和“可用”之间做取舍:要么暂停服务以确保数据一致,要么继续服务但容忍暂时的不一致。
这也解释了我们前面看到的一些设计:备份、缓存、多副本、区块链,本质上都在用不同方式回答同一个问题——当无法同时拥有全部好处时,你更愿意牺牲哪一样?
思考题
为什么“强一致”和“低延迟”常常难以兼得?
小结
知识点
- 一致性约定多副本对数据状态的看法
- 强一致与最终一致是一光谱的两端
- 事务、版本等机制化解并发冲突
- CAP 说明三者难以同时全部满足
参考资料
- Wikipedia(zh):一致性 (计算机科学):多副本数据状态的约定
- Wikipedia(zh):CAP定理:分布式系统三者不可兼得
- Wikipedia(zh):最终一致性:允许短暂不一致、最终收敛的模型
思考题答案(仅供参考)
因为强一致通常要求写入被多个副本确认后才算完成,而跨副本的通信存在网络延迟,必须等待它们回应。等待越多,响应就越慢。想在保证强一致的同时又追求极低延迟,就要面对这一对难以调和的矛盾。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪