分布式事务解决方案,微服事务解决方案
微服事务解决方案(分布式事务解决方案)
1. 什么是事务
由一组操作构成的可靠、 独立的工作单元。
事务具备以下特点:
?Atomicity(原子性)
?Consistency(一致性)
?Isolation(隔离性)
?Durability(持久性)
2.事务的一致性
单体应用可以在数据库的事物管理器中取得强一致性,这种本地事物可靠简单。
而在微服或者者SOA的场景下,我们的本地事物就不作用了。对于分布式系统 Google 提出 CAP定理 ,
分布式的事物只能同时拥有以下三项中的两个:
?Consistency(一致性): 所有 客户看到一致的数据。
?Availability(可用性): 总能找 到一个可用的数据复本。
?Tolerance to Network Partition(分区容忍性): 即便 在系统被分区的情况下,依然满足上述两点。
- 分布式系统的事物无法做到强一致性,只能做到最终一致性。*
3.常见分布式事物的解决方案
- 2pc 两段提交方案
- 3pc 三段提交方案,是两段提交方案的进化。
- TCC 模式 try ,confirm ,cancel。
- 可靠消息机制 ,可靠消息分为 非事物消息 和 事物消息。
事物消息,简单的说就是消息投递成功,你本地的数据库事物一定提交成功,消息投递失败你本地事物也一定提交失败。相当于你投递消息和操作数据库是绑定在一起的,两者是在同一个事物中。
非事物消息,简单的说就是消息投递成功,本地数据库事物不肯定执行成功。
而现有的开源的MQ框架 大多数是不支持 事物消息的,也没有和本地事物进行配合。
RocketMQ 如同实现了这个事物消息功能,有兴趣的同学可以去看看。
可靠消息机制保证数据一致性的处理方案(非事物消息)
先来看个案例:
假设我有一个 文章微服 负责发布文章,查询文章列表等,还有一个 客户微服 保持客户的少量基本信息,如:客户发文章的篇数等。
现在发文章在 文章微服,而客户的发文篇数在 客户微服。这种情况下我们怎样保证 发文的计数 不会多也不会少,保证其的一致性的呢?
大家先来看一段代码:
假设这是 文章微服 发文代码:
@Transactional public void saveArticle(Article article){ try{ //保存文章 articleDao.saveArticle(article); MqEvent saveArticleEvent = new MqEvent(); //消息ID saveArticleEvent.setMsgId(UUIDUtil.mongoObjectId()); //发送保存文章 事件个客户服务 sender.sendAddArticleMqEvent(saveArticleEvent); }catch (Exception e){ //抛异常 让事务回滚 throw new RuntimeException(); } }}看起来很正常呀!没有什么问题! 我们来列举一下可能会出现的情况;
保存文章正常,MQ发送也正常,好万事大吉,数据都正常。
保存文章正常,MQ发送失败,抛异常。这时数据回滚,尽管出了点问题 但是数据正常。这也没问题。
文章保存失败,这时一定抛异常,MQ发送走不到,这时也是正常的。
文章保存成功,MQ发送成功,这时会不会有问题出现呢? 刚刚我们说了 我们的MQ是非事物性的,凑巧这个时候 MQ 回执异常导致 MQ抛异常了。本地事物回滚,但是MQ尽管抛异常,消息却发成功了。这时候 会导致 客户发文计数多了一篇,数据不一致了导致。
尽管这种做法看起来没有什么问题,但其实是有问题的。
为理解决这个问题,我们需要 添加一个本地事件表,专门存放 MQ事件 ,有定时器轮训去发送MQ消息,发送成功后做标记,或者者删除。很多MQ都会有 消息回执的。当成功投递到消息队列是 就会得到回执。
于是我们的代码应该改成这样:
@Transactional public void saveArticle(Article article) { articleDao.saveArticle(article); MqEvent saveArticleEvent = new MqEvent(); //消息ID saveArticleEvent.setMsgId(UUIDUtil.mongoObjectId()); // 保存事件到事件表 mqEventDao.addMQEvent(saveArticleEvent); }这样在本地事物的强一致性下可以保证,发文的同事插入发文事件。
说说 客户微服那边的解决 , 客户微服也应该有一个这样的事件表,保存接收的事件,通过轮训等方式解决这些事件,只有成功的接收了事件,事件才能从MQ队列里面消失。MQ在消费消息的时候假如遇到异常会重新将消失重新发回到队列中,很多MQ具备这个特性。
细心的同学可能会想到我同一个事件消息投递了两次怎样办?这就涉及幂等性的设计了,看到上面的消息ID没? 这就是为幂等性设计的 唯一ID;当客户微服收到两个消息ID是一样的时候,丢弃掉一个。
总结
我们的微服系统 只需涉及 增 删 改 的操作都应该通过可靠事件进行操作,而不能直接通过 REST 接口,去操作,也不能直接的发送事件去操作。对于消防端,要做好幂等性的解决。可靠事件解决微服的事物算是比较靠谱的做法,2pc,3pc ,Tcc 在微服事物解决这一块,基本上起不了什么作用。
本人的了解大概是这样,欢迎大家提出疑问。
本文的重点是你有没有收获与成长,其他的都不重要,希望读者们能谨记这一点。同时我经过多年的收藏目前也算收集到了一套完整的学习资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货,希望对想成为架构师的朋友有肯定的参考和帮助
需要更详细思维导图和以下资料的可以加一下技术交流分享群:“708 701 457”免费获取




1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 分布式事务解决方案,微服事务解决方案