分布式事务——三阶段提交
在前文,我们介绍来了分布式事务,以及分布式事务的解决方案之一的二阶段提交。
本文介绍分布式事务处理方案之一的三阶段提交协议。
分布式事务
分布式事务是指发生在多个数据节点之间的事务,分布式事务比单机事务要复杂的多。在分布式系统中,各个节点之间在是相互独立的,需要通过网络进行沟通和协调。由于存在事务机制,可以保证每个独立节点上的数据操作可以满足ACID。但是,相互独立的节点之间无法准确地知道其他节点的事务执行情况。所以从理论上来讲,两个节点的数据是无法达到一致的状态。如果想让分布式部署的多个节点中的数据保持一致性,那么就要保证在所有节点数据的写操作,要么全部都执行,要么全部都不执行。但是,一台机器在执行本地事务的时候无法知道其他机器中的本地事务的执行结果,所以它也就不知道本次事务到底应该commit还是rollback。所以,常规的解决办法就是引入一个"协调者"的组件来统一调度所有分布式节点的执行。
为了解决这种分布式一致性问题,前人在性能和数据一致性的反反复复权衡过程中总结了许多典型的协议和算法。其中比较著名的有二阶提交协议(Two Phase Commitment Protocol)、三阶提交协议(Three Phase Commitment Protocol)和Paxos算法。针对分布式事务,是X/Open 这个组织定义的一套分布式事务的标准X/Open DTP(X/Open Distributed Transaction Processing ReferenceModel),定义了规范和API接口,可以由各个厂商进行具体的实现。
大部分的关系型数据库通过两阶段提交(Two Phase Commit,2PC)算法来完成分布式事务,比如Oracle中通过dblink方式进行事务处理。下面重点介绍下3PC算法。
下面重点介绍下三阶提交协议算法。
三阶段提交概述
三阶段提交协议可以理解为两阶段提交协议的改良版,是在协调者和参与者中都引入超时机制,并且把两阶段提交协议的第一个阶段分成了两步: 询问,然后再锁资源,最后真正提交。
两阶段提交协议最早是分布式事务的专家Jim Gray在1978年的一篇文章Notes on Database Operating Systems中提及。两阶段提交协议可以保证数据的强一致性,即保证了分布式事务的原子性:所有结点要么全做要么全不做。许多分布式关系型数据管理系统采用此协议来完成分布式事务。它是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。同时也是解决一致性问题的算法。该算法能够解决很多的临时性系统故障(包括进程、网络节点、通信等故障),被广泛地使用。但是,它并不能够通过配置来解决所有的故障,在某些情况下它还需要人为的参与才能解决问题。两阶段提交协议存在的问题是,协调者在某些时刻如果失败了, 整个事务就会阻塞。于是Skeen发布了"NonBlocking Commit Protocols" (1981)这篇论文,论文指出在一个分布式的事务里面, 需要一个三阶段的提交协议来避免在两阶段提交中存在的阻塞问题。
顾名思义,三阶段提交分为以下三个阶段:
- CanCommit
- PreCommit
- DoCommit
在三阶段提交协议中,系统一般包含两类角色:
- 协调者(Coordinator),通常一个系统中只有一个;
- 参与者(Participant),一般包含多个,在数据存储系统中可以理解为数据副本的个数。
CanCommit
在CanCommit阶段,协调者协议流程如下:
- 写本地日志“BEGIN_COMMIT”,并进入WAIT状态;
- 向所有参与者发送“VOTE_REQUEST”消息;
- 等待并接收参与者发送的对“VOTE_REQUEST”的响应。参与者响应“VOTE_ABORT”或“VOTE_COMMIT”消息给协调者。
该流程与两阶段提交协议类似。
PreCommit
在PreCommit阶段,,协调者将通知事务参与者准备提交或取消事务,写本地的redo和undo日志,但不提交。
协调者协议流程如下:
-
若收到任何一个参与者发送的“VOTE_ABORT”消息;
- 写本地“GLOBAL_ABORT”日志,进入ABORT状态;
- 向所有的参与者发送“GLOBAL_ABORT”消息;
-
若收到所有参与者发送的“VOTE_COMMIT”消息;
- 写本地“PREPARE_COMMIT”日志,进入PRECOMMIT状态;
- 向所有的参与者发送“PREPARE _COMMIT”消息;
- 等待并接收参与者发送的对“GLOBAL_ABORT”消息或“PREPARE_COMMIT”消息的确认响应消息。一旦收到所有参与者的“GLOBAL_ABORT”确认消息或者超时没有收到,写本地“END_TRANSACTION”日志流程结束,则不再进入DoCommit阶段。如果收到所有参与者的“PREPARE_COMMIT”确认消息,则进入DoCommit阶段。
该流程与两阶段提交协议相比,多了一个PRECOMMIT状态。
DoCommit
在该阶段,
协调者协议流程如下:
- 向所有参与者发送的“GLOBAL _COMMIT”消息;
- 等待并接收参与者发送的对 “GLOBAL_COMMIT”消息的确认响应消息,一旦收到所有参与者的确认消息,写本地“END_TRANSACTION”日志流程结束。
在DoCommit阶段,如果参与者无法及时接收到来自协调者的GLOBAL_COMMIT请求时,会在等待超时之后,会继续进行事务的提交。
三阶段提交状态机
下图为三阶段提交协议中的协调者及参与者的状态机。左侧a为协调者状态机;右侧b为参与者状态机。
三阶段提交的缺陷
相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。
参考引用
- 本文同步至: https://waylau.com/three-phase-commitment-protocol/
- 分布式事务——两阶段提交: https://waylau.com/two-phase-commitment-protocol/
- Distributed systems: principles and paradigms
- Notes on Database Operating Systems
- NonBlocking Commit Protocols
- 分布式系统常用技术及案例分析(第二版):https://github.com/waylau/distributed-systems-technologies-and-cases-analysis
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
相比Spark等传统模式,Flink 和 K8S是怎样的结合
Apache Flink 是近年来越来越流行的一款开源大数据计算引擎,它同时支持了批处理和流处理。大数据起源自批处理,Spark最初的定位就是改进Hadoop, 更快速的进行批处理。而Storm擅长的则是进行无状态的流计算(在无状态的流计算领域, 它的延迟是最小的), 进而出现的Flink则是Storm的下一代解决方案。它既可以处理stream data也可以处理batch data,可以同时兼顾Spark以及Spark streaming的功能。Flink在运行中主要有三个组件组成,JobClient,JobManager 和 TaskManager。 实时计算产品通常提供两种模式,共享型与独享型。在这样的模式下,用户不需要关心整个集群的运维。开发时,使用Blink SQL,用开箱即用的metric收集和展示。同时,作业的监控和异常时报警,也能得到保证。 新模式Flink on K8S,在功能、引擎和托管模式上,都有变化。 功能上,基于Flink的特性,它的常驻进程,类似于在线业务的App,作业发布后,修改频率比较低。用户在开发控制台提交并控制作业,可使用多样的可插拔的增值功能。 在...
- 下一篇
Spring Cloud Alibaba 之 Nacos 服务注册与发现
服务注册与发现,服务发现主要用于实现各个微服务实例的自动化注册与发现,是微服务治理的核心,学习 Spring Cloud Alibaba,首先要了解框架中的服务注册和发现组件——Nacos。 一、Spring Cloud 服务注册和发现组件 1.Spring Cloud Eureka 闭源风波 在Spring Cloud的子项目中,Spring Cloud Netflix提供了Eureka来实现服务的发现功能,Eureka的服务发现包含两大组件:服务端发现组件(EurekaServer)和客户端发现组件(Eureka Client)。Eureka的服务发现机制如图所示。 当客户端服务通过注解等方式嵌入到程序的代码中运行时,客户端发现组件就会向注册中心注册自身提供的服务,并周期性地发送心跳来更新服务,如果连续三次心跳都不能够发现服务,那么Eureka就会将这个服务节点从服务注册表中移除。各个服务之间会通过注册中心的注册信息以Rest方式来实现调用,并且可以直接通过服务名进行调用。 2012年,Netflix 将 Euerka 开源,Euerka 在 Spring Cloud 中广泛应用,...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7