参考文档:

如何用消息系统避免分布式事务:http://blog.jobbole.com/89140/

https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html

消息系统避免分布式事务

什么是用消息系统避免分布式事务

如果仔细观察生活的话,生活的很多场景已经给了我们提示
    比如在北京很有名的姚记炒肝点了炒肝并付了钱后,他们并不会直接把你点的炒肝给你,而是给你一张小票,然后让你拿着小票到出货区排队去取。为什么他们要将付钱和取货两个动作分开呢?原因很多,其中一个很重要的原因是为了使他们接待能力增强(并发量更高)
    还是回到我们的问题,只要这张小票在,你最终是能拿到炒肝的。同理转账服务也是如此,当支付宝账户扣除1万后,我们只要生成一个凭证(消息)即可,这个凭证(消息)上写着“让余额宝账户增加 1万”,只要这个凭证(消息)能可靠保存,我们最终是可以拿着这个凭证(消息)让余额宝账户增加1万的,即我们能依靠这个凭证(消息)完成最终一致性
    一种非常经典的实现,避免了分布式事务,实现了最终一致性

如何可靠保存凭证(消息)
业务与消息耦合的方式

支付宝在完成扣款的同时,同时记录消息数据,这个消息数据与业务数据保存在同一数据库实例里(消息记录表表名为message)
该事务能保证只要支付宝账户里被扣了钱,消息一定能保存下来。
当上述事务提交成功后,我们通过实时消息服务将此消息通知余额宝,余额宝处理成功后发送回复成功消息,支付宝收到回复后删除该条消息数据

业务与消息解耦方式

上述保存消息的方式使得消息数据和业务数据紧耦合在一起,从架构上看不够优雅,而且容易诱发其他问题。为了解耦,可以采用以下方式
1)支付宝在扣款事务提交之前,向实时消息服务请求发送消息,实时消息服务只记录消息数据,而不真正发送,只有消息发送成功后才会提交事务
2)当支付宝扣款事务被提交成功后,向实时消息服务确认发送。只有在得到确认发送指令后,实时消息服务才真正发送该消息
3)当支付宝扣款事务提交失败回滚后,向实时消息服务取消发送。在得到取消发送指令后,该消息将不会被发送
4)对于那些未确认的消息或者取消的消息,需要有一个消息状态确认系统定时去支付宝系统查询这个消息的状态并进行更新。为什么需要这一步骤,举个例子:假设在第2步支付宝扣款事务被成功提交后,系统挂了,此时消息状态并未被更新为“确认发送”,从而导致消息不能被发送
优点:消息数据独立存储,降低业务系统与消息系统间的耦合
缺点:一次消息发送需要两次请求;业务处理服务需要实现消息状态回查接口

如何解决消息重复投递的问题

还有一个很严重的问题就是消息重复投递,以我们支付宝转账到余额宝为例,如果相同的消息被重复投递两次,那么我们余额宝账户将会增加2万而不是1万了。
为什么相同的消息会被重复投递?比如余额宝处理完消息msg后,发送了处理成功的消息给支付宝,正常情况下支付宝应该要删除消息msg,但如果支付宝这时候悲剧的挂了,重启后一看消息msg还在,就会继续发送消息msg。
解决方法很简单,在余额宝这边增加消息应用状态表(message_apply),通俗来说就是个账本,用于记录消息的消费情况,每次来一个消息,在真正执行之前,先去消息应用状态表中查询一遍,如果找到说明是重复消息,丢弃即可,如果没找到才执行,同时插入到消息应用状态表(同一事务)

支持事务的消息队列MQ

比如:RocketMQ
基本原理就是以上“消息系统避免分布式事务”,事务消息队列做了比较好的封装
举个栗子

解决a转账给b的问题
具体来说,就是把消息的发送分成了2个阶段:Prepare阶段和确认阶段
具体来说,上面的2个步骤,被分解成3个步骤:
(1) 发送Prepared消息
(2) update DB
(3) 根据update DB结果成功或失败,Confirm或者取消Prepared消息
前2步执行成功了,最后1步失败了怎么办?
这里就涉及到了RocketMQ的关键点:RocketMQ会定期(默认是1分钟)扫描所有的Prepared消息,询问发送方,到底是要确认这条消息发出去?还是取消此条消息?所以本地消息表其实还是存在的。只不过消息中间件帮助业务方做了扫描本地消息表这件事

Sagas 事务模型

Saga事务模型又叫做长时间运行的事务(Long-running-transaction), 它是由普林斯顿大学的H.Garcia-Molina等人提出,它描述的是另外一种在没有两阶段提交的的情况下解决分布式系统中复杂的业务事务问题。你可以在这里看到 Sagas 相关论文
该模型其核心思想就是拆分分布式系统中的长事务为多个短事务,或者叫多个本地事务,然后由 Sagas 工作流引擎负责协调,如果整个流程正常结束,那么就算是业务成功完成,如果在这过程中实现失败,那么Sagas工作流引擎就会以相反的顺序调用补偿操作,重新进行业务回滚
比如我们一次关于购买旅游套餐业务操作涉及到三个操作,他们分别是预定车辆,预定宾馆,预定机票,他们分别属于三个不同的远程接口。可能从我们程序的角度来说他们不属于一个事务,但是从业务角度来说是属于同一个事务的

