网址:https://www.bilibili.com/video/BV1FJ411A7mV?from=search&seid=6938691415619000625
资料:
----
分布式事务的种类:
base理论是基本可用,软状态,最终一致性。
---
分布式事务的解决方案:
2pc的解决方案:
------------------------------------------------------------------------02---07-----------------------------------------------------------------------------------
1.数据库bank1和bank2
2.运行事务协调器
3.启动eureka和两个微服务。
----------------------------------------08--10------------------------------------------------------------------------------------
代码:
TM和RM是jar包的。
表:
这个表和张三数据库在同一张表是在业务层上的。
要点说明:
构建工程:
第一步导入sql
表的结构:
四个表:account_info*2 undo_log*2
数据库:192.168.244.130/131 bank1 bank2 root 123456
第二步:Seata服务端
打开:
第三步:打开eureka的注册中心
第四步:打开eureka
第五步:导入bank1和bank2
第六步:分析提交
1.TM和RM向TC注册
2.在哪里开启全局事务TM就在哪力
标识开启全局事务的起点。
3.TC返回全局事务的ID
4.RM向TC注册分支事务,分支事务的ID和全局事务的ID已经绑定了
5.写扣减逻辑。
6.向undo写入数据代理的。
7.提交事务。
8.上报事务的处理结果。
9.通过feign接口携带事务ID去增加金额。
10.向TC注册分支事务。
11.
12.
第七步:分析回滚
-------------------------------------------------------11--------12------------------------------------------------------------------
分析一些配置:
第一步:
引入这个TM和RM就有了
第二步:拷贝文件,我们在TC事务协调器拷贝这两个文件
到:
第三步:
file.conf的分组的说明,我们是文件的不是数据库的就修改这个:
service {
#vgroup->rgroup
vgroup_mapping.seata-demo-bank1-fescar-service-group = "default"
#only support single node
default.grouplist = "127.0.0.1:8888"
#degrade current not support
enableDegrade = false
#disable
disable = false
}
修改1就行,2是固定死的。
第一个名字就是微服务的注册的名字。这个是十分重要的。
default:TCC事务协调的默认的名字
这个地址是我们启动的协调器的地址。
第四步:修改配置类,配置数据源代理,Rm通过代理数据源在事务提交的时候,与TC通信交流,记录undo_log日志等。
@Configuration
public class DatabaseConfiguration {
private final ApplicationContext applicationContext;
public DatabaseConfiguration(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.ds0")
public DruidDataSource ds0() {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Primary
@Bean
public DataSource dataSource(DruidDataSource ds0) {
DataSourceProxy pds0 = new DataSourceProxy(ds0);
return pds0;
}
}
我们根据这个去配置去yml文件查看下。
---------------------------------------------------------------------13-----------------------------------------------------------------
案例是张三给李四转账:
第一步:写DAO
第二步:写Service
/**
* @author Administrator
* @version 1.0
**/
@Service
@Slf4j
public class AccountInfoServiceImpl implements AccountInfoService {
@Autowired
AccountInfoDao accountInfoDao;
@Autowired
Bank2Client bank2Client;
@Transactional //开启本地事务
@GlobalTransactional//开启全局事务 只开启一次
@Override
public void updateAccountBalance(String accountNo, Double amount) {
log.info("bank1 service begin,XID:{}", RootContext.getXID());
//扣减张三的金额
accountInfoDao.updateAccountBalance(accountNo,amount *-1);
//调用李四微服务,转账
String transfer = bank2Client.transfer(amount);
if("fallback".equals(transfer)){
//调用李四微服务异常
throw new RuntimeException("调用李四微服务异常");
}
if(amount == 2){
//人为制造异常
throw new RuntimeException("bank1 make exception..");
}
}
}
第三步:写Feign
@FeignClient(value="seata-demo-bank2",fallback=Bank2ClientFallback.class)
public interface Bank2Client {
//远程调用李四的微服务
@GetMapping("/bank2/transfer")
public String transfer(@RequestParam("amount") Double amount);
}
第四步:写controller。
---------------------------------------------------------------------14-----------------------------------------------------------------
李四的微服务:
@Transactional
@Override
public void updateAccountBalance(String accountNo, Double amount) {
log.info("bank2 service begin,XID:{}",RootContext.getXID());
//李四增加金额
accountInfoDao.updateAccountBalance(accountNo,amount);
if(amount==3){
//人为制造异常
throw new RuntimeException("bank2 make exception..");
}
}
---------------------------------------------------------------------15-----------------------------------------------------------------
测试:
第一步:启动三个工程,启动TC 协调器。
第二步:测试
1.正常的时候:http://localhost:56081/bank1/transfer?amount=1
2.给李四转的是3元,但是李四是异常的。
通过上下文拿到事务的id。
李四失败了张三回滚,张三失败了李四回滚。
在都未处理完成之后undolog日志会记录更新前和更新后的账户的信息的。
抛异常后自动生成update语句进行回滚。
3.超时:也会回滚
注意一点:每个数据库都要有undo_log这个表是本地事务一致性的关键,因为本地事务执行完都要提交的。
这里面记录了更新前的数据和更新后的数据。
抛出异常就根据日志回滚。
---------------------------------------------------------------------16-----------------------------------------------------------------
undolog日志,记录更新前的数据和更新后的数据。根据undolog日志自动生成update语句进行更新。
只要 回滚就删除undolog日志。