首页 > 其他分享 >基于消息队列实现分布式事务

基于消息队列实现分布式事务

时间:2022-12-19 11:36:45浏览次数:40  
标签:事务 本地 队列 购物车 订单 消息 提交 分布式


注意:本文把消息队列与购物车系统看作同一个事务
目标: 掌握消息队列的事务

场景:

订单系统产生订单,购物车系统减购物车中的商品。

实现思路 :

基于消息队列实现分布式事务_回滚

  1. 订单系统在消息队列上开启一个事务(没有创建订单)。
  2. 订单系统给消息服务器发送一个“半消息”,这个半消息不是说消息内容不完整,它包含的内容就是完整的消息内容,半消息和普通消息的唯一区别是,在事务提交之前,对于消费者来说,这个消息是不可见的。
  3. 半消息发送成功后,订单系统就可以执行本地事务了,在订单库中创建一条订单记录,并提交订单库的数据库事务。
  4. 然后根据本地事务的执行结果决定提交或者回滚事务消息。如果订单创建成功,那就提交事务消息,购物车系统就可以消费到这条消息继续后续的流程。如果订单创建失败,那就回滚事务消息,购物车系统就不会收到这条消息。

基于消息队列实现分布式事务_回滚_02

橙色和绿色分别是两个事务。

问题:

步骤4事务提交失败;这时候订单系统本地事务已提交尔购物车系统没有收到消息,造成数据不一致。

如何解決消息队列事务提交过程出现的异常:

kafka会直接抛出异常用户自行处理;

在RocketMQ中的事务实现中,增加了事务反查的机制来解决事务消息提交失败的问题 , RocketMQ的Broker没有收到提交或者回滚的请求,Broker会定期去producer上反查这个事务对应的本地事务的状态,然后根据反查结果决定提交或者回滚这个事务。

为了支持事务反查机制,我们的业务代码需要实现一个反查本地事务状态的接口告知RocketMQ本地事务是成功还是失败。

本例中的反查逻辑很简单只需根据消息中的订单ID,在订单库中查询订单是否存在即可。

能不能在订单创建完成后再向消息队列发送订单数据?这样不用考虑订单创建失败而发送消息的情况了

考虑这样一种情况:订单创建成功了,还没来得及发消息,这个节点突然断电了。本地事务无法回滚。

还有一种情况订单创建成功,减购物车(后续操作)失败的话要写事务补偿把创建的订单删掉。

能不能这样:

1.开启本地事务创建订单,2.发消息,3.根据发消息是否成功来决定提交还是回滚本地事务。这样不需要事务消息也能解决这个场景的问题了?

如果本地事务提交失败已发送的消息无法撤回,会导致数据不一致。

基于消息队列实现分布式事务_消息队列_03

小结

不论是消息队列事务还是异步事务都遵循事务的四大特性:原子性,一致性,隔离性,持久性。



标签:事务,本地,队列,购物车,订单,消息,提交,分布式
From: https://blog.51cto.com/u_10176086/5951812

相关文章

  • 添加数据库事务
    //数据库事务@Transactional(rollbackFor=Exception.class)具体实例`@Transactional(rollbackFor=Exception.class)@OverridepublicStringcreate(Creat......
  • 队列总结_legend
    队列总结:Queue (1)队列的基本知识:        (1.1)特点:尾进头出,先进先出。(rearinfrontout)         (1.2)与线性表比较:        队列......
  • 架构设计(六):引入消息队列
    架构设计(六):引入消息队列作者:Grey原文地址:博客园:架构设计(六):引入消息队列CSDN:架构设计(六):引入消息队列消息队列是一个支持持久化的组件,数据存储在内存中,支持异步通信。它......
  • “去中心化”和“分布式”
    很多人口中的“去中心化”,与它的字面意思并不匹配,“去中心化”成为了一个迷惑性的词。而人们口中的“分布式”也有不同的含义。我们可以先定义什么是中心化:把整个事物全......
  • cpp优先队列(priority_queue)
    优先队列的概念在优先队列中,队列中的每个元素都与某个优先级相关联,但是优先级在队列数据结构中不存在。优先队列中具有最高优先级的元素将被首先删除,而队列遵循FIFO(......
  • docker高级篇2-分布式存储之三种算法
    面试题:1~2亿条数据需要缓存,请问如何设计这个缓存案例?答:单机单台100%是不可能的。肯定是分布式缓存的。那么用Redis如何落地?一般有三种方案:哈希取余分区;一致性哈希算法分区;哈......
  • docker高级篇2-分布式存储之三种算法
    面试题:1~2亿条数据需要缓存,请问如何设计这个缓存案例?答:单机单台100%是不可能的。肯定是分布式缓存的。那么用Redis如何落地?一般有三种方案:哈希取余分区;一致性哈希算法......
  • 事务的隔离级别
    事务的隔离级别readuncommitted:出现脏读、幻读、不可重复读readcommitted:避免脏读repeatableread:避免脏读和不可重复读serializable:全都避免MySQL中默认第三个Ora......
  • redis 轻松实现分布式秒杀系统
    redis轻松实现分布式秒杀系统利用redis操作的原子性,轻松实现一个分布式的秒杀系统。假设设计背景:1万人去抢10个商品设计思路:在redis中存储一个list,每次用户请求抢购......
  • 事务
    TCLtransacationcontrollanguage事务控制语言事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行1.原子性:不可再分,要么全部执行,要么全......