本文共 5116 字,大约阅读时间需要 17 分钟。
只能控制自己的回滚,控制不了其他服务的回滚。
一般用SpringBoot的@Transactional()
但是有一个坑,当你设置了事务传播行为,在同一个对象内事务方法是失效的,因为事务是基于代理的,同对象动态代理都是同一个导致不能新建新的动态代理事务就设置失败了
失败案例:
解决方案:引用aop-starter
后,使用aspectJ
,开启AspectJ动态代理
,原来默认使用的是jdk动态代理。
主启动添加@EnableAspectJAutoProxy(exposeProxy=true)
后,就取代了jdk动态代理。它没有接口也可以创建动态代理。设置true是为了对外暴露代理对象。
AopContext.currentProxy()
然后强转,就是当前代理对象。
public void a() { //调用AOP代理对象的b方法执行事务切面进行事务增强 ((AService) AopContext.currentProxy()).b(); }
问题产生最大原因是网络问题。因为网络抖动根本不知道是成功还是失败。
CAP原则又称 CAP定理,指的是在一个分布式系统中
一致性( Consistency):
可用性( Availability)
分区容错性( Partition tolerance)
CAP原则指的是这三个要素最多只能同时实现两点,不可能三者兼顾
AP
是对CAP理论的延伸,思想是即使无法做到强一致性(CAP的一致性就是强一致性),但可以采用适当的采取弱一致性,即最终一致性。
基本可用(Basically Available)
软状态( Soft State)
最终一致性( Eventual Consistency)
强一致性、弱一致性、最终一致性
2PC模式
数据库支持的2PC [2 phase commit二阶提交],又叫做XATransactionso
MySQL从5.5版本开始支持,SQL Server 2005开始支持,Oracle7 开始支持。 其中,XA是一个两阶段提交协议,该协议分为以下两个阶段:Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata术语
三组件的概念
Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
Transaction Manager™:控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
Resource Manager(RM):控制分支事务,负责分支汪册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务提交或回滚。
TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
XID在微服务调用链路的上下文中传播;
RM向TC汪册分支事务,将其纳入XID对应全局事务的管辖;
TM向TC发起针对XID的全局提交或回滚决议;
TC调度XID下管辖的全部分支事务完成提交或回请求。
AT模式:(不适合高并发场景,锁机制导致性能下降)
配置文件修改
undo_log
表 CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `branch_id` bigint(20) NOT NULL, `xid` varchar(100) NOT NULL, `context` varchar(128) NOT NULL, `rollback_info` longblob NOT NULL, `log_status` int(11) NOT NULL, `log_created` datetime NOT NULL, `log_modified` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
com.alibaba.cloud spring-cloud-starter-alibaba-seata 2.1.0.RELEASE io.seata seata-all io.seata seata-all 1.0.0
启动seata客户端必须先启动nacos客户端
spring: cloud: alibaba: seata: tx-service-group: zng #事务组名需要跟配置一样
将配置文件复制到资源目录下
代理数据源(1.3以后好像不用手动代理了)
package com.zng.springcloud.config;import com.alibaba.druid.pool.DruidDataSource;import io.seata.rm.datasource.DataSourceProxy;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.transaction.SpringManagedTransactionFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;@Configurationpublic class DataSourceProxyConfig { //使用druid代理数据源 @Value("${mybatis.mapperLocations}") private String mapperLocations; @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource(){ return new DruidDataSource(); } @Bean public DataSourceProxy dataSourceProxy(DataSource dataSource){ return new DataSourceProxy(dataSource); } @Bean public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSourceProxy); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations)); sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory()); return sqlSessionFactoryBean.getObject(); }}//排除数据源自动配置,让seata管理数据源@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
在业务入口添加@GlobalTransactional
//分布式事务,全局事务。 小事务用@Transactional
转载地址:http://igtpz.baihongyu.com/