zoukankan      html  css  js  c++  java
  • 写数据库mq消息事务一致性解决方案

    原文链接:https://cloud.tencent.com/developer/article/1478827

    如果我们要在服务化拆分中使用消息队列,那么我们需要解决哪些问题呢?首先去哪儿网提供了旅游产品在线预订服务,那么就涉及电商交易,在电商交易中我们认为数据的一致性是非常关键的要素。那么我们的 MQ 必须提供一致性保证。

    MQ 提供一致性保证又分为两个方面。发消息时我们如何确保业务操作和发消息是一致的,也就是不能出现业务操作成功消息未发出或者消息发出了但是业务并没有成功的情况。举例来说,支付服务使用消息通知出票服务,那么不能出现支付成功,但是消息没有发出,这会引起用户投诉;但是也不能出现支付未成功,但是消息发出最后出票了,这会导致公司损失。总结一下就是发消息和业务需要有事务保证。一致性的另一端是消费者,比如消费者临时出错或网络故障,我们如何确保消息最终被处理了。那么我们通过消费 ACK 和重试来达到最终一致性。

    三、利用数据库事务解决一致性问题

    提到一致性,大家肯定就想到事务,而一提到事务,肯定就想到关系型数据库,那么我们是不是可以借助关系型 DB 里久经考验的事务来实现这个一致性呢。我们以 MySQL 为例,对于 MySQL 中同一个实例里面的 db,如果共享相同的 Connection 的话是可以在同一个事务里的。以下图为例,我们有一个 MySQL 实例监听在 3306 端口上,然后该实例上有 A,B 两个 DB,那么下面的伪代码是可以跑在同一个事务里的

    有了这层保证,我们就可以透明的实现业务操作和消息发送在同一个事务里了,首先我们在公司所有 MySQL 实例里初始化出一个 message db,这个可以放到自动化流程中(据说在去哪儿由运维团队完成),对应用透明。然后我们只要将发消息与业务操作放到同一个 DB 事务里即可。

    我们来看一个实际的场景,在支付场景中,支付成功后我们需要插入一条支付流水,并且发送一条支付完成的消息通知其他系统。那么这里插入支付流水和发送消息就需要是一致的,任何一步没有成功最后都会导致问题。那么就有下面的代码

    上面的代码可以用下面的伪代码解释

    实际上在 producer.sendMessage 执行的时候,消息并没有通过网络发送出去,而仅仅是往业务 DB 同一个实例上的消息库插入一条记录,然后注册事务的回调,在这个事务真正提交后消息才从网络发送出去,这个时候如果发送到 server 成功的话消息会被立即删除掉。而如果消息发送失败则消息就留在消息库里,这个时候我们会有一个补偿任务会将这些消息从消息库里捞出然后重新发送,直到发送成功。整个流程就如下图所示

    1、begin tx 开启本地事务

    2、do work 执行业务操作

    3、insert message 向同实例消息库插入消息

    4、end tx 事务提交

    5、send message 网络向 server 发送消息

    6、reponse server 回应消息

    7、delete message 如果 server 回复成功则删除消息

    8、scan messages 补偿任务扫描未发送消息

    9、send message 补偿任务补偿消息

    10、delete messages 补偿任务删除补偿成功的消息

  • 相关阅读:
    BZOJ 2654: tree(二分 最小生成树)
    洛谷P4602 [CTSC2018]混合果汁(主席树)
    SDOI 2018 round2游记
    Codeforces Round #479 (Div. 3) 题解
    软件开发中关于向后兼容的理解
    使用achartengine实现自定义折线图 ----附代码 调试OK
    python每次处理一个字符的三种方法
    子序列的个数 --- 庞果网
    IOS深入学习(4)之Coordinate System
    C# ADO基础 SqlHelper
  • 原文地址:https://www.cnblogs.com/fswhq/p/13853760.html
Copyright © 2011-2022 走看看