一,分布式系统与环境问题
概念
系统可以笼统分为集中式系统和分布式系统。
集中式系统就是由一台或多台主计算机组成中心节点,系统所有功能均由其集中处理。
分布式系统是硬件和软件组件分布不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。
特征
因此,分布式系统在没有特定业务约束的情况下,都会存在以下特征:
分布性(空间任意分布)
对等性(节点对等,没有主从之分,可选举)
并发性(更新并发)
缺乏全局时钟(总体缺乏事件序列控制)
问题
分布式系统的特征就决定分布式环境的各种问题
典型的:
通信异常(网络本身不可靠性很可能导致消息丢包和延迟)
网络分区(网络延时不断增大使只有部分节点可互相通信,即脑裂)
三态(成功,失败,超时)无法确定
节点故障
二,从ACID到CAP/BASE
事务是由一系列对系统中数据进行访问与更新的操作所组成的执行逻辑单元,具有ACID性质。
事务有4个特征:
A(原子性,要么全执行要么不执行)
C(一致性,事务在执行前后都必须保证数据库一致)
I(隔离性,一个事务执行时不能被其他事务干扰,四种隔离级别)
D(持久性,一个事务一旦提交,它对数据库中对应的改变是永久性的)
分布式事务由于上边产生的种种问题,很难保证事务的ACID性质,就衍生出了CAP/BASE理论
C 一致性:数据在多个副本中能够保持一致的特性
A 可用性:系统提供服务一直处于可用状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
P 分区容错性:分布式系统在遇到网络分区故障时,仍然保证对外提供满足一致性和可用性的服务
有趣的是CAP理论不能全部满足,只能满足其中的3选2
BASE理论指基本可用,软状态和最终一致性
BA 基本可用:指分布式系统出现不可预知故障时,允许损失部分可用性换取系统总体可用,比如相应时间和功能
S 弱状态:指允许系统中数据存在中间状态,而且该中间状态不会影响系统整体可用性。
E 最终一致性:强调系统所有的数据副本,在经过一段时间同步后,最终达到一个一致的状态,不需要实时保证强一致性。
三,四种隔离级别
读未提交:
该隔离级别允许脏读,如果一个事务在处理某一数据,并对其更新,但同时尚未完成事务,因此还没有进行事务提交;与此同时,允许另一个事务访问该数据。
事务A:1->2->3->4->5->6
事务B读数据可以读到1,2,3,4,5,6
脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
读已提交
和读未提交区别是只授权读取已经提交的数据,无法看见中间值。
事务A:1->2->3->4->5->6;事务C:6->7->8->9
事务B多次读取可读到1,6,9
不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
可重复读取:
保证事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻一致,不过也可能出现幻影数据,即相同的事务操作,在前后两个时间段读取同一数据结果不同。
幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
串行化:
要求所有事务串行执行,不能并发执行
不可重复读的重点是修改 :
同样的条件, 你读取过的数据,再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件, 第 1 次和第 2 次读出来的记录数不一样
四,分布式事务
在分布式系统中,每一个机器节点知道自己在事务操作中的结果,却无法直接获取其他分布式节点的操作结果。
因此,当一个事务操作需要跨越多个分布式节点,为了保证事务的ACID特性,就需要引入一个协调者(coordinator)统一调度所有分布式节点的执行逻辑,基于这个思想衍生出2PC和3PC提交协议
两阶段提交(2PC)
二阶段提交协议是将事务的提交过程分成了两个阶段来进行处理:
阶段一,提交事务请求
- 事务询问
- 执行事务
- 各参与者向协调者反馈事务询问的相应
阶段二,执行事务提交
正常执行事务提交,如果所有节点都正常
发送提交请求->事务提交->反馈提交结果->完成事务
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,脑裂,太过保守
- 同步阻塞
在二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态。 - 单点问题
在二阶段提交过程中,一旦协调者出现问题,那么整个二阶段提交流程将无法进行,而且如果协调者在阶段二出现问题,其他参与者将会一直处于锁定事务资源的状态中,而无法继续完成事务操作。 - 数据不一致
当执行事务提交时,当协调者向所有的参与者发送commit请求后,发生了局部网络异常或协调者在尚未发送完commit请求前自身发生了崩溃,导致最终只有部分参与者收到了commit请求,导致分布式系统数据不一致 - 太过保守
没有设计较完善的容错机制,任意节点失败都会导致整个事务失败
三阶段提交(3PC)
三阶段提交是2PC的改进版,将二阶段提交协议的提交事务请求过程一分为二,形成了由CanCommit,PreCommit和doCommit三个阶段组成的事务处理协议
阶段一:CanCommit
事务询问
协调者向所有的参与者发送一个包含事务内容的cancommit请求,询问是否可以执行事务提交,完成后各参与者向协调者反馈事务询问的响应
阶段二:PreCommit
事务预提交
协调者根据各参与者的反馈情况决定是否可以进行事务的PreCommit操作
如果协调者从参与者获得可以提交反馈,就会执行事务预提交,将信息写在日志文件中
阶段三:doCommit
真正提交
将预提交状态转换成提交状态,发送提交请求->事务提交->反馈结果->完成
优点:降低参与者的阻塞范围,并且能够在出现单点故障后继续达成一致
缺点:参与者收到precommit消息后,如果网络分区,参与者与协调者无法正常通信,参与者依然会进行事务提交,导致数据不一致性
总结:
二阶段提交解决了分布式事务原子性的问题,保证了分布式事务的多个参与者要么都执行成功,要么都执行失败。
但是在二阶段解决问题同时,依然存在一些问题比如同步阻塞,无限期等待和脑裂等问题
三阶段提交添加了预提交过程,从而避免了二提交中无限期等待的问题。
Paxos算法引入了过半的理念,通俗讲是少数服从多数原则,Paxos算法支持分布式节点角色之间的轮换,避免了分布式单点出现,既解决了无限期等待的问题也解决了脑裂问题。
消息日志异步执行分布式事务
分布式系统在处理任务时通过消息日志的方式来异步执行
本地消息表
采用定时轮询扫描的方式,去检查消息表的数据。
producer端需要设计DB消息表,consumer端准备判重表,实现业务的幂等,同时还需要一个后台任务,不断扫描本地消息。
将分布式事务拆分成本地事务执行
MQ事务消息
采用时效性高的 MQ,由对方订阅消息并监听,有消息时自动触发事件
以RocketMQ中间件为例,其思路为:
第一阶段Prepared消息,会拿到消息的地址
第二阶段执行本地事务
第三阶段通过第一阶段拿到的地址去访问消息并修改状态