分布式系统中经常出现的异常
机器宕机,网络异常,消息丢失,消息乱序,数据错误,不可靠的tcp,存储数据丢失。
分布式事务问题
也叫分布式数据一致性问题,简单来说就是如何在分布式场景中保证多个节点数据的一致性。分布式事务产生的核心原因在于存储资源的分布性,比如多个数据库,或者MySQL和Redis两种不同存储设备的数据一致性等。在实际应用中,我们应该尽可能地从设计层面去避免分布式事务的问题,因为任何一种解决方案都会增加系统的复杂度。
基于XA协议解决分布式数据一致性的基本原理
X/Open分布式事务模型
X/Open DTP(X/Open Distributed Transaction Processing Reference Model)是X/Open这个组织定义的一套分布式事务的标准。这个标准提出了使用两阶段提交(2PC,Two-Phase-Commit)来保证分布式事务的完整性。
X/Open DTP中包含以下三种角色
• AP:Application,表示应用程序。
• RM:Resource Manager,表示资源管理器,比如数据库。
• TM:Transaction Manager,表示事务管理器,一般指事务协调者,负责协调和管理事务,提供AP编程接口或管理RM。可以理解为Spring中提供的Transaction Manager。
也就是将一次事务提交分为了三个角色,AP负责业务编写产生实务操作,TM负责封装事务的操作作为事务的协调者,AP通过TM将事务提交给RM,也就是事务的持久化。
两阶段提交协议
在X/Open模型中,TM实现了多个RM事务的提交,实际上事务的提交分为两个阶段,第一阶段为事务的准备阶段,第二阶段是事务的提交或者回滚阶段。这两个阶段都是由事务管理器发起的。
两阶段提交流程
准备阶段
事务管理器(TM)通知资源管理器(RM)准备分支事务,记录事务日志,并告知事务管理器的准备结果。
提交/回滚阶段
如果所有的资源管理器(RM)在准备阶段都明确返回成功,则事务管理器(TM)向所有的资源管理器(RM)发起事务提交指令完成数据的变更。反之,如果任何一个资源管理器(RM)明确返回失败,则事务管理器(TM)会向所有资源管理器(RM)发送事务回滚指令。
两阶段提交的优缺点
优点
两阶段提交将一个事务的处理过程分为准备和执行两个阶段,它的优点在于充分考虑到了分布式系统的不可靠因素,并且采用非常简单的方式(两阶段提交)就把由于系统不可靠而导致事务提交失败的概率降到最小。
缺点
同步阻塞
所有参与者(RM)都是事务阻塞型的,对于任何一次指令都必须要有明确的响应才能继续进行下一步,否则会处于阻塞状态,占用的资源一直被锁定。
过于保守
任何一个节点失败都会导致数据回滚。
事务协调者的单点故障
如果协调者在第二阶段出现了故障,那么其他的参与者(RM)会一直处于锁定状态。
“脑裂”导致数据不一致问题
在第二阶段中,事务协调者向所有参与者(RM)发送commit请求后,发生局部网络异常导致只有一部分参与者(RM)接收到了commit请求,这部分参与者(RM)收到请求后会执行commit操作,但是未收到commit请求的节点由于事务无法提交,导致数据出现不一致问题。
三阶段提交协议
三阶段提交协议是两阶段提交协议的改进版本,它利用超时机制解决了同步阻塞的问题
三阶段提交协议的具体描述如下:
CanCommit(询问阶段)
事务协调者向参与者发送事务执行请求,询问是否可以完成指令,参与者只需要回答是或者不是即可,不需要做真正的事务操作,这个阶段会有超时中止机制。
PreCommit(准备阶段)
事务协调者会根据参与者的反馈结果决定是否继续执行,如果在询问阶段所有参与者都返回可以执行操作,则事务协调者会向所有参与者发送PreCommit请求,参与者收到请求后写redo和undo日志,执行事务操作但是不提交事务,然后返回ACK响应等待事务协调者的下一步通知。如果在询问阶段任意参与者返回不能执行操作的结果,那么事务协调者会向所有参与者发送事务中断请求。
DoCommit(提交或回滚阶段)
这个阶段也会存在两种结果,仍然根据上一步骤的执行结果来决定DoCommit的执行方式。如果每个参与者在PreCommit阶段都返回成功,那么事务协调者会向所有参与者发起事务提交指令。反之,如果参与者中的任一参与者返回失败,那么事务协调者就会发起中止指令来回滚事务。
三阶段提交协议和两阶段提交协议相比有一些不同点
• 增加了一个CanCommit阶段,用于询问所有参与者是否可以执行事务操作并且响应,它的好处是,可以尽早发现无法执行操作而中止后续的行为。
• 在准备阶段之后,事务协调者和参与者都引入了超时机制,一旦超时,事务协调者和参与者会继续提交事务,并且认为处于成功状态,因为在这种情况下事务默认为成功的可能性比较大。
实际上,一旦超时,在三阶段提交协议下仍然可能出现数据不一致的情况,当然概率是比较小的。另外,最大的好处就是基于超时机制来避免资源的永久锁定。需要注意的是,不管是两阶段提交协议还是三阶段提交协议,都是数据一致性解决方案的实现,我们可以在实际应用中灵活调整。比如ZooKeeper集群中的数据一致性,就用到了优化版的两阶段提交协议,优化的地方在于,它不需要所有参与者在第一阶段返回成功才能提交事务,而是利用少数服从多数的投票机制来完成数据的提交或者回滚。
分布式事务的两个理论模型
1.CAP 定理
CAP 理论为:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。(也就是说一致性和可用性不可兼得)
一致性(Consistency):
一致性指 (all nodes see the same data at the same time),即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。(等同于所有节点访问最新的数据副本,这是强一致性)
可用性(Availability):
可用性指(Reads and writes always succeed),即服务一直可用,而且是正常响应时间,系统对外提供的服务必须一直处于可用状态,在任何故障下,客户端都能在合理的时间内获得服务端的非错误响应。
分区容错性(Partition tolerance):
分区容错性指(the system continues to operate despite arbitrary message loss or failure of part of the system),即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。(出现网络分区)
为什么没有CA/CAP
如果要实现CA或者说CAP这种情况,相当于需要网络百分百可用,否则当出现网络分区的情况时,为了保证数据的一致性,系统必须等待网络分区故障结束之后,进行数据同步,那么这个等待故障节点恢复的过程中,就必须拒绝客户端的请求。但是如果拒绝了请求,就无法满足A,所以在分布式系统中不可能选择CA,因此只能有AP或者CP两种选择。(其实不是说没有CAP,而是CA不共存,所以也就没有CA的衍生特性CAP了)
AP:对于AP来说,相当于放弃了强一致性,实现最终的一致,这是很多互联网公司解决分布式数据一致性问题的主要选择。
CP:放弃了高可用性,实现强一致性。前面提到的两阶段提交和三阶段提交都采用这种方案。可能导致的问题是用户完成一个操作会等待较长的时间。
notice:
网络分区;
不同节点分布在不同的子网络中时,在内部子网络正常的情况下,由于某些原因导致这些子节点之间出现网络不通的情况,导致整个系统环境被切分成若干独立的区域,这就是网络分区。
2.BASE理论
BASE理论是对CAP订立的一种延伸,他的思想就是:
即使无法做到强一致性,也要做到最终一致性。也就是强调可以支持弱一致性。
基本可用(Basically Available)
基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。
软状态(Soft State)
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。MySQL Replication 的异步复制也是一种体现。
最终一致性(Eventual Consistency)
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。
特性
弱一致性,允许基本可用性
BASE理论和CAP定理的对比
BASE理论和CAP定理针对的都是分布式,BASE理论是对CAP定理的一种延伸,或者说是CAP定理实际应用中的一种妥协,也就是弱一致性和允许基本可用性,主要是提出了软状态,这个状态是分布式系统实现一致性前的一种状态,可以说是已执行的延迟状态,BASE理论允许一定时间内分布式节点出现这种中间状态,但是最终要实现一致性。
强一致性,弱一致性,最终一致性
在我看来可能从宏观上来看,只有强一致性和弱一致性,强一致性也就是线性一致性,他的所有数据同步过程都是同步的,而弱一致性即其所有同步过程都不是同步的,即异步的,而最终一致性也是弱一致性中的一种体现,最终一致性指允许节点延迟一段时间后和主节点数据同步。