zoukankan      html  css  js  c++  java
  • 利用事务消息实现分布式事务

    一、消息事务

    其实很多场景下,我们“发消息”这个过程,目的往往是通知另外一个系统或者模块去更新数据,消息队列中的“事务”,主要解决消息生产者和消息消费者的数据一致性问题

    用户在电商APP上购物时,先把商品加到购物车里,然后几件商品一起下单,最后支付,完成购物流程。

    这个过程中有一个需要用到消息队列的步骤,订单系统创建订单后,发消息给购物车系统,将已下单的商品从购物车中删除。因为从购物车删除已下单商品这个步骤,并不是用户下单支付这个主要流程中必要的步骤,使用消息队列来异步清理购物车是更加合理。

    对于订单系统,它创建订单的过程实际执行了2个步骤的操作:

    • 在订单库中插入一条订单数据,创建订单;
    • 发消息给消息队列,消息的内容就是刚刚创建的订单

    对于购物车系统:

    • 订阅相应的主题,接收订单创建的消息,然后清理购物车,在购物车中删除订单的商品。

    在分布式系统中,上面提到的步骤,任何一个都有可能失败,如果不做任何处理,那就有可能出现订单数据与购物车数据不一致的情况,比如:

    • 创建了订单,没有清理购物车;
    • 订单没创建成功,购物车里面的商品却被清掉了。

    所以我们需要解决的问题为:在上述任意步骤都有可能失败的情况下,还要保证订单库和购物车库这两个库的数据一致性。

    二、分布式事务

    分布式事务就是要在分布式系统中实现事务。在分布式系统中,在保证可用性和不严重牺牲性能的前提下,光是要实现数据的一致性就已经非常困难了,显然实现严格的分布式事务是更加不可能完成的任务。所以目前大家所说的分布式事务,更多情况下,是在分布式系统中事务的不完整实现,在不同的应用场景中,有不同的实现,目的都是通过一些妥协来解决实际问题。

    常见的分布式事务实现:

    • 2PC(Two-phase Commit,也叫二阶段提交)
    • TCC(Try-Confirm-Cancel)
    • 事务消息

    每一种实现都有其特定的使用场景,也有各自的问题,都不是完美的解决方案。

    事务消息适用的场景主要是那些需要异步更新数据,并且对数据实时性要求不太高的场景。比如在创建订单后,如果出现短暂的几秒,购物车里的商品没有被及时情况,也不是完全不可接受的,只要最终购物车的数据和订单数据保持一致就可。

    三、消息队列实现分布式事务

    事务消息需要消息队列提供相应的功能才能实现,kafka和RocketMQ都提供了事务相关功能。

    对于订单系统:

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

    对于购物车系统:

    • 对于购物车系统收到订单创建成功消息清理购物车这个操作来说,失败的处理比较简单,只要成功执行购物车清理后再提交消费确认即可,如果失败,由于没有提交消费确认,消息队列会自动重试

    如果在第四步提交事务消息时失败了怎么办?Kafka 和 RocketMQ 给出了 2 种不同的解决方案:

    1、Kafka 的解决方案:

    直接抛出异常,让用户自行处理。我们可以在业务代码中反复重试提交,直到提交成功,或者删除之前创建的订单进行补偿。

    2、RocketMQ 的解决方案:

    在 RocketMQ 中的事务实现中,增加了事务反查的机制来解决事务消息提交失败的问题。如果 Producer 也就是订单系统,在提交或者回滚事务消息时发生网络异常,RocketMQ 的 Broker 没有收到提交或者回滚的请求,Broker 会定期去 Producer 上反查这个事务对应的本地事务的状态,然后根据反查结果决定提交或者回滚这个事务。为了支撑这个事务反查机制,我们的业务代码需要实现一个反查本地事务状态的接口,告知 RocketMQ 本地事务是成功还是失败。

    综合上面讲的通用事务消息的实现和 RocketMQ 的事务反查机制,使用 RocketMQ 事务消息功能实现分布式事务的流程如下图:

  • 相关阅读:
    unity vscode 断点问题
    unity Prefab 序列化一个小问题。
    公司有同事中病毒
    有点愧疚,今天把unity官方骗了...
    网络处理,发送约定
    (转载)MonoBehaviour的事件和具体功能总结
    控制台输出乱码问题
    vs遇到的字符串问题
    cmake的下载和安装
    三消设计思路, 通过配置文件搞定一切。
  • 原文地址:https://www.cnblogs.com/chjxbt/p/11412727.html
Copyright © 2011-2022 走看看