springcloud +seata 1.4 分布式事务,全局事务xid传递给每个方法,解决事务回滚问题
/**
* 新增公告
*
* @param notice 公告信息
* @return 结果
*/
@Override
@GlobalTransactional
public int insertNotice(SysNotice notice)
{
try {
log.info("Seata全局事务id insertNotice =================>{}", RootContext.getXID());
String xid = RootContext.getXID();
noticeMapper.insertNotice(notice);
SysJobTest sysJobTest=new SysJobTest();
sysJobTest.setXid(xid);
sysJobTest.setJobName("整数关口发送邮件提醒11");
sysJobTest.setConcurrent("1");
sysJobTest.setJobGroup("DEFAULT");
sysJobTest.setInvokeTarget("ryTask.ryNoParams");
sysJobTest.setCronExpression("0/15 * * * * ?");
sysJobTest.setStatus("1");
sysJobTest.setMisfirePolicy("3");
remoteJobService.addTest(sysJobTest);
int p=1/0;
}catch (Exception e){
try {
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
} catch (TransactionException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
return 1;
}
@Override
@Transactional
public int addTest(SysJob job) {
try{
RootContext.bind(job.getXid());
log.info("Seata全局事务id insertJobTest =================>{}", RootContext.getXID());
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
int rows = jobMapper.insertJob(job);
return rows;
}catch (Exception e){
try {
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
} catch (TransactionException e1) {
e1.printStackTrace();
}
}
return 1;
}
在调用方法中直接传参全局事务xid 给下游服务
===============服务A
@Service
public class ServiceAImpl implements IServiceA
{
private static final Logger log = LoggerFactory.getLogger(ServiceAImpl.class);
@Autowired
private IServiceB serviceB;
@Autowired
private IServiceC serviceC;
@Override
@GlobalTransactional
@Transactional
public Boolean doA() {
String XID = RootContext.getXID();
serviceB.doB(XID);
serviceC.doC(XID);
//......
}
}
===============服务B
@Service
public class ServiceBImpl implements IServiceB
{
private static final Logger log = LoggerFactory.getLogger(ServiceBImpl.class);
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Boolean doB(XID) {
RootContext.bind(XID);
//......
}
}
===============服务C
@Service
public class ServiceCImpl implements IServiceC
{
private static final Logger log = LoggerFactory.getLogger(ServiceCImpl.class);
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Boolean doC(XID) {
RootContext.bind(XID);
//......
}
}
二、undo_log表有脏数据 当Seata没有正常结束时,每个服务对应数据库中的undo_log表和seata持久化数据库的brach_table、global_table、lock_table、undo_log表都有可能有脏数据没有正确删除,从而导致服务一直回滚,却不成功 解决办法:清除undo_log表以及seata持久化数据库的brach_table、global_table、lock_table、undo_log表中的脏数据
三、Fegin调用使用了Fallback降级或抛出的异常被全局处理
这种情况下属于seata服务发现不了下游服务抛出的异常,导致事务不会触发回滚
解决办法:
(1)通过 GlobalTransactionContext.reload(RootContext.getXID()).rollback() 进行手动回滚
===============服务A
@Service
public class ServiceAImpl implements IServiceA
{
private static final Logger log = LoggerFactory.getLogger(ServiceAImpl.class);
@Autowired
private IServiceB serviceB;
@Autowired
private IServiceC serviceC;
@Override
@GlobalTransactional
@Transactional
public Boolean doA() {
Integer bStatus = serviceB.doB();
if(bStatus == 0){//在Mybatis中,返回值为0证明插入失败
//手动回滚
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
return false;
}
Integer cStatus = serviceC.doC();
if(cStatus == 0){//在Mybatis中,返回值为0证明插入失败
//手动回滚
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
return false;
}
//......
}
}
===============服务B
@Service
public class ServiceBImpl implements IServiceB
{
private static final Logger log = LoggerFactory.getLogger(ServiceBImpl.class);
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Boolean doB() {
//......
Integer insertStatus = serviceBDAO.insert();
return insertStatus;
}
}
===============服务C
@Service
public class ServiceCImpl implements IServiceC
{
private static final Logger log = LoggerFactory.getLogger(ServiceCImpl.class);
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Boolean doC() {
//......
Integer insertStatus = serviceCDAO.insert();
return insertStatus;
}
springcloud +seata 1.4 分布式事务,全局事务xid传递给每个方法,解决事务回滚问题