后面的文章中,咱们介绍了分布式系统中的CAP实践和BASE实践,本文会就分布式事务的实现计划之一:两阶段提交(2PC)进行介绍。2PC是一个十分经典的强统一、中心化的原子提交协定。中心化是指协定中有两类节点:一个是中心化协调者节点(coordinator)和N个参与者节点(partcipant)。
2PC
一致性概念
一致性,是指对每个节点一个数据的更新,整个集群都晓得更新,并且是统一的,假如一个具备N个节点的分布式系统,当其满足以下条件时,咱们说这个零碎满足一致性:
- 全认同: 所有N个节点都认同一个后果;
- 值非法: 该后果必须由N个节点中的过半节点提出;
- 可完结: 决定过程在肯定工夫内完结,不会无休止地进行上来;
一致性的挑战
消息传递异步无序: 事实网络不是一个牢靠的信道,存在音讯延时、失落,节点间消息传递做不到同步有序:
- 节点宕机: 节点继续宕机,不会复原;
- 节点宕机复原: 节点宕机一段时间后复原,在分布式系统中最常见;
- 网络分化: 网络链路呈现问题,将N个节点隔离成多个局部;
- 拜占庭将军问题: 节点或宕机或逻辑失败,甚至不按套路出牌抛出烦扰决定的信息。
2PC原理
2PC(tow phase commit)两阶段提交。所谓的两个阶段是指:
- 第一阶段:筹备阶段(投票阶段)
- 第二阶段:提交阶段(执行阶段)。
咱们将提议的节点称为协调者(coordinator),其余参加决定节点称为参与者(participants, 或cohorts)。
2PC第一阶段
2PC的第一阶段是投票环节,投票由协调者节点发动,能够进一步细分为以下步骤:
- 事务询问:协调者向所有的参与者发送事务预处理申请,称之为Prepare,并开始期待各参与者的响应。
- 执行本地事务:各个参与者节点执行本地事务操作,但在执行实现后并不会真正提交数据库本地事务,而是先向协调者报告说:“我这边能够解决了/我这边不能解决”。
- 各参与者向协调者反馈事务询问的响应:如果参与者胜利执行了事务操作,那么就反馈给协调者Yes响应,示意事务能够执行,如果没有参与者胜利执行事务,那么就反馈给协调者No响应,示意事务不能够执行。
第一阶段执行完后,会有两种可能。1、所有都返回Yes. 2、有一个或者多个返回No。
2PC第二阶段:失常提交
如果第一阶段所有的参与者都返回Yes,那么咱们就能够继续执行2PC第二阶段的失常提交步骤:
- 协调者节点告诉所有的参与者Commit事务申请;
- 参与者收到Commit申请之后,就会正式执行本地事务Commit操作,并在实现提交之后开释整个事务执行期间占用的事务资源。
2PC第二阶段:异样回滚
如果任何一个参与者向协调者反馈了No响应,或者期待超时之后,协调者尚未收到所有参与者的反馈响应,那么咱们就须要执行2PC第二阶段的回滚操作:
- 协调者节点告诉所有的参与者Rollback申请;
- 参与者收到Rollback申请之后,就会正式执行本地事务Rollback操作,并在实现提交之后开释整个事务执行期间占用的事务资源。
2PC存在的问题
通过下面的演示,很容易想到2pc所带来的缺点:
- 性能问题:无论是在第一阶段的过程中,还是在第二阶段,所有的参与者资源和协调者资源都是被锁住的,只有当所有节点筹备结束,事务 协调者 才会告诉进行全局提交,参与者进行本地事务提交后才会开释资源。这样的过程会比拟漫长,对性能影响比拟大。
- 单节点故障:因为协调者的重要性,一旦协调者产生故障。参与者会始终阻塞上来。尤其在第二阶段,协调者产生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无奈持续实现事务操作。(尽管协调者挂掉,能够从新选举一个协调者,然而无奈解决因为协调者宕机导致的参与者处于阻塞状态的问题)。
2PC节点故障的状况
协调者失常,参与者宕机
因为协调者无奈收集到所有参与者的反馈,会陷入阻塞状况。解决方案:引入超时机制,如果协调者在超过指定的工夫还没有收到参与者的反馈,事务就失败,向所有节点发送终止事务申请。
协调者宕机,参与者失常
无论处于哪个阶段,因为协调者宕机,无奈发送提交申请,所有处于执行了操作然而未提交状态的参与者都会陷入阻塞状况。解决方案:引入协调者备份,同时协调者需记录操作日志.当检测到协调者宕机一段时间后,协调者备份取代协调者,并读取操作日志,向所有参与者询问状态。
协调者和参与者都宕机
如果产生在第一阶段: 因为第一阶段,所有参与者都没有真正执行commit,所以只需从新在残余的参与者中从新选出一个协调者,新的协调者在从新执行第一阶段和第二阶段就能够了。
产生在第二阶段并且挂了的参与者在挂掉之前没有收到协调者的指令:也就是下面的第2步挂了,这是可能协调者还没有发送第2步就挂了。这种情景下,新的协调者从新执行第一阶段和第二阶段操作。
产生在第二阶段并且有局部参与者曾经执行完commit操作:就好比这里订单服务A和领取服务B都收到协调者发送的commit信息,开始真正执行本地事务commit,但突发状况,A commit胜利,B挂了。这个时候目前来讲数据是不统一的。尽管这个时候能够再通过伎俩让他和协调者通信,再想方法把数据搞成统一的,然而,这段时间内他的数据状态曾经是不统一的了! 2PC无奈解决这个问题。
mysql对XA事务的反对
MySQL 从5.0.3开始反对XA分布式事务,且只有InnoDB存储引擎反对。MySQL Connector/J 从5.0.0版本之后开始间接提供对XA的反对。
须要留神的是, 在DTP模型中,mysql属于资源管理器(RM)。而一个残缺的分布式事务中,个别会存在多个RM,由事务管理器TM来对立进行协调。因而,这里所说的mysql对XA分布式事务的反对,个别指的是单台mysql实例如何执行本人的事务分支。
XA {START|BEGIN} xid [JOIN|RESUME] //开启XA事务,如果应用的是XA START而不是XA BEGIN,那么不反对[JOIN|RESUME],xid是一个惟一值,示意事务分支标识符XA END xid [SUSPEND [FOR MIGRATE]] //完结一个XA事务,不反对[SUSPEND [FOR MIGRATE]]XA PREPARE xid 筹备提交XA COMMIT xid [ONE PHASE] //提交,如果应用了ONE PHASE,则示意应用一阶段提交。两阶段提交协定中,如果只有一个RM参加,那么能够优化为一阶段提交XA ROLLBACK xid //回滚XA RECOVER [CONVERT XID] //列出所有处于PREPARE阶段的XA事务
JTA的实现
Java事务API(JTA:Java Transaction API)和它的同胞Java事务服务(JTS:Java Transaction Service),为J2EE平台提供了分布式事务服务(distributed transaction)的能力。 某种程度上,能够认为JTA标准是XA标准的Java版,其把XA标准中规定的DTP模型交互接口形象成Java接口中的办法,并规定每个办法要实现什么样的性能。在DTP模型中,规定了模型的五个组成元素:应用程序(Application)、资源管理器(Resource Manager)、事务管理器(Transaction Manager)、通信资源管理器(Communication Resource Manager)、 通信协议(Communication Protocol)。而在JTA标准中,模型中又多了一个元素Application Server,如下所示:
上面介绍一下在JTA标准中,模型中各个组件的作用:
事务管理器(transaction manager):
处于图中最为外围的地位,其余的事务参与者都是与事务管理器进行交互。事务了管理器提供事务申明,事务资源管理,同步,事务上下文流传等性能。JTA标准定义了事务管理器与其余事务参与者交互的接口,而JTS标准定义了事务管理器的实现要求,因而咱们看到事务管理器底层是基于JTS的。
应用服务器(application server):
顾名思义,是利用程序运行的容器。JTA标准规定,事务管理器的性能应该由application server提供,如上图中的EJB Server。一些常见的其余web容器,如:jboss、weblogic、websphere等,都能够作为application server,这些web容器都实现了JTA标准。特地须要留神的是,并不是所有的web容器都实现了JTA标准,如tomcat并没有实现JTA标准,因而并不能提供事务管理器的性能。
应用程序(application):
简略来说,就是咱们本人编写的利用,部署到了实现了JTA标准的application server中,之后咱们就能够咱们JTA标准中定义的UserTransaction类来申明一个分布式事务。通常状况下,application server为了简化开发者的工作量,并不一定要求开发者应用UserTransaction来申明一个事务,开发者能够在须要应用分布式事务的办法上增加一个注解,就像spring的申明式事务一样,来申明一个分布式事务。
特地须要留神的是,JTA标准规定事务管理器的性能由application server提供。然而如果咱们的利用不是一个web利用,而是一个本地利用,不须要被部署到application server中,无奈应用application server提供的事务管理器性能。又或者咱们应用的web容器并没有事务管理器的性能,如tomcat。对于这些状况,咱们能够间接应用一些第三方的事务管理器类库,如JOTM和Atomikos。将事务管理器间接整合进利用中,不再依赖于application server。
资源管理器(resource manager):
实践上任何能够存储数据的软件,都能够认为是资源管理器RM。最典型的RM就是关系型数据库了,如mysql,另外一种比拟常见的资源管理器是消息中间件,如ActiveMQ、RabbitMQ等, 这些都是真正的资源管理器。
事实上,将资源管理器(resource manager)称为资源适配器(resource adapter)仿佛更为适合。因为在java程序中,咱们都是通过client来于RM进行交互的,例如:咱们通过mysql-connector-java-x.x.x.jar驱动包,获取Conn、执行sql,与mysql服务端进行通信;通过ActiveMQ、RabbitMQ等的客户端,来发送音讯等。
失常状况下,一个数据库驱动供应商只须要实现JDBC标准即可,一个消息中间件供应商只须要实现JMS标准即可。 而引入了分布式事务的概念后,DB、MQ等在DTP模型中的作用都是RM,二者是等价的,须要由TM对立进行协调。
为此,JTA标准定义了一个XAResource接口,其定义RM必须要提供给TM调用的一些办法。之后,不论这个RM是DB,还是MQ,TM并不关怀,因为其操作的是XAResource接口。而其余标准(如JDBC、JMS)的实现者,同时也对此接口进行实现。如MysqlXAConnection,就实现了XAResource接口。
通信资源管理器(Communication Resource Manager):
这个是DTP模型中就曾经存在的概念,对于须要跨利用的分布式事务,事务管理器彼此之间须要通信,这是就是通过CRM这个组件来实现的。JTA标准中,规定CRM须要实现JTS标准定义的接口。
下图更加直观的演示了JTA标准中各个模型组件之间是如何交互的:
交互状况如下:
- application运行在application server中;
- application 须要拜访3个资源管理器(RM)上资源:1个MQ资源和2个DB资源;
- 因为这些资源服务器是独立部署的,如果须要同时进行更新数据的话并保障一致性的话,则须要应用到分布式事务,须要有一个事务管理器来对立协调;
- Application Server提供了事务管理器的性能;
- 作为资源管理器的DB和MQ的客户端驱动包,都实现了XAResource接口,以供事务管理器调用。
参考文章
mysql 对XA事务的反对
3.0 JTA标准
我是御狐神,欢送大家关注我的微信公众号:wzm2zsd
本文最先公布至微信公众号,版权所有,禁止转载!