本文来说下分布式事务模型之基于消息的分布式事务

文章目录

  • 概述
  • 基于消息的分布式事务
    • 基于事务消息的分布式事务
    • 基于本地消息的分布式事务
    • 特点剖析
  • 本文小结

概述

事务是一组不可分组的操作集合,这些操作要么都成功执行,要么都取消执行。最典型的需要事务的场景是银行账户间的转账:假如 A 账户要给 B 账户转账 100 元,那么 A 账户要扣减 100 元,B 账户要增加 100 元,这两个账户的数据变更都成功才可算作转账成功。更严格来说,可以用 ACID 四个特性表述事务:

  • Atomicity:原子性,事务中的所有操作要么都成功执行,要么都取消执行,不能存在部分执行,部分不执行的状态。
  • Consistency:一致性,举个例子简单的理解就是,A、B 两个账户各有 100 元,无论两个账户并发相互转账多少次,两个账户的资金总额依然是 200 元。
  • Isolation:隔离性,并发事务之间的相互影响程度,隔离性也是分级别的:读未提交、读已提交、可重复读等。
  • Durability:持久性,事务完成后对数据的更改不会丢失。

单体数据库不涉及网络交互,所以在多表之间实现事务是比较简单的,这种事务我们称之为本地事务。

但是单体数据库的性能达到瓶颈的时候,就需要分库(分物理实例),就会出现跨库(数据库实例)的事务需求;随着企业应用的规模越来越大,企业会进一步进行服务化改造,以满足业务增长的需求;当前微服务架构越来越流行,跨服务的事务场景也会越来越多。

这些都是分布式事务的需求。分布式事务是指是指事务的发起者、参与者、数据资源服务器以及事务管理器分别位于分布式系统的不同节点之上。

概括起来,分布式事务有三种场景:

  • 跨数据库分布式事务
  • 跨服务分布式事务
  • 混合式分布式事务


分布式事务中涉及的参与者分布在异步网络中,参与者通过网络通信来达到分布式一致性,网络通信不可避免出现失败、超时的情况,因此分布式事务的实现比本地事务面临更多的困难。下面介绍下常见的分布式事务解决方案之基于消息的分布式事务。


基于消息的分布式事务

基于消息的分布式事务模式核心思想是通过消息系统来通知其他事务参与方自己事务的执行状态。

消息系统的引入更有效的将事务参与方解耦,各个参与方可以异步执行。

该种模式的难点在于解决本地事务执行和消息发送的一致性:两者要同时执行成功或者同时取消执行。

实现上主要有两种方式:

  • 基于事务消息的方案
  • 基于本地消息的方案

基于事务消息的分布式事务

普通消息是无法解决本地事务执行和消息发送的一致性问题的。因为消息发送是一个网络通信的过程,发送消息的过程就有可能出现发送失败、或者超时的情况。超时有可能发送成功了,有可能发送失败了,消息的发送方是无法确定的,所以此时消息发送方无论是提交事务还是回滚事务,都有可能不一致性出现。

解决这个问题,需要引入事务消息,事务消息和普通消息的区别在于事务消息发送成功后,处于 prepared 状态,不能被订阅者消费,等到事务消息的状态更改为可消费状态后,下游订阅者才可以监听到次消息

本地事务和事务消息的发送的处理流程如下:

  • 事务发起者预先发送一个事务消息。
  • MQ 系统收到事务消息后,将消息持久化,消息的状态是“待发送”,并给发送者一个 ACK 消息。
  • 事务发起者如果没有收到 ACK 消息,则取消本地事务的执行;如果收到了 ACK 消息,则执行本地事务,并给 MQ 系统再发送一个消息,通知本地事务的执行情况。
  • MQ 系统收到消息通知后,根据本地事务的执行情况更改事务消息的状态,如果成功执行,则将消息更改为“可消费”并择机下发给订阅者;如果事务执行失败,则删除该事务消息。
  • 本地事务执行完毕后,发给 MQ 的通知消息有可能丢失了。所以支持事务消息的 MQ 系统有一个定时扫描逻辑,扫描出状态仍然是“待发送”状态的消息,并向消息的发送方发起询问,询问这条事务消息的最终状态如何并根据结果更新事务消息的状态。因此事务的发起方需要给 MQ 系统提供一个事务消息状态查询接口。
  • 如果事务消息的状态是“可发送”,则 MQ 系统向下游参与者推送消息,推送失败会不停重试。
  • 下游参与者收到消息后,执行本地事务,本地事务如果执行成功,则给 MQ 系统发送 ACK 消息;如果执行失败,则不发送 ACK 消息,MQ 系统会持续推送给消息。


基于本地消息的分布式事务

基于事务消息的模式对 MQ 系统要求较高,并不是所有 MQ 系统都支持事务消息的,RocketMQ 是目前为数不多的支持事务消息的 MQ 系统。如果所依赖的 MQ 系统不支持事务消息,那么可以采用本地消息的分布式模式。

该种模式的核心思想是事务的发起方维护一个本地消息表,业务执行和本地消息表的执行处在同一个本地事务中。业务执行成功,则同时记录一条“待发送”状态的消息到本地消息表中。系统中启动一个定时任务定时扫描本地消息表中状态为“待发送”的记录,并将其发送到 MQ 系统中,如果发送失败或者超时,则一直发送,知道发送成功后,从本地消息表中删除该记录。后续的消费订阅流程则与基于事务消息的模式雷同。

