seata的tcc模式

seata.data-source-proxy-mode=tcc

package com.i9i.seataaccount.service;

import com.i9i.commons.req.AccountReq;
import com.i9i.commons.resp.AccountResp;

import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;

@LocalTCC
public interface AccountTCCService {

	@TwoPhaseBusinessAction(name = "reduce", commitMethod = "commit", rollbackMethod = "rollBack")
	AccountResp reduce(@BusinessActionContextParameter("req") AccountReq req);

	boolean commit(BusinessActionContext cxt);

	boolean rollBack(BusinessActionContext cxt);

}
package com.i9i.seataaccount.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.i9i.commons.req.AccountReq;
import com.i9i.commons.resp.AccountResp;
import com.i9i.seataaccount.dao.AccountDao;
import com.i9i.seataaccount.dao.AccountTccRecordDao;
import com.i9i.seataaccount.enums.TccState;
import com.i9i.seataaccount.model.AccountTccRecord;
import com.i9i.seataaccount.service.AccountTCCService;

import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class AccountTCCServiceImpl implements AccountTCCService{
	@Autowired
	private AccountDao accountDao;
	
	@Autowired
	private AccountTccRecordDao accountTccRecordDao;
	@Transactional
	@Override
	public AccountResp reduce(AccountReq req) {
		//0 获取全局事务id xid
		String xid=RootContext.getXID();
//		1\ 检查是否已经执行过,如果执行过直接返回,保持幂等性,如果没有执行执行23进行资源锁定
		AccountTccRecord records=accountTccRecordDao.selectById(xid);
		if(records!=null) {//业务悬挂判断
			log.info(xid+" has executed");
			return new AccountResp();
		}
//		2\ 进行资源锁定隔离
		accountDao.reduce(req);
//		3\增加一条锁定记录,状态为try
		records=new AccountTccRecord();
		records.setXid(xid);
		records.setUserId(req.getUserId());
		records.setMoney(req.getTotalMoney());
		records.setState(TccState.TRY.ordinal());
		accountTccRecordDao.insert(records);
		return null;
	}

	@Override
	public boolean commit(BusinessActionContext cxt) {
		String xid=cxt.getXid();
		//执行删除
		int updates=accountTccRecordDao.deleteById(xid);
		return updates==1;
	}

	@Override
	public boolean rollBack(BusinessActionContext cxt) {
		//1\ 检查是否有记录,判断是否执行了try,如果没有执行增加一条锁定记录状态为rollback
		String xid=cxt.getXid();
		AccountTccRecord records=accountTccRecordDao.selectById(xid);
		// 2 如果try阶段没有执行,则有可能不存在 判断是否存在,如果不存在需要记录一条记录状态为rollback
		if(records==null) {//空回滚
			AccountReq req=cxt.getActionContext("req", AccountReq.class);
			records=new AccountTccRecord();
			records.setXid(xid);
			records.setUserId(req.getUserId());
			records.setMoney(0d);
			records.setState(TccState.ROLLBACK.ordinal());
			accountTccRecordDao.insert(records);
			return true;
		}
		//幂等判断
		if(records.getState()==TccState.ROLLBACK.ordinal()) {
			return true;
		}
		
//		3\恢复账户余额
		AccountReq req=cxt.getActionContext("req", AccountReq.class);
		accountDao.refund(req);
		
//		4\设置 冻结 金额为 rollback
	
		records.setMoney(0d);
		records.setState(TccState.ROLLBACK.ordinal());
		int updates=accountTccRecordDao.updateById(records);
		return updates==1;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值