当前位置: 首页 > news >正文

利用消息队列处理分布式事务

引言

这篇说说分布式事务的问题。企业现在的架构都由传统的架构转向了微服务架构,如下图所示:

那么,都不可避免的会遇到跨数据库调用的,分布式事务问题!
目前,业内解决分布式事务问题,都基本不用JTA这种强一致性的解决方案,基本是采用如下两套方案

  • 基于TCC的事务框架
  • 消息队列

OK,你们先记住两点
(1)图中的服务A和服务B,如果是同步调用,要求一起成功,或者一起失败,那么此时应选用TCC的事务框架,这点我改天另写一篇,先挖坑!
(2)图中的服务A和服务B,如果是异步调用,比如服务C先调用服务A后,服务C不用管服务B的执行结果,直接返回,那么这种情况下,应选用消息队列!这篇文章重点讲!
目前为止,大部分文章都讲的太复杂了。导致很多新人看完后于是看这篇文章前,你们先忘记你们在其他文章看到的概念,跟着博主的思路走!

正文

先给大家套一个业务场景,也是很常见的一个异步调用场景:

  • 支付宝往余额宝转钱

即将服务A假设为支付宝,服务B假设为余额宝。
于是呢,我们的支付宝往余额宝转100块钱是怎么做的呢?
特别容易,借助消息队列即可,如下图所示

一致性解决

OK,上面这一版有一个致命的问题!如下所示
事务开始
(1)给支付宝账户zhangsan,扣100元
(2)将(给余额宝账户zhangsan,加100元)封装为消息,发送给消息队列
事务结束

敢问你,如何保证第一步和第二步是在同一个事务里完成的。换句话说,第一步操作的是数据库,第二步操作的是一个消息队列,你如何保证这两步之间的一致性?
记住了,任何涉及到数据库和中间件之间的业务逻辑操作,都需要考虑二者之间的一致性。比如,你先操作了数据库,再操作缓存,数据库和缓存之间一致性如何解决?好吧,如果是博主的铁粉,应该知道怎么解决了,回到我们的场景。
改变思路,加一张事务表,如下图所示

注意了,此时事务的内容为
事务开始
(1)给支付宝账户zhangsan,扣100元
(2)给事件表插入一条记录
事务结束

此时是对同一数据库的两张表操作,因此可以用数据库的事务进行保证。
另外,起一个定时程序,定时扫描事务表,发现一个状态为'UNFINISHED'的事件,就进行封装为消息,发送到消息中间件,然后将状态改为'FINISHED'.

幂等性解决

注意了,这一版还存在一个幂等性问题!
仔细看,定时程序做了如下三个操作
(1)定时扫描事务表,发现一个状态为'UNFINISHED'的事件
(2)将事件信息,封装为消息,发送到消息中间件
(3)将事件状态改为'FINISHED'

OK,假设在步骤(2)的时候,发送完消息体,还未执行步骤(3),定时程序阵亡了!然后重启定时程序,发现刚那个事务的状态依然为'UNFINISHED',因此重新发送。这样,就会出现重复消费问题。因此,幂等性也是需要保证的!

如果是博主的忠实读者,应该知道,博主曾经写过一篇《分布式之消息队列复习精讲》,里头就提到了如何解决幂等性问题。什么?你没看过这篇?拉出去枪毙!
借用这篇文章里的方案。在消费者端,也维护一个带主键的表,可以选txid为主键,如下图所示

如果一旦出现重复消费,则在事务里直接报出主键冲突错误,从而保证了幂等性!

面试连环炮

面试官:"你们用了微服务架构么?"
求职者:"用了,用了"
面试官:"怎么解决分布式事务的啊?"
求职者:"我们的服务刚好是异步的场景,所以用消息队列!"
面试官:"怎么保证一致性和幂等性啊?"
求职者:"嗯,听我细细说来....."

转载于:https://www.cnblogs.com/liliuguang/p/10370963.html

相关文章:

  • 番外篇1:在Windows环境下安装JDK
  • qwq
  • LeetCode18.四数之和 JavaScript
  • matlab-高数 diff 方向导数
  • 聊一聊前端的监控
  • android图片蒙层
  • Docker学习笔记_使用Dockerfile创建flask的一个镜像
  • java 多线程基础, 我觉得还是有必要看看的
  • Nginx压测和并发预估
  • 未发先侃?对比华为,高通第二代5G调制解调器如何?
  • 安卓P底部有空白,需要手动全屏
  • vue.js框架原理浅析
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • SpringBoot 实战 (九) | 整合 Mybatis
  • ThinkSNSPlus 2.0 产品体验报告
  • __proto__ 和 prototype的关系
  • 【391天】每日项目总结系列128(2018.03.03)
  • 03Go 类型总结
  • 0x05 Python数据分析,Anaconda八斩刀
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • es6(二):字符串的扩展
  • gops —— Go 程序诊断分析工具
  • iOS编译提示和导航提示
  • IOS评论框不贴底(ios12新bug)
  • MYSQL 的 IF 函数
  • Zepto.js源码学习之二
  • 从0到1:PostCSS 插件开发最佳实践
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 前端之Sass/Scss实战笔记
  • 手写双向链表LinkedList的几个常用功能
  • 一些css基础学习笔记
  • 译自由幺半群
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (23)Linux的软硬连接
  • (26)4.7 字符函数和字符串函数
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (层次遍历)104. 二叉树的最大深度
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)计算机毕业设计ssm电影分享网站
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (排序详解之 堆排序)
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (四)linux文件内容查看
  • (五)网络优化与超参数选择--九五小庞
  • (转)Unity3DUnity3D在android下调试
  • (转载)Linux 多线程条件变量同步
  • .NET 动态调用WebService + WSE + UsernameToken
  • []利用定点式具实现:文件读取,完成不同进制之间的
  • [20171101]rman to destination.txt
  • [codeforces]Checkpoints
  • [IMX6DL] CPU频率调节模式以及降频方法
  • [Interview]Java 面试宝典系列之 Java 多线程