详细说分布式事务
一、分布式事务的概念
回到顶部回到顶部回到顶部https://github.com/changmingxie/tcc-transactiona)导入数据库
sql文件下载地址为:dtx-tcc-sql
b)工程配置
涉及到分布式事务的工程均需要的配置
maven配置
org.dromara hmily‐springcloud 2.0.4‐RELEASE
application.yaml中添加hmily
org:
dromara:
hmily:
serializer: kryo
recoverDelayTime: 30
retryMax: 30
scheduledDelay: 30
scheduledThreadMax: 10
repositorySupport: db
#对于发起方的时候,把此属性设置为true。参与方为false。
started: true
hmilyDbConfig:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/hmily?useUnicode=true
username: root
password: 123456
注入hmily的配置Bean
@Bean
public HmilyTransactionBootstrap hmilyTransactionBootstrap(HmilyInitService hmilyInitService){
HmilyTransactionBootstrap hmilyTransactionBootstrap = new HmilyTransactionBootstrap(hmilyInitService);
hmilyTransactionBootstrap.setSerializer(env.getProperty("org.dromara.hmily.serializer"));
hmilyTransactionBootstrap.setRecoverDelayTime(Integer.parseInt(env.getProperty("org.dromara.hmily.recoverDelayTime")));
hmilyTransactionBootstrap.setRetryMax(Integer.parseInt(env.getProperty("org.dromara.hmily.retryMax")));
hmilyTransactionBootstrap.setScheduledDelay(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledDelay")));
hmilyTransactionBootstrap.setScheduledThreadMax(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledThreadMax")));
hmilyTransactionBootstrap.setRepositorySupport(env.getProperty("org.dromara.hmily.repositorySupport"));
hmilyTransactionBootstrap.setStarted(Boolean.parseBoolean(env.getProperty("org.dromara.hmily.started")));
HmilyDbConfig hmilyDbConfig = new HmilyDbConfig();
hmilyDbConfig.setDriverClassName(env.getProperty("org.dromara.hmily.hmilyDbConfig.driverClassName"));
hmilyDbConfig.setUrl(env.getProperty("org.dromara.hmily.hmilyDbConfig.url"));
hmilyDbConfig.setUsername(env.getProperty("org.dromara.hmily.hmilyDbConfig.username"));
hmilyDbConfig.setPassword(env.getProperty("org.dromara.hmily.hmilyDbConfig.password"));
hmilyTransactionBootstrap.setHmilyDbConfig(hmilyDbConfig);
return hmilyTransactionBootstrap;
}
启动类上添加注解
@ComponentScan({"org.dromara.hmily"})
c)调用方(bank1)实现
代码实现:AccountInfoServiceImpl
try:
try幂等校验
try悬挂处理
检查余额是够扣减金额
扣减金额
confirm:
空
cancel
cancel幂等校验
cancel空回滚处理
增加可用余额
注意:远程调用bank2时,在feign调用的接口上加注解@Hmily
d)参与方(bank2)实现
代码实现:AccountInfoServiceImpl
try:
空
confirm:
confirm幂等校验
正式增加金额
cancel:
空
e)小结
如果拿TCC事务的处理流程与2PC两阶段提交做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让应用自己定义数据操作的粒度,使得降低锁冲突、提高吞吐量成为可能。 而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。 回到顶部cloud-dtx-txmsg AccountInfoServiceImpl//两个方法 //1,向mq发送转账消息 //2,更新账户,扣减金额 (通过事务id保证幂等性)
Controller:AccountInfoController
//生成事务id,调用service的发消息接口
message:ProducerTxmsgListener
//两个方法executeLocalTransaction和checkLocalTransaction //事务消息发送后的回调方法。此时保证本地事务,调用Service扣减金额同时将消息改为COMMIT(可消费状态),如果捕获异常,将消息改为ROLLBACK回滚 //事务回查。查询是否在调用方已经处理,如果已经处理需修改消息为COMMIT可消费,否则就是UNKOWN状态。
e)bank2
Service:AccountInfoServiceImpl
//更新账户bank2,增加金额。(通过事务id保证幂等性)
message:TxmsgConsumer
//监听bank1发送的消息topic,调用Service增加金额回到顶部cloud-dtx-notify AccountPayServiceImpl
//两个方法 //1,插入充值记录。生成事务id,将事务id和充值信息发送给MQ队列 //2,查询充值记录。提供给调用方查询。
Controller:AccountPayController
//直接调用Service中的方法插入充值记录
d)bank1
Service:AccountInfoServiceImpl
//两个方法 //1,更新账户金额。根据事务id保证更新的幂等性。 //2,远程调用pay的查询充值结果。如果发现状态改变同时更新当前账号情况。
message:NotifyMsgListener
//监听消息。调用Service的更新账户金额,幂等更新。
Controller:AccountInfoController
//调用Service的查询充值结果
5,总结
最大努力通知方案是分布式事务中对一致性要求最低的一种,适用于一些最终一致性时间敏感度低的业务;最大努力通知方案需要实现如下功能:
- 消息重复通知机制。
- 消息校对机制。 主动调用接口查询并修改。