利用事务消息实现分布式事务

举一个电商的例子,用户在购物车中付款,会调用一个服务生成一条订单,并调用另一个服务将该商品从购物车中删除。这两个操作应该是原子性的,要么都成功,要么都失败,这就是事务要解决的问题。我们下面来谈谈事务的概念、分布式事务的复杂点和实现方式。

一. 事务

事务的四大特性ACID:原子性、一致性、隔离性、持久性

1. 原子性

原子性指一个事务的操作是不可分割的,要么成功要么失败,不会存在成功一半的情况。

2. 一致性

一致性指一个事务在执行完成的时间点前读取到的一定是更新前的状态,执行完成后读取到的一定是更新后的状态,不会存在一个时间点读取到执行到一半的状态。

3. 隔离性

隔离性指一个事务的执行不会被其他事务干扰。

4. 持久性

持久性指一个事务一旦提交,后续的操作和故障不会对事务的结果产生影响。

二. 分布式事务

在分布式系统中,有着不同的服务,不同的数据存储位置。在保证可用性和较好的性能的同时,实现数据的一致性是一件较为困难的事情。我们一般采用的都是替代解决方案,比如顺序一致性、最终一致性等等。

在实际应用中,比较常见的分布式事务实现方式有2PC(二阶段提交)、TCC和事务消息。我们着重介绍一下事务消息实现的分布式事务。

1. 事务消息的应用场景

事务消息适用场景主要是那些需要异步更新数据,并且对数据的实时性要求的高的场景。比如,我们在开始提到的例子,创建订单后,购物车的数据延迟1秒清空也是完全可以接受的,只要最终购物车的数据和订单数据保持一直就可以了。

2. 事务消息是如何实现的?

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

回到刚才的例子,看看事务消息是如何在订单创建中完成工作的。

首先,订单系统在消息队列上开启一个事务,然后订单系统会给消息队列服务器发送一个"半消息",这个半消息不是说消息内容不完整,而是说事务提交前,这个消息对消费者来说是不可见的。半消息发送成功以后,订单系统开始创建订单,并根据订单创建是否成功来决定事务消息是提交还是回滚。事务消息提交后,消费者就能获取到这个消息并作出相应的处理。这样一来就基本实现了"要么都成功,要么都失败"的一致性要求。

其中还有一个麻烦的问题,如果在提交事务时遇到网络或者服务器故障导致提交失败了怎么办?RocketMQ和kafka都给出了各自的解决方案。kafka直接抛出异常,让用户自行处理。而RocketMQ增加了事务反查机制,如果RocketMQ没有收到提交或者回滚的请求,Broker会定期去Producer上反查这个事务对应的本地事务的状态,然后在根据反查结果决定提交或者回滚消息事务。为了支撑这个反查机制,我们的业务代码还需要实现一个反查本地事务的接口,告知RocketMQ本地事务是成功还是失败。

在我们的这个例子中,反查本地事务的接口逻辑很简单,我们只要根据消息队列中的订单ID,在订单中查询这个订单是否存在即可,RocketMQ会自动根据反查结果提交或者回滚事务消息。

这个反查事务的实现,并不依赖消息的发送方,也就是订单服务的某个实例节点上的任何数据。这种情况下,即使是发送事务消息的那个订单节点宕机了,RocketMQ依然可以通过其他订单节点来执行反查,确保事务的完整性。

原文地址:https://www.cnblogs.com/wang-yi-shan/p/11657831.html

时间: 2024-08-29 16:10:02

利用事务消息实现分布式事务的相关文章

搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务

搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务 初步认识RocketMQ的核心模块 rocketmq模块 rocketmq-broker:接受生产者发来的消息并存储(通过调用rocketmq-store),消费者从这里取得消息. rocketmq-client:提供发送.接受消息的客户端API. rocketmq-namesrv:NameServer,类似于Zookeeper,这里保存着消息的TopicName,队列等运行时的元信息.(有点NameNode的味道) rocketm

猪齿鱼_学习_01_事务(三)_分布式事务解决方案

一.前言 本文承接上一节:猪齿鱼_学习_01_事务(二)_分布式理论 第一节中,我们谈到了本地事务数据库断电时的故障恢复: 我们在执行事务的时候数据库首先会记录下这个事务的redo操作日志,然后才开始真正操作数据库,在操作之前首先会把日志文件写入磁盘,那么当突然断电的时候,即使操作没有完成,在重新启动数据库时候,数据库会根据当前数据的情况进行undo回滚或者是redo前滚,这样就保证了数据的强一致性. 分布式系统的核心就是处理各种异常情况,这也是分布式系统复杂的地方,因为分布式的网络环境很复杂,

对分布式事务、消息队列的重新认识

本质上问题可以抽象为:当一个表数据更新后,怎么保证另一个表的数据也必须要更新成功.若两张表在同一个数据库实例中,则使用本地事务就好了.否则可以采用分布式事务,或者消息队列. 前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品

分布式事务消息队列的应用

前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在点击事件表中增加一条记录外,还得去商家账户表中找到这个商家并扣除广告费吧,怎么保证?!等等,相信大家或

用消息系统实现分布式事务的简单设想

前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在点击事件表中增加一条记录外,还得去商家账户表中找到这个商家并扣除广告费吧,怎么保证?!等等,相信大家或

如何用消息系统避免分布式事务?

前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在点击事件表中增加一条记录外,还得去商家账户表中找到这个商家并扣除广告费吧,怎么保证?!等等,相信大家或

如何用消息系统避免分布式事务

前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在点击事件表中增加一条记录外,还得去商家账户表中找到这个商家并扣除广告费吧,怎么保证?!等等,相信大家或

[转]如何使用消息系统避免分布式事务?

文章来源:伯乐在线-占利军 原文地址:http://blog.jobbole.com/89140/ 前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在点

(转)如何用消息队列来代替分布式事务

转自:http://blog.csdn.net/ss123465/article/details/7964184 由于数据量的巨大,大部分Web应用都需要部署很多个数据库实例.这样,有些用户操作就可能需要去修改多个数据库实例中的数据.传统的解决方法是使用分布式事务保证数据的全局一致性,经典的方法是使用两阶段提交协议. 长期以来,分布式事务提供的优雅的全局ACID保证麻醉了应用开发者的心灵,很多人都不敢越雷池一步,想像没有分布式事务的世界会是怎样.如今就如MySQL和PostgreSQL这类面向低