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

分布式事务解决方案(最终一致性【可靠消息解决方案】)

可靠消息最终一致性解决方案

        可靠消息最终一致性分布式事务解决方案指的是事务的发起方执行完本地事务之后,发出一条消息,事务的参与方,也就是消息的消费者一定能够接收到这条消息并且处理完成,这个方案强调的是只要事务发起方将消息发送给事务参与者,事务参与方就一定能够执行完成,事务最终达到一致性的状态

适用的场景

        适用于消息数据能够独立存储,能够减低系统之间耦合度,并且业务对数据一致性的时间敏感度高的场景

需要实现的服务模式

        需要实现的服务模式是可查询操作和幂等操作,需要参与分布式事务的业务服务提供可查询自身事务状态的接口,发生异常时,能够通过接口查询具体的事务状态,这就是可查询操作,参与分布式事务的各个业务接口需要保证数据操作的幂等性。

方案的执行流程

        可靠消息最终一致性方案中,事务发起方执行完本地事务后,通过可靠消息服务将消息发送给事务参与方,事务参与方收到消息后,一定能够成功执行,这里的可靠消息服务可以通过本地消息表实现,也可以通过RocketMq消息队列实现

        首先,事务发起方将消息发送给可靠消息服务,这里的可靠消息服务可以基于本地数据表实现,也可以基于消息队列中间件实现。然后,事务参与方从可靠消息服务中接收消息。事务发起方和可靠消息服务之间、可靠消息服务和事务参与方之间都是通过网络进行通信的。由于网络本身的不稳定性,可能会造成分布式事务问题,因此在实现上,需要引人消息确认服务和消息恢复服务。

        消息确认服务会定期检测事务发起方业务的执行状态和消息库中的数据,如果发现事务发起方业务的执行状态与消息库中的数据不一致,消息确认服务就会同步事务发起方的业务数据和消息库中的数据,保证数据一致性,确保事务发起方业务完成本地事务后消息定会发送成功。

        消息恢复服务会定期检测事务参与方业务的执行状态和消息库中的数据,如果发现事务参与方业务的执行状态与消息库中的数据不一致(这里的不一致,通常指的是事务参与方消费消息后,执行本地事务操作失败,导致事务参与方本地事务的执行状态与消息库中的数据不一致),消息恢复服务就会恢复消息库中消息的状态,使消息的状态回滚为事务发起方发送消息成功,但未被事务参与方消费的状态。

方案的优缺点

        消息最终一致性方案的可靠消息服务可以基于本地消息表和消息队列中间件两种方式实现

基于本地消息表实现的最终消息一致性方案

优点:

  • 在业务应用中实现了消息的可靠性,减少了对消息中间件的依赖

缺点:

  • 绑定了具体的业务场景,耦合度太高,不可公用和扩展
  • 消息数据与业务数据同在一个数据库,占用了业务系统的资源

基于消息队列中间件实现的最终消息一致性方案

优点:

  • 消息数据能够独立存储,与具体的业务数据库解耦
  • 消息的并发性和吞吐量由于本地消息表方案

缺点:

  • 发送一次消息需要完成两次网络交互,一次是消息的发送,另外一次是消息的提交或者回滚
  • 需要实现消息的回查接口,增加了开发的成

需要注意的问题

        使用可靠消息最终一致性方案解决分布式事务问题时,需要注意本地事务与消息发送的原子性问题、事务参与方接收消息的可靠性与幂等性问题

1、事务发送方本地事务与消息发送的原子性问题

  • 产生的原因:可靠消息最终一致性要求事务发起方的本地事务与消息发送的操作具有原子性,也就是事务发起方执行本地事务成功后,一定要将消息发送出去,执行本地事务失败后,一定要丢弃消息。执行本地事务和发送消息,要么都成功,要么都失败
  • 原子性问题的解决方案:在实际的解决方案中,可以通过消息确认服务解决本地事务与消息发送的原子性问题

2、事务参与方接收消息的可靠性问题

  • 可靠性问题产生的原因:由于服务器宕机、服务崩溃或网络异常等原因,导致事务参与方不能正常接收消息或者接收消息后处理事务的过程中发生异常,无法将结果正确回传到消息库中。此时,就会产生可靠性问题
  • 可靠性问题的解决方案:可以通过消息恢复服务保证事务参与方的可靠性

3、事务参与方接收消息的幂等性问题

  • 幂等性问题产生的原因:在实际场景中,由于某种原因,可靠消息服务可能会多次向事务参与方发送消息,如果事务参与方的方法不具有幂等性,就会造成消息重复消费的问题,这就是典型的幂等性问题
  • 幂等性问题的解方案:解快方案就是事务参与方的方法实现要具有幂等性,只要参数相同,无论调用多少次接口或方法、得出的结果都与第一次调用接口或方法得出的结果相同

最大努力通知型解决方案

        当分布式事务跨越多个不同的系统,尤其是不同企业之间的系统时,解决分布式事务问题就需要用到最大努力通知型方案

适用的场景

        最大努力通知型解决方案适用于最终一致性时间敏感度低的场景,并且事务被动方的处理结果不会影响主动方的处理结果,典型的使用场景就是支付成功后,支付平台异步通知商户支付结果

