Consistency#
建模的是“Interface”,不管如何实现,而是系统对外展现的状态。
分布式系统一致性模型(从强到弱)#
| 一致性模型 | 保证了什么 | 放松了什么 | 现实例子 |
|---|---|---|---|
| Linearizability | 等价于某个顺序历史 + 尊重实时顺序 | —(最强) | 银行转账、抢票/秒杀系统、贴吧帖子内楼层排序、分布式锁(Zookeeper)、Google Spanner |
| Sequential Consistency | 等价于某个顺序历史 + 尊重每个节点的本地顺序 | 不再要求尊重全局实时顺序 | 贴吧实际体验(有 CDN 缓存延迟)、单 Primary 读(读可能落后但不乱序) |
| Causal Consistency | 有因果关系的操作,所有人按相同顺序看到 | 没有因果关系的并发操作,不同人可以看到不同顺序 | Git(离线 commit → push/pull 同步 → merge conflict 处理并发)、协同文档编辑、聊天中"回复"必须出现在原消息之后 |
| Processor Consistency | 同一个进程的写,所有人按相同顺序看到 | 不同进程的写,不同读者可以看到不同顺序 | 社交媒体 Feed(同一人的微博不乱序,不同人的交错因人而异)、邮件列表(同一发件人的邮件有序,不同发件人之间可能乱序) |
| Memory Fence | fence 之间的操作不跨 fence 重排 | 同一进程内 fence 之间的读写可被重排 | CPU 乱序执行、多处理器缓存一致性、Java/C++/Go 内存模型(无同步时指令可被重排) |
| Eventual Consistency | 所有写停止后,最终所有人读到相同值 | 过程中什么都不保证:乱序、倒退都可能 | DNS(改域名后 24-48h 全球逐渐同步)、NFS、CDN 缓存刷新、Cassandra 默认配置、购物车最终同步 |
Snapshot Reads#
Snapshot Reads 不在上面的从强到弱光谱上,它是一个正交维度的概念。
光谱上的模型回答的是:读和写之间的顺序关系是什么? Snapshot Reads 回答的是一个不同的问题:**读允许读旧数据,但必须读到一个历史上真实存在过的一致状态。同一事务内所有读来自同一个时间点的快照。
可以理解为:系统的写操作排成了一条时间线,每次读就是在这条时间线上挑一个点拍快照,而且下一次读的点不能往回走。
例子:银行对账(所有账户余额来自同一时刻)、数据库 MVCC(PostgreSQL、MySQL InnoDB)、同时读推文和屏蔽列表要来自同一快照
核心设计原则#
一致性要匹配业务需求,不是越强越好。
- 数据越集中(如贴吧单个帖子)→ 强一致性容易实现
- 数据越分散(如微博 Feed 聚合多人内容)→ 弱一致性更合理
- Feed 天然让不同人看到不同内容 → 不需要 Linearizability
弱一致性 → 容易实现,性能好,难写程序(程序员要处理各种奇怪的情况)
强一致性 → 容易写程序,性能差,难实现(系统要付出巨大的协调成本)