他们的执行顺序如上图所示,所以当发生失败时,会依次进行取消的补偿操作。
因为长事务被拆分了很多个业务流,所以 Sagas 事务模型最重要的一个部件就是工作流或者你也可以叫流程管理器(Process Manager),工作流引擎和Process Manager虽然不是同一个东西,但是在这里,他们的职责是相同的

分布式事务解决方案(二)消息系统避免分布式事务 & MQ事务消息 & Sagas 事务模型的更多相关文章

  1. 阿里分布式事务解决方案-GTS

    摘要: 本文将深入和大家探讨微服务架构下,分布式事务的各种解决方案,并重点为大家解读阿里巴巴提出的分布式事务解决方案----GTS.该方案中提到的GTS是全新一代解决微服务问题的分布式事务互联网中间件 ...

  2. 微服务架构下分布式事务解决方案——阿里GTS

    1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...

  3. Kafka — 高吞吐量的分布式发布订阅消息系统【转】

    1.Kafka独特设计在什么地方?2.Kafka如何搭建及创建topic.发送消息.消费消息?3.如何书写Kafka程序?4.数据传输的事务定义有哪三种?5.Kafka判断一个节点是否活着有哪两个条件 ...

  4. 微服务架构下分布式事务解决方案——阿里云GTS

    https://blog.csdn.net/jiangyu_gts/article/details/79470240 1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这 ...

  5. 分布式事务(二)Java事务API(JTA)规范

    一.引子 既然出现了分布式场景(DTP模型), 大java也及时制定出一套规范来给各大应用服务器.数据库/mq等厂商使用,以方便管理互通--->JTA闪亮登场.JTA(Java Transact ...

  6. Kafka消息系统

    一.基本概念 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计. 首先让我们看几个基本的消息系统术语: Kafka将消息以topic为单位进行归纳 ...

  7. Kafka不只是个消息系统

    作者丨 Jay Kreps Confluent 联合创始人兼 CEO Jay Kreps 发表了一篇博文,给出了 Kafka 的真正定位——它不只是个消息系统,它还是个存储系统,而它的终极目标是要让流 ...

  8. 现代IM系统中的消息系统架构 - 模型篇

    前言 在架构篇中我们介绍了现代IM消息系统的架构,介绍了Timeline的抽象模型以及基于Timeline模型构建的一个支持『消息漫游』.『多端同步』和『消息检索』多种高级功能的消息系统的典型架构.架 ...

  9. 分布式开放消息系统RocketMQ的原理与实践(消息的顺序问题、重复问题、可靠消息/事务消息)

    备注:1.如果您此前未接触过RocketMQ,请先阅读附录部分,以便了解RocketMQ的整体架构和相关术语2.文中的MQServer与Broker表示同一概念 分布式消息系统作为实现分布式系统可扩展 ...

随机推荐

  1. 深入V8引擎-默认Platform之mac篇(2)

    先说结论,V8引擎在默认Platform中初始化的这个线程是用于处理类似于setTimeout的延时任务. 另外附一些图,包括继承树.关键属性归属.纯逻辑工作流程,对代码木得兴趣的看完图可以X掉了. ...

  2. new/delete与malloc/free的区别

    new/delete与malloc/free的区别 参考: https://blog.csdn.net/u013485792/article/details/51329541 https://www. ...

  3. 2 java并行基础

    我们认真研究如何才能构建一个正确.健壮并且高效的并行系统. 进程与线程 进程(Process):是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础 ...

  4. Centos7 日志查看工具

    1  概述     日志管理工具journalctl是centos7上专有的日志管理工具,该工具是从message这个文件里读取信息.Systemd统一管理所有Unit的启动日志.带来的好处就是,可以 ...

  5. 微服务架构 ------ 插曲 Linux平台 Ubuntu的安装

    1.一定要通过自定义安装 2.选择的硬件兼容性选择 14.x   这里介绍一下红框内的东西,是为了做虚拟存储使用的,也就是一批服务器对外展示位一个服务器,类似于服务器集群 3.选择稍后安装操作系统,如 ...

  6. vue+element 根据内容计算单元格的宽度

    需求是这样的,之前我也写过,就是前端渲染的表格数据是动态渲染表格的行和列, 那么就必然出现了一个问题,当列超过一定的个数的时候,会出现横向滚动条, 那么怎么让表格整体看起来自然协调一些呢,老大要求表格 ...

  7. Java进程间通信学习

    转自:https://www.iteye.com/blog/polim-1278435 进程间通信的主要方法有:(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共 ...

  8. How to use VideoToolbox to decompress H.264 video stream

    来源:http://stackoverflow.com/questions/29525000/how-to-use-videotoolbox-to-decompress-h-264-video-str ...

  9. PHP查询附近的人及其距离的实现方法

    1.附近的人 //获取该点周围的4个点 $distance = 1;//范围(单位千米) $lat = 113.873643; $lng = 22.573969; define('EARTH_RADI ...

  10. python处理excel函数xlrd、xlwt

    https://www.jianshu.com/p/f2c9dff344c6 https://www.cnblogs.com/ilovepython/p/11068841.html 行列操作:http ...