需要实现的服务模式

        最大努力通知型解决方案需要实现的服务模式是可查询操作和幂等操作。例如,在充值业务场景中,用户调用支付服务充值成功后,支付服务会按照一定的阶梯型通知规则调用账户服务的接口,向账户服务发送支付数据。此时,账户服务的接口需要满足幂等性,这就是幂等操作。如果支付服务调用账户服务的接口超过了设置的最大次数,仍然没有调用成功,则支付服务需要提供查询支付结果的接口,以便账户服务调用并恢复丢失的业务

方案的执行流程

        最大努力通知型分布式事务解决方案在执行的过程中,允许丢失消息,但需要业务主动方提供事务状态查询接口,以便业务被动方主动调用并恢复丢失的业务

实现最大努力通知型方案时,需要实现如下功能。

  1. 业务主动方在完成业务处理后,会向业务被动方发送消息通知。发送消息通加时,允许消息丢失
  2. 在实现上,业务主动方可以设置时间阶梯型通知规则,在消息通知失败后,可以按照规则再次通知,直到到达最大通知次数为止
  3. 业务主动方需要提供查询接口供业务被动方按照需要查询,用于恢复丢失的消息

方案的优缺点

最大努力通知型方案存在如下优点:

  1. 能够实现跨企业的数据一致性。
  2. 业务被动方的处理结果不会影响业务主动方的处理结果
  3. 能够快速接入其他业务系统,达到业务数据一致性。

最大努力通知型方案存在如下缺点:

  1. 只适用于时间敏感度低的场景。
  2. 业务主动方发送的消息可能丢失,造成业务被动方收不到消息。
  3. 需要业务主动方提供查询消息的接口,业务被动方需要按照主动方的接口要求查数据,增加了开发成本

需要注意的问题

        业务被动方需要保证接收通知的方法的幂等性,关键是要业务主动方通过一定的机最大限度地将业务的处理结果通知给业务被动方,因此必须解决如下两个问题

1、消息重复通知产生的问题:

  • 消息重复通知产生的原因:由于业务主动方发送消息通知后,业务被动方不一定能够接收到消息,因此需要一定的阶梯型通知规则重复向业务被动方发送消息通知。此时,就出现了消息重复通情况,因为业务被动方的方法被执行了多次,所以有可能造成数据不一致的问题
  • 消息重复通知的解决方案:保证业务被动方接收消息通知的方法具备幂等性,则在业务上就能够解决消息重影知的问题

2、消息通知丢失的问题

  • 消息通知丢失问题的原因:如果业务主动方尽最大努力都没有将消息通知给业务被动方,或者业务被动方接收消息并执行完毕后,需要再次获取消息。此时,业务主动方已经删除对应的通知消息,向业务被动方发送消息通知,也就是说,消息通知已经丢失
  • 消息通知丢失的解决方案:业务主动方需要提供查询消息的接口来满足业务被动方主动查询消息的需求,以恢复丢失的业务。另外,业务主动方在设计消息回查接口时,一定要注意接口的安全性和并发性

相关文章:

  • grafana大盘展示node_expod节点
  • springboot发送短信验证码,结合redis 实现限制,验证码有效期2分钟,有效期内禁止再次发送,一天内发送超3次限制
  • 【C++】牛客——小红的口罩
  • NodeJS安装并生成Vue脚手架(保姆级)
  • 从需求角度介绍PasteSpider(K8S平替部署工具适合于任何开发语言)
  • zabbix监控mysql
  • OpenHarmony 实战开发PhotoView——支持图片缩放、平移、旋转的一个优雅的三方组件
  • WXSS (WeiXin Style sheets)
  • Java中volatile关键字
  • 英语学习笔记22——Give me/him/her/us/them a .... Which one?
  • js处理服务器响应Blob对象格式文件处理
  • 【Unity】免费的高亮插件——QuickOutline
  • 【全开源】JAVA同城搬家系统源码小程序APP源码
  • Scrapy框架简单介绍及Scrapy项目编写详细步骤(Scrapy框架爬取豆瓣网站示例)
  • 在Ubuntu系统中使用Systemctl添加启动项的详细指南
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 【刷算法】从上往下打印二叉树
  • CSS 提示工具(Tooltip)
  • exports和module.exports
  • Github访问慢解决办法
  • Golang-长连接-状态推送
  • Markdown 语法简单说明
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Python实现BT种子转化为磁力链接【实战】
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • ViewService——一种保证客户端与服务端同步的方法
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 产品三维模型在线预览
  • 大型网站性能监测、分析与优化常见问题QA
  • 分布式任务队列Celery
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 高性能JavaScript阅读简记(三)
  • 基于web的全景—— Pannellum小试
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 前端面试之CSS3新特性
  • 如何进阶一名有竞争力的程序员?
  • 使用 Docker 部署 Spring Boot项目
  • 一、python与pycharm的安装
  • 译米田引理
  • 应用生命周期终极 DevOps 工具包
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 回归生活:清理微信公众号
  • ‌Excel VBA进行间比法设计
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (十)c52学习之旅-定时器实验
  • (十)T检验-第一部分
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转) ns2/nam与nam实现相关的文件
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)原始图像数据和PDF中的图像数据