CAP中的一致性
关于CAP这里就不详细说明,本文主要讨论CAP中的 C 即一致性(线性一致性)
首先我们要知道什么是CAP的一致性,他跟事务的一致性有什么区别,跟分布式事务里面所谓的一致性又有什么区别?
这是一个非常经典且容易混淆的问题,因为“一致性”(Consistency)这个词在计算机科学的不同领域里,虽然名字一样,但含义却大相径庭。
这三个概念分别对应了:单机数据库理论(ACID)、分布式系统理论(CAP) 和 工程实践(分布式事务)。
我们可以用一句话概括它们的区别:
- ACID 的一致性:关乎数据的“正确性”(符合业务约束)。
- CAP 的一致性:关乎数据的“新旧”(多副本同步)。
- 分布式事务的一致性:关乎跨系统的“协调”(让多个独立系统的数据最终对齐)。
1. 事务的一致性 (ACID 中的 C)
这里的背景通常指单机数据库(如 MySQL)的本地事务。
- 定义:指事务执行前后,数据库必须从一个合法状态变换到另一个合法状态。
- 核心关注点:业务逻辑与约束 (Business Logic & Constraints)。
- 详细解释:
“合法状态”是指数据必须符合预定义的规则。这些规则包括:- 数据库约束:主键唯一、外键约束、字段类型、Check约束(例如余额不能小于0)。
- 业务逻辑:例如 A 转账给 B 100元,那么 A 减去 100,B 加上 100,总金额必须不变。如果代码写错了,A 减了 100,B 却只加了 50,虽然数据库没崩溃(原子性满足),但一致性被破坏了,因为数据不再符合“总额守恒”的业务规则。
- 一句话总结:它保证数据不违背现实世界的业务规则。
2. 分布式系统的一致性 (CAP 中的 C)
这里的背景是指多副本的数据存储系统(如 Redis Cluster, Cassandra, ZooKeeper, HDFS)。
- 定义:在 CAP 理论中,C 代表 Linearizability (线性一致性) 或 Strong Consistency (强一致性)。意思是:所有的节点在同一时间看到的数据是完全相同的。
- 核心关注点:多节点间的数据同步 (Synchronization & Timing)。
- 详细解释:
在分布式系统中,为了容灾,数据通常会有多个副本(Replica)。- 当你向节点 A 写入一个新值
x = 1。 - 紧接着向节点 B 读取
x。 - 一致性要求:你必须读到
1。如果你读到了旧值0,那么这个系统就不满足 CAP 中的 C。
- 当你向节点 A 写入一个新值
- 一句话总结:它保证你读到的永远是最新写入的数据(就像只有一个副本一样)。
3. 分布式事务中的一致性
这里的背景是指微服务架构或跨数据库的操作(如 订单服务 + 库存服务 + 支付服务)。
- 定义:指在跨越多个独立服务或数据库的操作中,确保所有相关的数据最终能够达成一种逻辑上的对齐。它可以理解为事务的原子性,要么全部成功,要么全部失败。
- 核心关注点:跨系统的原子性与最终状态 (Global Outcome)。
- 详细解释:
由于分布式系统很难同时满足 CAP(通常为了可用性 A,必须牺牲强一致性 C),所以在分布式事务中,我们通常讨论两种一致性:- 强一致性(刚性事务):如 XA 协议、2PC(两阶段提交)。要求所有服务同时提交,立刻看到结果。这很像 ACID,但在分布式环境下性能极差。
- 最终一致性(柔性事务,BASE理论):如 TCC、Saga、消息队列。允许中间有一段时间数据是不一致的(例如订单已创建,但库存还没扣减完),但保证经过一段时间后,所有数据都会变对。
- 一句话总结:它保证多个独立系统的数据,虽然可能有延迟,但最终会“账目”对齐,不会出现“订单成功了但没扣库存”的烂账。
三者对比总结表
为了更清晰地理解,我们可以通过下表对比:
| 维度 | ACID 的一致性 (事务) | CAP 的一致性 (分布式系统) | 分布式事务的一致性 |
|---|---|---|---|
| 侧重点 | 数据的正确性 (逻辑约束) | 数据的可见性 (时间同步) | 全局操作的协同 (多方对齐) |
| 场景 | 单机数据库 (Oracle, MySQL) | 分布式存储 (Redis, ZK, NoSQL) | 微服务、跨库业务 |
| 反例 | 转账后总金额变少了 (违反守恒) | 刚写完主库,读从库还是旧数据 | 订单库显示“已支付”,库存库显示“未扣减” |
| 依赖对象 | 依赖数据库引擎的约束检查 | 依赖共识算法 (Raft, Paxos) 或同步复制 | 依赖协调器、MQ 或 补偿代码 |
| 核心问题 | “这笔数据合乎逻辑吗?” | “我现在读到的是最新的吗?” | “这几个系统的数据最后能对上吗?” |
举个通俗的例子
假设你要去买一杯奶茶:
ACID 一致性:你付了 20 元,店员必须给你一杯 20 元的奶茶。如果店员只给你一杯 10 元的水,或者没收钱就给你奶茶,这就违背了交易规则(ACID 破坏)。
CAP 一致性:这家奶茶店有 3 个店员(副本)。店长(主节点)刚刚更新了菜单,把“珍珠奶茶”涨价到 25 元。你问店员 A,他说 25 元;你立刻问店员 B,如果店员 B 还说 20 元,那就是同步没做好(CAP 的 C 破坏)。
分布式事务一致性:你在手机 App 上点单。
- 你的支付宝扣了钱(支付服务)。
- 奶茶店的打印机出了小票(订单服务)。
- 如果支付宝扣了钱,但奶茶店没收到单子;或者奶茶店出了单子,支付宝没扣钱,这就是跨系统的不一致。分布式事务就是要保证:要么没扣钱也没单子,要么扣了钱也有单子(哪怕中间有几秒延迟)。
线性一致性跟顺序一致性
顺序一致性
如果一个并发执行过程所包含的所有读写操作能够重排成一个全局线性有序的序列,并且这个序列满足以下两个条件,那么这个并发执行过程就是满足顺序一致性的:
• 条件 I:重排后的序列中每一个读操作返回的值,必须等于前面对同一个数据对象的最近一次写操作所写入的值。
• 条件 II:原来每个进程中各个操作的执行先后顺序,在这个重排后的序列中必须保持一致。
线性一致性
线性一致性的定义,与顺序一致性非常相似,也是试图把所有读写操作重排成一个全局线性有序的序列,但除了满足前面的条件 I 和条件 II 之外,还要同时满足一个条件:
• 条件 III:不同进程的操作,如果在时间上不重叠,那么它们的执行先后顺序,在这个重排后的序列中必须保持一致。
区别
• 它们都试图让系统“表现得像只有一个副本”一样。
• 它们都保证了程序执行顺序不会被打乱。体现在条件 II 对于进程内各个操作的排序保持上。
• 线性一致性考虑了时间先后顺序,而顺序一致性没有。
• 满足线性一致性的执行过程,肯定都满足顺序一致性;反之不一定。
• 线性一致性隐含了时效性保证(recency guarantee)。它保证我们总是能读到数据最新的值。
• 在顺序一致性中,我们有可能读到旧版本的数据。
具体可以参考这篇博客 https://mp.weixin.qq.com/s/3odLhBtebF4cm58hl-87JA
最终一致性又是什么?
其实最终一致性就不满足CAP理论的C,而是对于AP系统的扩充。
最终一致性(Eventual Consistency)是 CAP 理论中选择了 AP(可用性 + 分区容错性)策略后,为了弥补缺失的 C(强一致性)而不得不采用的一种“妥协”方案。
或者更简单点说:最终一致性是 AP 系统的核心特征。
我们可以从以下几个层面来剖析这段关系:
1. CAP 的必然性与“二选一”
CAP 理论告诉我们,在分布式系统中,P(分区容错性)是不可避免的(网线总会断,节点总会挂)。所以我们只能在 C(强一致性/线性一致性)和 A(可用性)之间做选择:
- 选择 CP(放弃 A):为了保证数据绝对一致,当网络出问题时,我宁愿报错拒绝服务,也不让你读到旧数据。
- 结果:这是强一致性系统(如 Zookeeper, HBase)。
- 选择 AP(放弃 C):为了保证服务永远可用,哪怕网络出问题了,我也让你读,虽然读到的可能是旧数据。
- 结果:这就是最终一致性发挥作用的地方(如 DNS, Eureka, Cassandra)。
2. 最终一致性在 CAP 图谱中的位置
如果把 CAP 画成一个三角形:
- CAP 中的 C (Consistency):指的是线性一致性(强一致性)。如果你追求 CAP 的 C,你就必须保证写完立刻能读到。
- 最终一致性:它是弱一致性的一种特例。它不属于 CAP 的 C。相反,它是当我们抛弃了 CAP 的 C 之后,退而求其次追求的目标。
关系公式:
CAP (AP 模式) = Availability (高可用) + Partition Tolerance (分区容错) + Eventual Consistency (最终一致性)
3. 为什么 AP 系统必然导致最终一致性?
让我们推演一下:
- 前提 (P):系统有两个节点 Node A 和 Node B,它们之间的网络断了。
- 抉择 (A):我们选择了高可用(Availability),所以当用户向 Node A 写入
x=1时,Node A 必须接受并返回成功,不能报错。 - 后果:此时,Node A 的数据是
x=1,而 Node B 因为网络断了,数据还是x=0。 - 现状:此时系统已经不一致了(违反了 CAP 的 C)。
- 补救 (最终一致性):我们不能让 Node B 永远是
0。系统承诺:当网络恢复后,Node A 会后台把x=1同步给 Node B。经过一段时间(不确定多久),Node B 最终也会变成1。
结论:因为选择了 A(允许在断网时继续写),必然导致数据暂时不一致。而“最终一致性”就是对这种暂时不一致的容忍和对未来的承诺。
4. 延伸:BASE 理论
讲到最终一致性与 CAP 的关系,就不得不提 BASE 理论。它是对 CAP 中 AP 策略的工程化延伸。:
- BA (Basically Available):基本可用(允许响应时间慢一点,或者部分降级)。
- S (Soft state):软状态(允许系统存在中间状态,即允许数据同步有延迟)。
- E (Eventual consistency):最终一致性(数据最终会变对)。
5. 总结表
| 维度 | CAP 的 C (强一致性) | 最终一致性 (弱一致性的一种) |
|---|---|---|
| CAP 选择 | CP (放弃可用性) | AP (放弃强一致性) |
| 核心逻辑 | 写操作完成后,所有节点立刻可见。 | 写操作完成后,数据异步复制,经过一段时间才可见。 |
| 用户体验 | “要么读到最新的,要么系统告诉我报错/超时。” | “我可能读到旧的,但系统保证随时能用。” |
| 典型场景 | 银行余额、库存扣减、分布式锁 (Etcd/ZK) | 社交网络点赞、DNS解析、电商商品浏览量 |
| 关系 | 它是 CAP 定义的一致性标准 | 它是放弃 CAP 的 C 之后的替代方案 |

