事务的概念
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。从而确保了数据的准确与安全
本地事务(回顾)
事务的四大特性
1)原子性
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2)一致性
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
例如转账前A有1000,B有1000。转账后A+B也得是2000。
3)隔离性
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,每个事务不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
4)持久性
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
事务的隔离级别
1)不考虑隔离级别,会出现以下情况:(以下情况全是错误的)
脏读:一个线程中的事务读到了另外一个线程中未提交的数据。
不可重复读:一个线程中的事务读到了另外一个线程中已经提交的update的数据(前后内容不一样)
虚读(幻读):一个线程中的事务读到了另外一个线程中已经提交的insert的数据(前后条数不一样)
2)数据库共定义了四种隔离级别:
Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化) 最高
Repeatable read:可避免脏读、不可重复读情况的发生。(有可能发生幻读) 第二
Read committed:可避免脏读情况发生。 第三
Read uncommitted:最低级别,以上情况均无法保证。(读未提交) 最低
注意:级别依次升高,效率依次降低
MySQL的默认隔离级别是:REPEATABLE READ。(Oracle的默认是:READ COMMITTED)
分布式事务(正餐)
分布式事务概念
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单来说就是组成事务的各个单元处于不同数据库服务器上
分布式事务解决方案分类
1)刚性事务
刚性事务指的就是遵循本地事务四大特性(ACID)的强一致性事务。它的特点就是强一致性,要求组成事务的各个单元马上提交或者马上回滚,没有时间弹性,要求以同步的方式执行。通常在单体架构项目中应用较多,一般都是企业级应用(或者局域网应用)。例如:生成合同时记录日志,付款成功后生成凭据等等。但是,在时下流行的互联网项目中,这种刚性事务来解决分布式事务就会有很多的弊端。其中最明显的或者说最致命的就是性能问题
因为某个参与者不能自己提交事务,必须等待所有参与者执行OK了之后,一起提交事务,那么事务锁住的时间就变得非常长,从而导致性能非常低下。基于此我们也就得出了一个结论,阶段越多,性能越差
2)柔性事务
柔性事务是针对刚性事务而说的,我们刚才分析了刚性事务,它有两个特点,第一个强一致性,第二个近实时性(NRT)。而柔性事务的特点是不需要立刻马上执行(同步性),且不需要强一致性。它只要满足基本可用和最终一致就可以了。详细了解可参考BASE理论和CAP理论
3)再谈刚性事务和柔性事务的比较
事务类型 | 时间要求 | 一致性要求 | 应用类型 | 应用场景 |
---|---|---|---|---|
刚性事务 | 立即 | 强一致性 | 企业级应用(单体架构) | 订单/订单项/日志 |
柔性事务 | 有时间弹性 | 最终一致性 | 互联网应用(分布式架构) | 订单/支付/库存 |
分布式事务解决方案
二阶段提交(2PC)方案详述
DTP标准(DTP模型)
名称 | 简称 | 说明 |
---|---|---|
应用程序(Application Program) | AP | 用于定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作。 |
资源管理器(Resource Manager) | RM | 如数据库、文件系统等,并提供访问资源的方式。 |
事务管理器(Transaction Manager ) | TM | 负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等。 |
通信资源管理器(CommunicationResource Manager) | CRM | 控制一个TM域(TM domain)内或者跨TM域的分布式应用之间的通信。 |
通信协议(CommunicationProtocol) | CP | 提供CRM提供的分布式应用节点之间的底层通信服务。 |
一个DTP模型最少需要包含AP,TM和RM三部分组成,如下图所示:
这张图类似于我们之前提到的跨库事务的概念,即单个应用需要操作多个库。在这里就是一个AP需要操作多个RM上的资源。AP通过TM来声明一个全局事务,然后操作不同的RM上的资源,最后通知TM来提交或者回滚全局事务。
XA协议规范
XA协议是资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax开头的。
----
以DTP本地模型实例中,由AP、RMs和TM组成,不需要其他元素。AP、RM和TM之间,彼此都需要进行交互,如下图所示
JTA
JTA,它是XA协议的Java版本规范。全称是Java Transaction API。它是JavaEE的13个规范之一。
&
是基于Java语言开发分布式事务二阶段提交的标准。而要想真正的使用,必须使用它的实
现。在早期我们都学习过JavaEE容器技术(也有称为服务器或中间件的),像Tomcat,weblogic ,websphere,
JBOSS,Jetty,Resin等等。这里面有轻量级,也有重量级。凡是重量级服务器都是完整实现了JavaEE规范的,也就是说可以直接使用JTA的实现。除了完整的实现了JavaEE规范的容器外,还有单独针对JTA进行实现的,像atomikos,JOTM。
atomikos
atomikos是一款开源的,且实现了JTA规范的分布式事务解决方案,可以在github,官方网站上下载它的资料。在github上可以看到它的亮点,如下图:
从上面,我们可以看出,它支持java的分布式事务管理,支持微服务,支持JDBC连接池和JMS消息机制。在早期的二阶段提交方式的分布式事务技术选型中,它的出场几率是非常高的。
TCC补偿方案
关于TCC
TCC分别指的是Try,Confirm,Cancel。它是补偿型分布式事务解决方案。何为补偿呢?其实我们把TCC这3个部分分别做什么捋清楚,就很容理解了。首先,我们先来看下它们的主要作用:
·
Try 阶段主要是对业务系统做检测及资源预留
·
Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
·
Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
由此,我们可以得出结论,就是在Try阶段进行尝试提交事务,当Try执行OK了,Confirm执行,且默认认为它一定成功。但是当Try提交失败了,则由Cancel处理回滚和资源释放。
TCC流程图
TCC和2PC的优劣分析
最终一致性方案
本地消息表
1)简述
这种实现方式应该是业界使用最多的,其核心思想是将分布式事务拆分成本地事务进行处理,这种思路是来源于ebay。它和MQ事务消息的实现思路都是一样的,都是利用MQ通知不同的服务实现事务的操作。不同的是,针对消息队列的信任情况,分成了两种不同的实现。本地消息表它是对消息队列的稳定性处于不信任的态度,认为消息可能会出现丢失,或者消息队列的运行网络会出现阻塞,于是在数据库中建立一张独立的表,用于存放事务执行的状态,配合消息队列实现事务的控制
2)优缺点
优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。
缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。
MQ事务消息
1)简述
有一些第三方的MQ是支持事务消息的,比如RocketMQ,ActiveMQ,他们支持事务消息的方式也是类似于采用的二阶段提交。但是有一些常用的MQ也不支持事务消息,比如 RabbitMQ 和 Kafka 都不支持。
以阿里的 RocketMQ 中间件为例,其思路大致为:
第一阶段Prepared消息,会拿到消息的地址。
第二阶段执行本地事务。
第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。
也就是说在业务方法内要想消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了RocketMQ会定期扫描消息集群中的事务消息,这时候发现了Prepared消息,它会向消息发送者确认,所以生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。下图描述了它的工作原理:
2)它和本地消息表的对比
具体应用及项目改造未完待续。。。。