跳到主要内容

CAP 理论

CAP

  • Consistency 一致性。写操作之后,进行读操作必须返回刚刚已写入的值。
  • avaiable 可用性,收到用户的请求,服务器就必须给出回应。
  • partition tolerance 分区容错性。不同分区的服务直接通信可能会失败,这个无法避免。分区容错性性指的是,当网络分区之间通信发生故障时,系统会被分割成多个独立的部分,这是系统仍能够继续运行并提供服务的能力。因此可以认为 CAP 中的 P 总是成立的。

比如:北京的订单系统,访问上海的库存系统,可能导致失败。如果发生失败,就要在 A 和 C 之间做出选择。 要么停止系统进行错误恢复(AP),要么继续服务但是降低一致性(CP),所以说只能保证 AP 或 CP。

AP 不可能同时成立。

在向 S1 写入数据的时候,如何要保证一致性,那么就需要将 S2 锁定。不然没法保证一致性,此时用户请求 S2 是无法获得返回值的(不满足可用性)。

如果追求可用性,那么就不能锁定 S2, 此时 S2 返回值是修改之前的。不满足一致性。

AP,CP 如何取舍?

对于数据不敏感的系统,获取到旧版本的数据也没多大影响的时候,选择 AP。 最终一致性算法

但是对于金融系统,必须保证一致性,选择 CP。强一致性算法,如 paxos,raft

一致性

  • 单副本系统 single copy system
    • 主从复制 master/slave
    • 两阶段提交 phase commit
    • 多数派读写 quorum
  • 多主系统 multi-master system(允许多个节点同时拥有写入权限)

Isolation 隔离性

Dirty Write 脏写

一个事务可以覆盖另一个事务还未提交的已修改的值。

案例:

事务 A: x = 1; y = 1;

事务 B: x = 2; y = 2;

期望的结果:x,y 全为 12

t1: x = 1;
t2: x = 2;
t3: y =2 ;
t4: y = 1;

实际结果:x = 2; y = 1; 与预期不符。

Dirty Read 脏读

一个事务读取到了另一个事务未提交的已修改的数据。

案例

事务 A: x,y 都有 50 元,现在 x 给 y 转账 40 元。 x = x - 40; y = y + 40; 事务 B: 读取 x,y 的值。

t1: x = 50, y = 50
t2: x = 10, y = 50 注意: 此时 x 已扣减,但是 y 没有增加,这个是因为事务还没执行结束
t3: 事务 B x = 10; y= 50; 发现 x + y = 60 < 100 此处发生了脏读
t4: x = 10, y = 90 事务 A 执行结束
t5: 事务 B x = 10; y = 90;

Non-Repeatable Read 不可重复读

同一个事务,2 次读取的值不一样。

案例同上,在 t2t5 时刻,事务B 读取到的 y 值是不同的(t2: y = 50; t5: y = 90;)。

Phantom 幻读

Phantom 通常发生在一个事务首先进行了一次按照某个条件的 read 操作,譬如 SQL 里面的 SELECT WHERE P, 然后在这个事务还没结束的时候,另外的事务写入了一个新的满足这个条件的数据,这时候这个新写入的数据就是 Phantom 的了。

案例

数据库表 user 有三条数据

t1: 事务 A 查询 user 表的总数,结果为 3
t2: 事务 B 新增了一条数据。
t3: 事务 A 再一次查询了 user 表的总数,结果为 4 ,与 t1 时刻查询结果不一致。

Lost Update 丢失的更新

  1. 一个事务撤销时,把另一个已提交事务的更新数据覆盖了。
  2. 一个事务覆盖另一个事务已提交的数据。

Cursor Lost Update

Read Skew

Read Skew 发生在两个或者多个有完整性约束的数据上面

Write Skew

Consistency 一致性

相关文档

https://www.jianshu.com/p/3673e612cce2

https://jepsen.io/consistency/models

https://zinglix.xyz/2021/02/18/consistency-model/

https://www.cnblogs.com/open-source-java/p/10564836.html