分布式事务学习总结(一)

文章目录

  • 前言
  • LCN(XA)
  • seata
  • TCC
  • RocketMQ事务消息
    • 流程
    • 芋大神的流程图
    • TransactionListener
    • Springboot实现
      • 疑问
    • 阿里官网介绍
  • 自研mq分布式事务
  • 参考博客

前言

  为啥是总结(一)呢?知识总是在不断的学习,总结。总会跟之前大同小异,总会有所收获,也算是version吧,哈哈。
  在之前大学的时候有做过类似自研mq分布式事务的。参考下面的博客

  • MQ实现分布式事务

大概思路

  执行完本地操作,保存一条mysql数据,然后定时去判断状态发到mq进行消费。

缺陷
  当mq不可用时,定时扫数据库的会不断重试,消耗性能~参考rocketmq会先发条half消息,证明mq是可以用的,再进行本地事务。

LCN(XA)

这个没有怎么了解过,强一致性的,性能相对会差一点。
分布式事务学习总结(一)_第1张图片
lcn被誉为不是事务的生产者,只是事务的搬运工,哈哈。就是本地事务一套,大家各自处理,外面再一层事务管理器

seata

他的原理使用统一的事务管理器Transation Manager来控制两个不同事务是提交还是回滚。(了解还不是很深入)

分布式事务学习总结(一)_第2张图片

TCC

Try->Confirm->Cancel(最终一致性

第一步预扣,然后提交,如果有人失败呢就回滚。

相关框架:ByteTcc

RocketMQ事务消息

看下官网介绍

  • 交易范例
可以将其视为两阶段提交消息实现,以确保分布式系统中的最终一致性。
事务性消息可确保本地事务的执行和消息的发送可以原子方式执行。

官网也有个demo,执行完是不会进行回查的,这里有点奇怪

流程

分布式事务学习总结(一)_第3张图片
细品:先发送half消息,这个是为啥?先问下这位mq先生是否还在?或者有没有问题?有问题就不在进行下去了。
分布式事务学习总结(一)_第4张图片
然后进行本地事务处理,判断返回状态
分布式事务学习总结(一)_第5张图片
交易状态
分布式事务学习总结(一)_第6张图片
  讲道理,如果是Unknown已经会使mq回查才对,结果没有(无论是运行官网的demo还是网上的demo,有知道原因的大佬评论一下)

  根据这个状态最终决定half消息进行rollback还是commit。

芋大神的流程图

分布式事务学习总结(一)_第7张图片
配上链接

TransactionListener

分布式事务学习总结(一)_第8张图片

Springboot实现

@RocketMQTransactionListener

@Component
@RocketMQTransactionListener(txProducerGroup = "product_dajitui")
public class TransactionListenerImpl implements RocketMQLocalTransactionListener {

    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(org.springframework.messaging.Message message, Object o) {
        /*try {
            Thread.sleep(1000 * 60 * 20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        return RocketMQLocalTransactionState.UNKNOWN;
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(org.springframework.messaging.Message message) {
        System.out.println("回查" + message);
        return RocketMQLocalTransactionState.COMMIT;
    }
}

txProducerGroup 必须跟你发送事务消息的groupId是一致的。

发送者

	@Resource
    private RocketMQTemplate rocketMQTemplate;

    @GetMapping("/dajitui")
    public void dd() {
        Message message = MessageBuilder.withPayload("dajitui1111111").build();
        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction("product_dajitui", "DefaultCluster", message, null);
        System.out.println(String.format("send transcation message body=%s,result=%s", message.getPayload(), sendResult.getSendStatus()));
    }

疑问

executeLocalTransaction加上了睡眠,结果还是不会引起mq的回查,太难了。

阿里官网介绍

  • 事务消息

分布式事务学习总结(一)_第9张图片

自研mq分布式事务

请教了某大佬的自研分布式事务,原理也跟Rocketmq事务原理一样。

  开始讲故事:一开始也有个prepare消息到mq,并且保存状态在数据库里头,简称消息状态标识记录。就是预发状态
  然后进行本地事务,如果成功把标识改成确认,并且发布mq里头。如果说执行失败,标识就结束
  另一种情况,就是数据库是预发状态,但是一直没有动静,可能你应用挂了,网络延迟是吧,所以模拟rocketmq一个事务回查,提供一个回查的接口。定时器定时扫数据库预发状态的数据,进行事务回查,如果本地没有执行完那么就结束,如果执行完了就发送mq。

为啥有回查这一步?

执行本地事务跟mq发布不是原子性的

上面做了那么多是在干嘛的?

为了发送方尽可能的发送成功

那么如何保证消息也是成功?

mq重试->死信->人工处理

最终一致性的体现!

参考博客

  • Apache RocketMQ
  • RocketMQ源码解析:事务消息.md
  • 事务消息
  • SpringCloud集成RocketMQ实现事务消息方案添加链接描述

你可能感兴趣的:(分布式事务学习总结(一))