Tcc-transaction is the open source tcc distributed transaction framework of github. Compared with other tcc open source frameworks, tcc-transaction ranks first in the number of stars. It can be processed asynchronously or synchronously.
Github User Guide 1.2.x: https://github.com/changmingxie/tcc-transaction/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%971.2.x
tcc three stages
Try: Try to execute business
完成所有业务检查(一致性)
预留必须业务资源(准隔离性)
Confirm: Confirm execution of business
真正执行业务
不作任何业务检查
只使用Try阶段预留的业务资源
Confirm操作满足幂等性
Cancel: Cancel execution of business
释放Try阶段预留的业务资源
Cancel操作满足幂等性
maven configuration
<!--tcc-transaction核心包-->
<dependency>
<groupId>org.mengyun</groupId>
<artifactId>tcc-transaction-spring</artifactId>
<version>1.2.12</version>
</dependency>
<!--tcc-transaction整合dubbo核心包-->
<dependency>
<groupId>org.mengyun</groupId>
<artifactId>tcc-transaction-dubbo</artifactId>
<version>1.2.12</version>
<exclusions>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</exclusion>
<exclusion>
<artifactId>zookeeper</artifactId>
<groupId>org.apache.zookeeper</groupId>
</exclusion>
<exclusion>
<artifactId>curator-recipes</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
</exclusions>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>2.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.7</version>
</dependency>
</dependency>
First, you need to configure the config of the tcc service and the remote tcc service
tcc service configuration
@Configuration
public class TccConfig {
@Bean
public DefaultRecoverConfig defaultRecoverConfig(){
DefaultRecoverConfig defaultRecoverConfig = new DefaultRecoverConfig();
defaultRecoverConfig.setMaxRetryCount(30); //最大重试次数
defaultRecoverConfig.setRecoverDuration(30); //恢复持续时间
defaultRecoverConfig.setCronExpression("0/30 * * * * ?"); //每30秒检查一次是否需要恢复(检查对应的日志表有无需要恢复的数据)//每30秒检查一次是否需要恢复
defaultRecoverConfig.setDelayCancelExceptions(Sets.newHashSet(org.apache.dubbo.remoting.TimeoutException.class));
return defaultRecoverConfig;
}
@Bean("transactionRepository")
public SpringJdbcTransactionRepository springJdbcTransactionRepository(){
SpringJdbcTransactionRepository springJdbcTransactionRepository = new SpringJdbcTransactionRepository();
springJdbcTransactionRepository.setDomain("CONSUMER"); //domain
springJdbcTransactionRepository.setTbSuffix("_CONSUMER"); //配置tcc日志表名称后缀:这里为:tcc_transaction_consumer
//tcc所需分布式事务日志数据源(也可以使用其他数据源框架)
HikariDataSource hikariDataSource = new HikariDataSource();
hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
hikariDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/tcc?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=CTT");
hikariDataSource.setUsername("root");
hikariDataSource.setPassword("root");
springJdbcTransactionRepository.setDataSource(hikariDataSource);
return springJdbcTransactionRepository;
}
}
Remote tcc service configuration, only need to modify the following two codes, other configurations are the same
springJdbcTransactionRepository.setDomain("PROVIDER");
springJdbcTransactionRepository.setTbSuffix("_PROVIDER"); //配置tcc日志表名称后缀:这里为:tcc_transaction_provider
- service defines the three stages of tcc service
asyncConfirm = false:是否异步处理confirm阶段,默认false,也就是同步处理
asyncCancel = false:是否异步处理cancel阶段,默认false,也就是同步处理
@Service
public class TccService{
@DubboReference(check = false, retries = 0, timeout = 30000) //dubbo rpc远程过程调用
private TestService testService;
@Override
@Transactional
@Compensable(confirmMethod = "commit", cancelMethod = "rollback", asyncConfirm = false, asyncCancel = false, delayCancelExceptions = {
SocketTimeoutException.class, org.apache.dubbo.remoting.TimeoutException.class})
public void doTry(@UniqueIdentity TransactionContext transactionContext, String accountNo, String to, BigDecimal amount) {
//try阶段
testService.remoteDoTry(transactionContext, accountNo, amount);
}
//如果try阶段成功,commit阶段必须成功,如果commit阶段抛出异常,则会重试commit阶段
@Transactional
public void commit(TransactionContext transactionContext, String accountNo, String to, BigDecimal amount) {
//commit阶段
}
@Transactional
public void rollback(TransactionContext transactionContext, String accountNo, String to, BigDecimal amount) {
//rollback阶段
}
Controller call:
@RestController
public class TestController {
@Autowired
private TccService tccService;
@GetMapping("tcc")
@ResponseBody
public String tcc(String from, String to, BigDecimal amount) throws Exception {
try{
tccService.doTry(null, from, to, amount);
return "success";
} catch (Exception e){
return "fail:" + e.getMessage();
} finally {
System.out.println("success finally");
}
}
}
- service defines three stages of remote tcc service
@Override
@Transactional
@Compensable(confirmMethod = "remoteCommit", cancelMethod = "remoteRollback", asyncConfirm = false, asyncCancel = false, delayCancelExceptions = {
SocketTimeoutException.class, org.apache.dubbo.remoting.TimeoutException.class})
public void remoteDoTry(@UniqueIdentity TransactionContext transactionContext, String accountNo, BigDecimal amount) {
//try阶段
}
//如果try阶段成功,commit阶段必须成功,如果commit阶段抛出异常,则会重试commit阶段
@Transactional
public void remoteCommit(TransactionContext transactionContext, String accountNo, BigDecimal amount) {
//commit阶段
}
@Transactional
public void remoteRollback(TransactionContext transactionContext, String accountNo, BigDecimal amount) {
//rollback阶段
}
TestService interface, pay attention to the @Compensable
annotation on the remote interface
@Compensable
void remoteDoTry(TransactionContext transactionContext, String accountNo, BigDecimal amount);
The core code has been completed, configure the startup class
@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo //启动dubbo配置与注解
@EnableAspectJAutoProxy //启动切面类
@ImportResource(locations = {
"classpath:tcc-transaction.xml", "classpath:tcc-transaction-dubbo.xml"}) //加载框架tcc-transaction配置
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
tcc database configuration
Tcc configuration database, because the database name configured as a front tcc, and tcc service configuration table suffix _CONSUMER
, remote tcc service configuration table suffix _PROVIDER
, so tcc create two tables in the database, the following is sql script
sql script, fields are The same, the only difference is the table name suffix
CREATE TABLE `tcc_transaction_consumer` (
`TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,
`DOMAIN` varchar(100) DEFAULT NULL,
`GLOBAL_TX_ID` varbinary(32) NOT NULL,
`BRANCH_QUALIFIER` varbinary(32) NOT NULL,
`CONTENT` varbinary(8000) DEFAULT NULL,
`STATUS` int(11) DEFAULT NULL,
`TRANSACTION_TYPE` int(11) DEFAULT NULL,
`RETRIED_COUNT` int(11) DEFAULT NULL,
`CREATE_TIME` datetime DEFAULT NULL,
`LAST_UPDATE_TIME` datetime DEFAULT NULL,
`VERSION` int(11) DEFAULT NULL,
`IS_DELETE` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`TRANSACTION_ID`),
UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)
) ENGINE=InnoDB AUTO_INCREMENT=378 DEFAULT CHARSET=utf8;
CREATE TABLE `tcc_transaction_provider` (
`TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,
`DOMAIN` varchar(100) DEFAULT NULL,
`GLOBAL_TX_ID` varbinary(32) NOT NULL,
`BRANCH_QUALIFIER` varbinary(32) NOT NULL,
`CONTENT` varbinary(8000) DEFAULT NULL,
`STATUS` int(11) DEFAULT NULL,
`TRANSACTION_TYPE` int(11) DEFAULT NULL,
`RETRIED_COUNT` int(11) DEFAULT NULL,
`CREATE_TIME` datetime DEFAULT NULL,
`LAST_UPDATE_TIME` datetime DEFAULT NULL,
`VERSION` int(11) DEFAULT NULL,
`IS_DELETE` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`TRANSACTION_ID`),
UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)
) ENGINE=InnoDB AUTO_INCREMENT=378 DEFAULT CHARSET=utf8;
Finally, attach a picture of using the apache jmeter stress test tool: the test is 100 threads, each thread has a throughput of 10, and the test data is accurate:
调用处理次数1000次没有问题,数据库数据也没有问题 !
At this point, the tcc distributed transaction is complete. If you still have questions, you can leave a message and you will answer as soon as you see it. Helpful friends 点个赞-点个赞-点个赞
, refills~