文章目录
分布式事务产生的原因
产生的原因:分布式,微服务之间的跨数据库,在大型互联网里面,数据垂直分割, 按照业务的需求具体划分数据库,
所谓的本地事务:连接的同一个jdbc数据源. 这是分布式事务产生的原因我想你们也大概知道啦,因为连接的不同的jdbc数据源所以会产生分布式事务的问题
分布式事务的理解
我们可以看一下这个案例,当我们支付完成后,调用另一个服务的增加积分服务,如果此时在 支付的服务里面 积分操作完成后,出现了个一个错,那么增加了@Transactional注解的方法
问题1:积分的服务会否能够提交事务呢?
问题2: 支付的服务是否能够回滚?
问题1 答案是: 会提交,.因为他们连接的是2个jdbc数据源.他们是两个事务,他们之间的事务不受影响
问题2 答案是: 会回滚, 和上面一样,他们之间的事务不受影响
此时我们根据案例,就可以显而易见的知道,事务发生了不一致的现象,这就是分布式事务产生的原因
分布式理论知识
事务的特性
事务的特性分别: 原子,隔离,原子,持久性
事物特性(ACID)
原子性(A)
所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样。
一致性(C)
事务的执行必须保证系统的一致性,就拿转账为例,A有500元,B有300元,如果在一个事务里A成功转给B50元,那么不管并发多少,不管发生什么,只要事务执行成功了,那么最后A账户一定是450元,B账户一定是350元。
隔离性(I)
所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。
持久性(D)
所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。
这种特性 简称 刚性事物
CPA理论
• 数据一致性(consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(strong consistency) — 简称为 写即为新
• 服务可用性(availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待 — 写不可待
• 分区容错性(partition-tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务 — 分不可断
Base理论
BASE理论是指,Basically Available(基本可用)、Soft-state( 软状态/柔性事务)、Eventual Consistency(最终一致性)。是基于CAP定理演化而来,是对CAP中一致性和可用性权衡的结果。核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。
1、基本可用:指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;网页访问过大时,部分用户提供降级服务,等。 ----勇士断臂
2、软状态:软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。即允许系统在不同节点间副本同步的时候存在延时。— 存在中间状态
3、最终一致性:
系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。BASE理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID是传统数据库常用的概念设计,追求强一致性模型。—比如你调用支付宝,支付宝给你返回消息,结果你的机器宕机啦,但是支付宝总不能不给你返回消息了呀,此时如果他无法给你返回消息.那么他会等一段时间在进行发送; 就好像去朋友家,他没在家,那你就待会再去找他;总不能他不在家,你这一辈子就不去找他了呀!
ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
柔性事务和刚性事务
柔性事务满足BASE理论(基本可用,最终一致)
刚性事务满足ACID理论
本文主要围绕分布式事务当中的柔性事务的处理方式进行讨论。
柔性事务分为
- 两阶段型
- 补偿型
- 异步确保型
- 最大努力通知型几种。 由于支付宝整个架构是SOA架构,因此传统单机环境下数据库的ACID事务满足了分布式环境下的业务需要,以上几种事务类似就是针对分布式环境下业务需要设定的。
XA接口
XA是一个分布式事务协议,XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。XA实现分布式事务的原理如下:
告诉大家如何理解: 本地资源可以看成数据库,事务管理器就是管理事务的;
事务管理器可以考虑成: 老板, 本地事务可以看成员工
老板给员工发一个团建的邮件,此时员工收到邮件,回复给老板,加入说我去参加; 此时老板接收到了所有的人的答复,此时老板会安排一个团建的地点和时间,并且进行确认人员(因为有些人可能会太远不想去),此时员工进行回复,确认最后的人数;; 从上面你的列子可以看出第一阶段是准备阶段,第二阶段是确认阶段; 在第一阶段假如有个员工说不去,在XA中 他是默认关不不执行的… 这点和生活中不同
什么是Jta
作为java平台上事务规范JTA(Java Transaction API)也定义了对XA事务的支持,实际上,JTA是基于XA架构上建模的,在JTA 中,事务管理器抽象为javax.transaction.TransactionManager接口,并通过底层事务服务(即JTS)实现。像很多其他的java规范一样,JTA仅仅定义了接口,具体的实现则是由供应商(如J2EE厂商)负责提供,目前JTA的实现主要由以下几种:
1.J2EE容器所提供的JTA实现(JBoss)
2.独立的JTA实现:如JOTM,Atomikos.这些实现可以应用在那些不使用J2EE应用服务器的环境里用以提供分布事事务保证。如Tomcat,Jetty以及普通的java应用。
基于XA协议的两阶段提交
所谓的两个阶段是指:第一阶段:准备阶段(投票阶段)和第二阶段:提交阶段(执行阶段)。
XA一般由两阶段完成,称为two-phase commit(2PC)。
阶段一为准备阶段,协调者会向参与者发送一个指令,如果参与者收到指令后,会把业务逻辑是否执行成功返回给协调者
阶段二为提交阶段。只要有一发执行失败,返回给协调者,协调者会在第二阶段发出通知,告诉其他的业务进行回滚,中止提交
XA的性能问题
XA的性能很低。一个数据库的事务和多个数据库间的XA事务性能对比可发现,性能差10倍左右。因此要尽量避免XA事务,例如可以将数据写入本地,用高性能的消息系统分发数据。或使用数据库复制等技术。
只有在这些都无法实现,且性能不是瓶颈时才应该使用XA。
LCN框架的原理
当我们发起方调用参与方的时候,此时发起方会创建一个分组ID 通过http协议请求头条的形式传递给积分服务,同时也会把这个事务分组id给协调者,当积分服务受到分组事务id的时候,此时他会采用一种假关闭的形式,不会进行事务上的提交,当支付走的没有问题的情况下,此时支付服务会给协调者发起一个通知, 然后协调者会根据事务分组id找到积分服务,然后去告诉积分服务到底是提交还是回滚;
SpringCloud2.0的 LCN的基本使用
tx-lcn的具体官方地址为 http://www.txlcn.org/zh-cn/
项目代码
链接:https://pan.baidu.com/s/1o_ZBAubFU1iFGfKp3n4Diw
提取码:u189
复制这段内容后打开百度网盘手机App,操作更方便哦
1.LCN自带的框架
1.启动服务的Eureka服务
2.启动redis
3.修配配置文件
4.启动类
2.自己的服务整合LCN
1.在实现类添加两个文件
package com.antmeite.api.order.impl;
import com.codingapi.tx.netty.service.TxManagerHttpRequestService;
import com.lorne.core.framework.utils.http.HttpUtils;
import org.springframework.stereotype.Service;
/**
* create by lorne on 2017/11/18
*/
@Service
public class TxManagerHttpRequestServiceImpl implements TxManagerHttpRequestService{
@Override
public String httpGet(String url) {
System.out.println("httpGet-start");
String res = HttpUtils.get(url);
System.out.println("httpGet-end");
return res;
}
@Override
public String httpPost(String url, String params) {
System.out.println("httpPost-start");
String res = HttpUtils.post(url,params);
System.out.println("httpPost-end");
return res;
}
}
package com.antmeite.api.order.impl;
import com.codingapi.tx.config.service.TxManagerTxUrlService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* create by lorne on 2017/11/18
*/
@Service
public class TxManagerTxUrlServiceImpl implements TxManagerTxUrlService {
@Value("${tm.manager.url}")
private String url;
@Override
public String getTxUrl() {
System.out.println("load tm.manager.url ");
return url;
}
}
2.在实现类发起方添加@TxTransaction(isStart = true) 注解, 参与方为@TxTransaction
3. 增加application.yml 连接事务管理中心的地址链接
tm:
manager:
url: http://127.0.0.1:8899/tx/manager/
4.库存(参与方)服务和上面的操作一样