1、事务的概念算法
事务是一组操做的执行单元,相对于数据库操做来说,事务管理的是一组SQL指令,好比增长,修改,删除等,事务的一致性,要求,这个事务内的操做必须所有执行成功,若是在此过程种出现了差错,好比有一条SQL语句没有执行成功,那么这一组操做都将所有回滚数据库
最经典的例子即是:A向B汇款500元,B帐户多了500元,这整个过程,要么所有正常执行,要么所有回滚,否则就会出现A扣款,B收不到钱,或者A没扣款,B收到500元的状况,这种场景是灾难性的。编程
事务特性(ACID)
(1)Atomic(原子性):要么都成功,要么都失败
(2)Consistent(一致性):数据应该不被破坏
(3)Isolate(隔离性):用户间操做不相混淆
(4)Durable(持久性):永久保存 服务器
2、本地事务和分布式事务网络
本地事务:本地事务是在同一个JVM实例中调用不一样的资源造成事务,紧密依赖于底层资源管理器(例如数据库链接 ),事务处理局限在当前事务资源内。此种事务处理方式不存在对其余应用服务器或实例的依赖。分布式
如上述说到的汇款案例来讲,若两个过程都在同一个JVM实例中,使用同个数据库链接,则事务比较好控制,以下图:函数
分布式事务:分布式事务是在一个JVM实例中调用不一样的服务造成事务,不一样的服务可能不在同一个JVM实例中,可能涉及到操做多个数据库的事务,必须保证每一个独立节点上的数据操做能够知足ACID。spa
如上述说到的汇款案例来讲,若两个过程在不一样的JVM实例中,使用不一样的数据库链接,则事务很差控制,缘由是A,B没法知道事务在其余地方所作的全部动做,没法实现事务的一致性,以下图,A,B各自使用本身的事务管理完成begin,commit,rollback等操做,AB整个过程是没法实现事务一致性的。日志
3、对分布式事务的处理中间件
在分布式系统中,各个节点之间在物理上相互独立,经过网络进行沟通和协调。可是相互独立的节点没法知道其余节点的事务执行状况,要保证全部节点上的写操做,要么所有提交,要么所有rollback,最好的办法就是引入coordinator,即协调者来协调和通知各个节点上的事务执行状况。
Java 事务编程接口(JTA:Java Transaction API)和 Java 事务服务 (JTS:Java Transaction Service) 为 J2EE 平台提供了分布式事务服务。分布式事务(Distributed Transaction)包括事务管理器(Transaction Manager)和一个或多个支持 XA 协议的资源管理器 ( Resource Manager )。咱们能够将资源管理器看作任意类型的持久化数据存储;事务管理器承担着全部事务参与单元的协调与控制。
因为事务管理器统一管理全部事务参与单元,则全部事务参与单元都应实现同一套协议,才方便事务管理器的管理,就好似一个老师A管理一班学生,全部学生按照老师约定好的形式完成做业,以后交由同一个老师批改,批改后统一退回。若同一个做业,部分学生按照A老师的标准完成,部分同窗按照B老师的标准完成,再提交上去批改,则最终获得的结果就可能互相不一致了。
4、XA协议
分布式事务中,全部的事务单元都须要实现统一的协议,XA 就是定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。 XA 接口函数由数据库厂商,或消息中间件厂商提供。
以下图,咱们能够将 JTA 的事务管理器和资源管理器理解为两个方面:面向开发人员的使用接口(事务管理器)和面向服务提供商的实现接口(资源管理器),开发人员使用开发人员接口,实现应用程序对全局事务的支持;各提供商(数据库,消息中间件等)依据提供商接口(即XA接口)的规范提供事务资源管理功能;事务管理器( Transaction Manager )将应用对分布式事务的使用映射到实际的事务资源并在事务资源间进行协调与控制,使得 JTA 能够在异构事务资源之间执行协同沟通。
5、强一致性事务实现原理
2PC,即二阶段提交,是分布式事务中一个很重要的协议,当一个事务跨越多个节点时,为了保持事务的ACID特性,须要引入一个coordinator,即协调者做为的组件来统一掌控全部节点(称做参与者)的操做结果并最终指示这些节点是否要把操做结果进行真正的提交或回滚。
二阶段提交的算法思路能够归纳为: 参与者将操做成败通知协调者,再由协调者根据全部参与者的反馈情报决定各参与者是否要提交操做仍是回滚操做。
各参与者成功提交事务流程:
(1)在一个有A,B,C参与的事务中,引入一个协调者,用来协调和通知各参与者执行相应的事务动做,其中黑线为协调者发起的指令,红线为参与者响应的指令。
(2)协调者通知全部参与者节点准备提交事务,参与者节点执行事务操做,并将Undo信息和Redo信息写入日志,但此时不提交事务。
(3)协调者收到各参与者准备提交完成的指令,没有任何节点出错,此时通知全部节点提交事务。
(4)参与者节点正式完成提交操做,并释放在整个事务期间内占用的资源。
(5)协调者收到全部参与者确认提交完毕的答复,此时整个事务完成。
各参与者提交事务失败流程:
(1)在一个有A,B,C参与的事务中,引入一个协调者,用来协调和通知各参与者执行相应的事务动做,其中黑线为协调者发起的指令,红线为参与者响应的指令。
(2)协调者通知全部参与者节点准备提交事务,参与者节点执行事务操做,并将Undo信息和Redo信息写入日志,但此时不提交事务,但此时B节点在准备执行操做事务时出现了异常,则返回给协调者准备失败的响应信息
(3)协调者虽然收到A跟C准备完成的响应,但B返回的状态是准备失败,此时进入通知全部参与者回滚的阶段
(4)参与者节点正式完成回滚操做,并释放在整个事务期间内占用的资源。
(5)协调者收到全部参与者确认回滚完毕的答复,此时整个事务完成
结论:无论最后结果如何,第二阶段都会结束当前事务。
建议:少使用分布式事务,在分布式事务这个问题上,还不多有成熟牛逼的产品,并且分布式事务过程当中,涉及到了各个节点的通知,二次通知,当节点多的时候,协调者的压力巨大,并且整个流程对业务的时间开销是巨大的,因此建议谨慎使用分布式事务,即便二阶段看似能处理好分布式节点的ACID问题,可是其自己也存在不小的问题。
一、同步阻塞问题。执行过程当中,全部参与节点都是事务阻塞型的。当参与者占有公共资源时,其余第三方节点访问公共资源不得不处于阻塞状态。
二、单点故障。因为协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤为在第二阶段,协调者发生故障,那么全部的参与者还都处于锁定事务资源的状态中,而没法继续完成事务操做。(若是是协调者挂掉,能够从新选举一个协调者,可是没法解决由于协调者宕机致使的参与者处于阻塞状态的问题)
三、数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求以后,发生了局部网络异常或者在发送commit请求过程当中协调者发生了故障,这回致使只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求以后就会执行commit操做。可是其余部分未接到commit请求的机器则没法执行事务提交。因而整个分布式系统便出现了数据部一致性的现象。
四、二阶段没法解决的问题:协调者再发出commit消息以后宕机,而惟一接收到这条消息的参与者同时也宕机了。那么即便协调者经过选举协议产生了新的协调者,这条事务的状态也是不肯定的,没人知道事务是否被已经提交。
注:二阶段提交的缺点描述引用来自http://blog.jobbole.com/95632/。