为啥是总结(一)呢?知识总是在不断的学习,总结。总会跟之前大同小异,总会有所收获,也算是version吧,哈哈。
在之前大学的时候有做过类似自研mq分布式事务的。参考下面的博客
大概思路
执行完本地操作,保存一条mysql数据,然后定时去判断状态发到mq进行消费。
缺陷
当mq不可用时,定时扫数据库的会不断重试,消耗性能~参考rocketmq会先发条half消息,证明mq是可以用的,再进行本地事务。
这个没有怎么了解过,强一致性的,性能相对会差一点。
lcn被誉为不是事务的生产者,只是事务的搬运工,哈哈。就是本地事务一套,大家各自处理,外面再一层事务管理器
他的原理使用统一的事务管理器Transation Manager来控制两个不同事务是提交还是回滚。(了解还不是很深入)
Try->Confirm->Cancel(最终一致性)
第一步预扣,然后提交,如果有人失败呢就回滚。
相关框架:ByteTcc
看下官网介绍
可以将其视为两阶段提交消息实现,以确保分布式系统中的最终一致性。
事务性消息可确保本地事务的执行和消息的发送可以原子方式执行。
官网也有个demo,执行完是不会进行回查的,这里有点奇怪
细品:先发送half消息,这个是为啥?先问下这位mq先生是否还在?或者有没有问题?有问题就不在进行下去了。
然后进行本地事务处理,判断返回状态
交易状态
讲道理,如果是Unknown已经会使mq回查才对,结果没有(无论是运行官网的demo还是网上的demo,有知道原因的大佬评论一下)
根据这个状态最终决定half消息进行rollback还是commit。
@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的回查,太难了。
请教了某大佬的自研分布式事务,原理也跟Rocketmq事务原理一样。
开始讲故事:一开始也有个prepare消息到mq,并且保存状态在数据库里头,简称消息状态标识记录。就是预发状态
然后进行本地事务,如果成功把标识改成确认,并且发布mq里头。如果说执行失败,标识就结束。
另一种情况,就是数据库是预发状态,但是一直没有动静,可能你应用挂了,网络延迟是吧,所以模拟rocketmq一个事务回查,提供一个回查的接口。定时器定时扫数据库预发状态的数据,进行事务回查,如果本地没有执行完那么就结束,如果执行完了就发送mq。
为啥有回查这一步?
执行本地事务跟mq发布不是原子性的
上面做了那么多是在干嘛的?
为了发送方尽可能的发送成功
那么如何保证消息也是成功?
mq重试->死信->人工处理
最终一致性的体现!