在分布式系统中,一致性模型是描述“系统状态如何演进”以及“客户端能观察到什么”的契约。为了更好地理解,我们通常将其拆分为读一致性(侧重可见性)和写一致性(侧重顺序性)。
一、读写一致性级别汇总
我们将读写一致性级别按保障强度从强到弱进行汇总对比:
| 强度 | 读一致性级别 (侧重可见性) | 写一致性级别 (侧重顺序性) | 核心保障 |
|---|---|---|---|
| 最强 | 强一致性 | 强一致性 | 读写操作都有一个绝对的原子生效点,全局时序唯一。 |
| 较强 | 会话一致性 | 顺序一致性 | 保证特定范围(如单人或全局)内的操作顺序不乱。 |
| 中等 | 单调读一致性 | 因果一致性 | 保证逻辑上的因果关系或时间轴不倒退。 |
| 最弱 | 最终一致性 | 最终一致性 | 不保证即时性与顺序,只保证数据最终收敛。 |
二、读 vs 写:维度的差异
虽然它们共享一些名称(如强一致性、最终一致性),但关注的矛盾点不同:
- 读一致性解决的是“可见性”问题:
- 核心问法:“我读到的数据够不够新?”
- 主要挑战:如何规避由于主从同步延迟导致的“数据消失”或“时光倒流”。
- 写一致性解决的是“顺序性”问题:
- 核心问法:“两个并发操作谁先谁后?所有节点看到的顺序一样吗?”
- 主要挑战:如何在没有全局时钟的情况下,为分布式请求定序并解决冲突。
三、容易混淆的点
1. 强一致性:读写是“硬币的两面”
在实现强一致性(线性化)时,读和写是不可分割的。
- 写强读弱:写操作同步了所有副本,但读操作去读了一个不校验版本的从库,依然会读到旧数据。
- 读强写弱:读操作每次都强制读主库,但写操作没有共识算法保证顺序,导致主库数据本身就是混乱的。
- 结论:真正的强一致性要求读写协议共同协作(如 Raft 的多数派写 + Read Index 读)。
2. 单调读 vs 顺序一致性
这是最容易搞混的一对:
- 单调读是“个人感受”:只要我看到的数据不退步就行,我不关心别人看到了什么。
- 顺序一致性是“全局契约”:要求全集群所有节点看到的演进序列完全一致。
- 关系:顺序一致性比单调读强得多。顺序一致性保证了世界的演化路径唯一,而单调读只保证你的视角不混乱。
3. 会话一致性 vs 因果一致性
- 会话一致性是因果一致性的一个特例。
- 它仅关注“我写的 我读的”这一条因果链。
- 而广义的因果一致性还关注“他写的 我读到的 我又写的”这种跨用户的逻辑依赖。
四、如何选择?
- 错一点都不行(金融、锁):强一致性。
- 可以慢,但不能乱(配置分发、消息队列):顺序一致性。
- 不让用户感到困惑(社交、个人资料):会话一致性 / 单调读。
- 追求极致吞吐(点赞、计数):最终一致性。