分布式事务
什么是事务
事务提供了一种机制,在一次操作中可能涉及到多步操作,事务可以保证这一系列操作“要么全部完成,要么什么都不做”,只要这一系列操作中有一步失败,那么在这之前的操作都要回滚。
ACID 理论
我们在本地使用数据库的时候,经常会涉及到事务的 ACID 特性,所谓的 ACID 其实就是原子性、一致性、隔离性和持久性的缩写。
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
原子性
原子性保证的是事务中的一系列操作要么全部完成要么什么都不做,不能停在某个中间状态。
假设我们有一个转账的事务,包含两个操作:
- 从 A 账户中取走 100 元
- 存入 B 账户 100 元
这两个操作根据原子性的要求,是必须要么都做,要么都不做的,假设只完成了第一步而第二步没做,那么钱的总数就会少了 100 元
一致性
一致性保证的是,我们在一个事务开始之前和结束之后,整个数据库都需要不破坏一致性约束。
还是转账的例子,假设在事务在开始之前 A 账户有 100 元,B 账户有 0 元,那么在一致性约束下,事务结束之后 A 账户剩余 0 元,B 账户拥有 100 元,A 和 B 账户钱的总和不能变
隔离性
隔离性说的是,一个事务要访问的数据正在被另一个事务修改,只要另一个事务未提交,那么这个事务所访问的数据就不会受到未提交事务的影响。我们不希望一个事务可以看到另一个事务未提交的数据。
依然是转账的例子,当 A 向 B 转账这个事务还没有完成的时候,B 查询了自己的余额,那么 B 仍然看到的余额是 0 元。
持久性
持久性约束是当一个事务对数据修改了之后,这个修改是永久性的,即使数据库故障了也不会丢失。
CAP 理论
分布式事务由于有 CAP 理论的约束,所以是不能实现上面这种 ACID 特性的
CAP 理论是一致性、可用性和分区容错性的缩写:
- 一致性(Consistency)
- 可用性(Availability)
- 分区容错性(partition-tolerance)
CAP 理论说的是在一个分布式系统中,一致性、可用性和分区容错性这三种特性无法全部满足,要么AP要么CP要么AC。
一致性
一致性保证一旦数据更新完毕并返回客户端响应了,那么集群中各个节点在同一时间数据必须都是一致的,从各个节点读取到的数据都是最新的数据
在 CAP 中一致性包括 强一致性、弱一致性和最终一致性
所以要保证一致性的话就意味着,我们在写入主数据库后,在向从数据库中同步的时候要对从数据库上锁,防止其他线程从从数据库中读取到旧数据,在同步完从数据库后进行解锁再响应客户端。
可用性
服务一直可用,一直是正常的响应时间
- 当主节点正在被更新的时候,备份节点接收到数据查询的请求后依然可以响应客户端请求
- 备份节点不允许出现响应超时
流程:
- 写入主数据库后要同步给备份节点
- 需要保证备份节点的可用性,不可以对备份节点进行加锁
- 即使数据还没同步过来,从数据库也要返回要查询的数据,即使是旧数据
分区容错性
通常分布式系统的各个节点都部署在不同的子网中,不可避免的会出现由于网络问题导致的节点与节点之间通信失败即发生网络分区,此时分布式系统应该依然就可以对外提供服务,这就是分区容错性,分区容错性是分布式系统必须要具有的特性。
CAP 三选二
假设我们现在有两台主机,Host1 和 Host2,他们之间网络互通,Host1 运行的 P1对应的数据库 Data,Host2运行的P2 对应的数据库 Data
此时,因为网络原因,Host1 和 Host2 之间的网络断开了,但是一个分布式系统要支持这种网络异常,因为要满足分区容错性,此时能不能同时满足一致性和可用性呢?
假设这个时候,
- 用户向Host1发送个数据的更新请求,那Host1中的数据将会从 Data(0)变为 Data(1)
- 因为此时网络是断开的,所以分布式系统之间的同步会失败,所以不能将数据同步到 Host2,Host2中的数据依然是 Data(0)
- 此时有用户向 Host2 发送读取数据的请求,因为数据还没有同步,所以没办法给用户最新的数据,此时就有两个选择:
- 牺牲一致性,返回用户旧的数据
- 牺牲可用性,P2 阻塞等待,直到网络连接回复,同步了新的数据
CP 放弃 A:
即分布式系统不强调可用性,允许系统停机并长时间无响应,而追求一致性和分区容错性
AP 放弃 C:
放弃一致性,而保证分布式系统的可用性和分区容错性,实现AP,前提是用户可以接收所查询的数据在一定时间内不是最新的即可。
总结:
- CA 放弃 P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。这样分区将永远不会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA。
- CP 放弃 A:如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。很多传统的数据库分布式事务都属于这种模式。
- AP 放弃 C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。
BASE 理论
BASE 是基本可用(Basically Available),软状态(Soft State),**最终一致性(Eventually consistent)**的缩写、
BASE 是对 CAP 理论可用性和一致性权衡的结果,核心思想是即使无法做到强一致性,但是每个应用都可以根据自身特点采用适当的方法,来使系统达到最终一致性
ACID 是传统数据库常用的概念,追求 强一致性 的概念
BASE 支持的大型分布式系统,通过牺牲 强一致性 获得 高可用性
基本可用
基本可用其实就是两个妥协:
- 对响应时间的妥协:正常情况下一个搜索引擎的搜索响应时间只需要0.5秒,但是在出现故障的时候,查询结果响应的时间增加到1~2秒
- 对功能损失的妥协:例如在一个电商系统中,正常情况下,消费者能够正常的完成一笔订单,但是在双十一的时候由于消费者购物行为激增,为了保证系统的稳定性,部分消费者可能会被引导到一个降级页面
软状态
原子性(硬状态):要求多个节点的数据副本都是一致的
软状态:允许多个节点的系统中个别节点存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个系统节点的数据副本存在数据延迟
最终一致性
因为软状态允许系统中个别节点存在中间状态,但是不能一直是中间状态,要有一个期限,在期限过后应该保证所有节点的数据一致性,从而达到数据的最终一致性