详细说分布式事务


 

一、分布式事务的概念

回到顶部回到顶部回到顶部https://github.com/changmingxie/tcc-transaction Hmily https://github.com/yu199195/hmily ByteTCC  https://github.com/liuyangming/ByteTCC EasyTransaction  https://github.com/QNJR-GROUP/EasyTransaction cloud-dtx-tcc

a)导入数据库

  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,总结

  最大努力通知方案是分布式事务中对一致性要求最低的一种,适用于一些最终一致性时间敏感度低的业务;最大努力通知方案需要实现如下功能:

  • 消息重复通知机制。
  • 消息校对机制。 主动调用接口查询并修改。
回到顶部

七、四种分布式事务对比

  2PC:最大的诟病是一个阻塞协议。RM在执行分支事务后需要等待TM的决定,此时服务会阻塞并锁定资源。由于其阻塞机制和最差时间复杂度高, 因此,这种设计不能适应随着事务涉及的服务数量增加而扩展的需要,很难用于并发较高以及子事务生命周期较长 (long-running transactions) 的分布式服务中。   TCC:如果拿TCC事务的处理流程与2PC两阶段提交做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让应用自己定义数据操作的粒度,使得降低锁冲突、提高吞吐量成为可能。而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。典型的使用场景:登录送优惠券等。   可靠消息最终一致性事务:适合执行周期长且实时性要求不高的场景。引入消息机制后,同步的事务操作变为基于消息执行的异步操作, 避免了分布式事务中的同步阻塞操作的影响,并实现了两个服务的解耦。典型的使用场景:注册送积分,登录送优惠券等。   最大努力通知:是分布式事务中要求最低的一种,适用于一些最终一致性时间敏感度低的业务;允许发起通知方处理业务失败,在接收通知方收到通知后积极进行失败处理,无论发起通知方如何处理结果都会不影响到接收通知方的后续处理;发起通知方需提供查询执行情况接口,用于接收通知方校对结果。典型的使用场景:银行通知、支付结果通知等。 

相关