-
协调者甲将收集到的结果反馈给乙丙丁(什么时候反馈,以及反馈结果如何,在此例中取决与丙的时间与决定);
-
乙收到;
-
丙收到;
-
丁收到;
不仅要锁住参与者的所有资源,而且要锁住协调者资源,开销大。一句话总结就是:2PC效率很低,对高并发很不友好。
引用《世界性难题...》
一文原话 “国外具有几十年历史和技术沉淀的基于XA模型的商用分布式事务产品,在相同软硬件条件下,开启分布式事务后吞吐经常有数量级的下降。”
此外还有三阶段提交
三 柔性事务
所谓柔性事务是相对强制锁表的刚性事务而言。流程入下:服务器A的事务如果执行顺利,那么事务A就先行提交,如果事务B也执行顺利,则事务B也提交,整个事务就算完成。但是如果事务B执行失败,事务B本身回滚,这时事务A已经被提交,所以需要执行一个补偿操作,将已经提交的事务A执行的操作作反操作,恢复到未执行前事务A的状态。
缺点是业务侵入性太强,还要补偿操作,缺乏普遍性,没法大规模推广。
目前基于消息队列的解决方案有阿里的RocketMQ
,它实现了半消息
的解决方案,有点类似于Paxos算法。
第一阶段:上游应用执行业务并发送MQ消息
-
上游应用发送待确认消息到可靠消息系统
-
可靠消息系统保存待确认消息并返回
-
上游应用执行本地业务
-
上游应用通知可靠消息系统确认业务已执行并发送消息。
可靠消息系统修改消息状态为发送状态并将消息投递到 MQ 中间件
第二阶段:下游应用监听 MQ 消息并执行业务
下游应用监听 MQ 消息并执行业务,并且将消息的消费结果通知可靠消息服务。
-
下游应用监听 MQ 消息组件并获取消息
-
下游应用根据 MQ 消息体信息处理本地业务
-
下游应用向 MQ
-
确认消息被消费
-
下游应用通知可靠消息系统消息被成功消费,可靠消息将该消息状态更改为已完成
RocketMQ
貌似是一种先进的实现方案了,但问题是缺乏文档
,无论是在Apache项目主页,还是在阿里的页面上,最多只告诉你如何用,而原理性或者指导性的东西非常缺乏。
当然,如果你在阿里云上专门购买了RocketMQ
服务,想必是另当别论了。但如果你试图在自己的服务环境中部署和使用,想必要历经相当大的学习曲线。
RabbitMQ
遵循了AMQP规范
,用消息确认机制来保证:只要消息发送,就能确保被消费者消费来做到了消息最终一致性。而且开源,文档还异常丰富,貌似是实现分布式事务的良好载体
4.1 RabbitMQ消息确认机制
rabbitmq的整个发送过程如下
1. 生产者发送消息到消息服务
2. 如果消息落地持久化完成,则返回一个标志给生产者。生产者拿到这个确认后,才能放心的说消息终于成功发到消息服务了。否则进入异常处理流程。
3. 消息服务将消息发送给消费者
4. 消费者接受并处理消息,如果处理成功则手动确认。当消息服务拿到这个确认后,才放心的说终于消费完成了。否则重发,或者进入异常处理。
4.2 异常
我们来看看可能发送异常的四种
1. 直接无法到达消息服务
网络断了,抛出异常,业务直接回滚即可。如果出现connection closed
错误,直接增加 connection
数即可
connectionFactory.setChannelCacheSize(100);
2. 消息已经到达服务器,但返回的时候出现异常
rabbitmq
提供了确认ack机制,可以用来确认消息是否有返回。因此我们可以在发送前在db中(内存或关系型数据库)先存一下消息,如果ack异常则进行重发. 其实就是生产者推送消息后,触发的回调方法里做处理。
/*confirmcallback用来确认消息是否有送达消息队列/
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
//try to resend msg
} else {
//delete msg in db
}
});
/**若消息找不到对应的Exchange会先触发returncallback */
rabbitTemplate.setReturnCallback((message, replyCode, replyText, tmpExchange, tmpRoutingKey) -> {
try {
Thread.sleep(Constants.ONE_SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("send message failed: " + replyCode + " " + replyText);
rabbitTemplate.send(message);
});
3. 消息送达后,消息服务自己挂了
如果设置了消息持久化,那么ack= true
是在消息持久化完成后,就是存到硬盘上之后再发送的,确保消息已经存在硬盘上,万一消息服务挂了,消息服务恢复是能够再重发消息
4. 未送达消费者
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后:学习总结——MyBtis知识脑图(纯手绘xmind文档)
学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)
除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
[外链图片转存中…(img-u2kLOnqc-1713681912723)]
除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!