强一致性与高实时性通常存在系统层面的取舍,产品需明确优先项
别名: 一致性与新鲜度 · PACELC · 强一致 · 最终一致
概念解释
同一份钱不能在两个地方同时被花掉,和同一份列表要尽快在所有人屏幕上跳出来,常常不能同时做到极致。强一致与高实时存在取舍:要所有人看到同一版、读到自己刚写进去的值,协调要花时间,新鲜度会让路;要每个节点自己先画上最新一笔,画面会快,短暂的各看各的就会出现。产品必须先说清这一块优先哪一头,不能把两头都写成「都要」。
机制
多副本之间传状态有延迟。等所有副本承认同一版再给用户看,用户看到的是一致的,但是晚的——协调的那一截就是新鲜度的损失。先在本地承认再往后台传,用户看到的是快的,但是别人可能还看到旧版,自己刚写下的值在另一台设备上可能还没到。分布式系统里这件事被写成延迟与一致之间的选择:正常时你是要短延迟还是要强一致;分区时你是要继续写还是要停下来等一致。
界面上的对应物不是协议名,是两种失败哪一种更不可接受。余额花两遍、库存超卖、权限刚收回还能进,属于一致失败,代价是错的事实。列表晚两秒、头像还是上一张、协作光标顿一下,属于新鲜失败,代价是旧的事实。两者都烦,但修法相反:优先一致就要让人等、或暂时拒绝写入;优先新鲜就要准备好回滚、冲突和「你看到的可能不是最终版」。
边界
单机、单用户、数据不复制,取舍几乎不存在,不要把分布式的话套上去。法律上必须强一致的账(支付、过户、投票计数)不能为了画面跳得快而改成最终一致。纯展示、可丢失中间帧的流(在线人数的近似值)强一致没有收益。同一产品里不同块可以选不同头:支付走强一致,动态走高新鲜,前提是不要让人把动态那一块的数字拿去当账。取舍会随故障翻转:分区发生时,平时选新鲜的系统往往必须停止写入,界面要准备「现在不能改」而不是继续假装实时。
怎么落地
- 给会做错事的数据写优先项:错不得的走强一致,允许短暂各看各的走高新鲜。写进产品语言,不要只写在架构图里。
- 选强一致的块:写入未确认前不要画成已成功;读要能读到自己刚确认的写。
- 选高新鲜的块:允许短暂分叉,但要有冲突可见和回滚,并避免把这些数字接到强一致的决策上。
- 验证:在复制延迟可被拉大的环境里,对账类操作应宁可慢或拒绝,也不出现两份都成功。对动态类操作应仍能画上去,并在追平后不留两份事实。把两头都标成「又快又绝对一致」却没有任何一侧的失败演练,视为未做选择。