特点剖析

基于消息的分布式事务模式对 ACID 特性的支持如下:

  • 原子性:最终可以实现分支事务都执行或者都不执行。
  • 一致性:提供最终一致性。
  • 隔离性:不保障隔离性。
  • 持久性:由本地事务来保证。

基于消息的分布式事务可以将分布式系统之间更有效的解耦,各个事务参与方之间的调用不再是同步调用。

对 MQ 系统的要求较高,对业务实现也有一定的侵入性,要么提供事务消息状态查询接口,要么需要维护本地消息表。并且原则上只接受下游分支事务的成功,不接受事务的回滚,如果失败就要一直重试,适用于对最终一致性敏感度较低的业务场景,例如跨企业的系统间的调用,适用的场景有限。


本文小结

本文详细介绍了一种分布式事务解决方案之基于消息的分布式事务,后续会对相关知识与内容进行深入的分析。

分布式事务模型--基于消息的分布式事务相关推荐

  1. 基于消息的分布式架构设计

    背景: 随着社会的发展,经济的飞跃,传统的单系统模式(webApp+DB)已经很难满足业务场景的需要.企业系统开始不断演化成多个子系统并存协作的局面.大大降低了系统间的耦合性,更重要的便于子系统的扩展 ...

  2. Mysql学习总结(83)——常用的几种分布式锁:ZK分布式锁、Redis分布式锁、数据库分布式锁、基于JDK的分布式锁方案对比总结

    一.基于数据库实现分布式锁 1.1.悲观锁 利用select - where - for update 排他锁.注意: 其他附加功能与实现一基本一致,这里需要注意的是"where name= ...

  3. 分布式计算机联锁系统,基于MAS的分布式计算机联锁系统研究

    基于MAS的分布式计算机联锁系统研究 第29卷 第1期2010年2月 文章编号:1001 4373(2010)01 0021 04 兰州交通大学学报 JournalofLanzhouJiaotongU ...

  4. php使用redis分布式锁,php基于redis的分布式锁实例详解

    在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现. 固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效 ...

  5. python分布式存储系统_基于Python的分布式文件共享系统的实现

    基于 Python 的分布式文件共享系统的实现 朱亚林 ; [期刊名称] <智能计算机与应用> [年 ( 卷 ), 期] 2015(005)004 [摘要] 大数据时代 , 信息的分享与传 ...

  6. 分布式会话和基于TOKEN的分布式会话

    单机会话管理 1.基于cookie传输的sessionId:在java tomcat容器session实现 http请求会有一个Session会话管理机制,用来标识用户会话的过程,默认使用的是spri ...

  7. 基于数据库的事务消息解决分布式事务方案

    转载请注明出处:http://www.cnblogs.com/lizo/p/8516502.html 概述 当单库已不能支撑当前业务的时候,我们往往都考虑进行分库(横向拆分或者纵向拆分).但分库有个无 ...

  8. 事务模型与分布式事务总结思考

    转载自 事务模型与分布式事务总结思考 1. 介绍 之前了解过一些分布式事务处理的思想,包括MVCC.TCC等.但是对具体实现的规范和约束还不够理解清晰.本文从事务模型分类来讨论常见的事务模型.事务模型 ...

  9. 分布式事务(三)、柔性事务之 TCC、Saga、本地消息表、事务消息、最大努力通知

    目录 [前言] TCC Saga [通知型事务] 本地消息表 MQ事务消息 最大努力通知 总结 分布式事务: 分布式事务(一).CAP,BASE理论 分布式事务(二).刚性事务之 2PC.3PC [前 ...

最新文章

  1. python mongodb 异步_【转】Python操作MongoDB数据库
  2. mascara-2(MetaMask/mascara本地实现)-连接线上钱包
  3. 函数调用栈 剖析+图解
  4. 关于fflush、缓冲区、scanf、EOF等问题真麻烦
  5. 数据库系统概念总结:第五章 高级SQL
  6. php接收get数组参数吗,php获取到data参数,如何与数组匹配
  7. Mongodb ruby driver API(中文)
  8. Codeforces Round #601 (Div. 2)
  9. html中文字过长 自动隐藏,css 实现文字过长自动隐藏功能
  10. 想系统化提升自己产品能力,就要读这些书籍
  11. 数仓开发神器--DBeaver
  12. Safari、IE8、iPhone和BlackBerry在Pwn2Own竞赛中被挑落
  13. BZOJ1001 狼抓兔子(网络流转最短路:对偶图)
  14. 批量生成 Hibernate Dao
  15. Java JDK中文帮助文档免费下载,百度网盘下载。
  16. PCI Express Base Specification Revision 3.0 英文手册 免费下载
  17. Kinect-v2 Examples with MS-SDK Doc(Chinese documents)
  18. Docker容器镜像加速器
  19. 搜索结果排列html模板,搜索结果页优化-城市模板
  20. 无法更新到Win8.1的原因与解决办法

热门文章

  1. Andriod Studio两种签名机制V1和V2的区别
  2. React性能优化记录(不定期更新)
  3. Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局
  4. 【转载】Java 内存分配全面浅析
  5. mybatis生成工具
  6. Java并发(一)wait()与notifyAll()
  7. c/c++ 基金会(七) 功能覆盖,虚函数,纯虚函数控制
  8. CentOS6.5与XP双系统安装
  9. 谷歌将于11月修改服务条款
  10. 在 Windows 下部署 Go 语言环境