互联网电商大厂的分布式事务使用案例

news2024/11/23 19:18:18

事务的原子性、持久性可确保在一个事务内,更新多条数据都成功/失败。在一个系统内部,我们可以使用数据库事务来保证数据一致性。那如果一笔交易,涉及到跨多个系统、多个数据库的时候,用单一的数据库事务就没办法解决了。

在之前大系统时代,普遍的做法:设计时尽量避免这种跨系统跨数据库的交易。

但现在技术趋势是云原生和微服务,大系统被打散成多个微服务,每个微服务独立部署并拥有自己的数据库,大数据库也被打散成多个小数据库。跨越微服务和数据库的交易就成为普遍情况,不可避免要面对跨系统的数据一致性问题。

如何解决这种跨系统、跨数据库的数据一致性问题?分布式事务。但它可不像数据库事务,在开始和结尾分别加上begin和commit,剩下的问题数据库都可以帮我们搞定。

分布式环境,一个交易将会被分布到不同系统,多个微服务进程内执行计算,在多个数据库中执行数据更新操作,这比数据库事务支持的单进程单数据库场景复杂多。所以,并没有什么分布式事务服务或组件能在分布式环境下,提供接近数据库事务的数据一致性保证。

如何用分布式事务的方法,解决微服务系统中实际面临的分布式数据一致性问题呢?

1 什么是分布式事务

没有一种分布式事务的服务或组件,能简单解决分布式系统下的数据一致性问题。使用分布式事务时,更多情况是,用分布式事务理论指导设计和开发,自行解决数据一致性问题。即要解决分布式一致性问题,须掌握分布式事务实现原理。

即使是数据库事务,它考虑到性能因素,大部分情况下不能也不需要百分之百地实现ACID,所以才有事务隔离级别。

分布式事务也是事务,也需遵从ACID。但实际分布式系统中,因为须兼顾性能、高可用,不可能完全满足ACID。分布式事务实现都是“残血版”事务,相比数据库事务,更加“残血”。

分布式事务的解决方案如:2PC、3PC、TCC、Saga和本地消息表。强、弱项都不一样,适用场景也不一样。2PC和本地消息表较贴近于日常开发的业务系统。

2 2PC:订单与优惠券的数据一致性问题

2PC,二阶段提交。

购物下单时,若使用了优惠券,订单系统、优惠券系统都要更新自己的数据,才能完成“在订单中使用优惠券”的操作。

订单系统需:

  1. 在“订单优惠券表”中写入订单关联的优惠券数据
  2. 在“订单表”中写入订单数据

订单系统内两个操作的一致性问题可直接使用DB事务。

促销系统需要操作就比较简单,把刚使用的那张优惠券的状态更新成“已使用”。

需要这两个系统的数据更新操作保持一致,都更新成功/失败。

2PC怎么解决问题

2PC引入一个

事务协调者

来协调订单系统和促销系统,协调者对客户端提供一个完整的“使用优惠券下单”的服务,在这个服务内部,协调者再分别调用订单、促销的相应服务。

二阶段

准备阶段、提交阶段:

准备阶段

协调者分别给订单系统、促销系统发“准备”命令,订单、促销系统收到准备命令后,开始执行准备操作。准备阶段都需要做哪些事儿呢?除了提交数据库事务以外的所有工作,都要在准备阶段完成。如订单系统在准备阶段需完成:

  1. 在订单库开启一个DB事务
  2. 在“订单优惠券表”写入这条订单的优惠券记录
  3. 在“订单表”中写入订单数据

到这里,我们没提交订单DB的事务,最后给事务协调者返回“准备成功”。

同理,促销服务在准备阶段,需在促销库开启一个DB事务,更新优惠券状态,但暂不提交该DB事务,给协调者返回“准备成功”。

协调者收到两个系统“准备成功”的响应后,开始进入第二阶段。等两个系统都准备好,进入

提交阶段

协调者再给这两个系统发“提交”命令,每个系统提交自己的DB事务,然后给协调者返回“提交成功”响应。

协调者收到所有响应后,给客户端返回成功响应,整个分布式事务结束。

该过程的时序图

img

这都是理想的正常情况

3 异常了怎么办?

还分两个阶段

3.1 准备阶段

若任一步错误或超时,协调者就会给两个系统发送“回滚事务”请求。每个系统在收到请求之后,回滚自己的DB事务,分布式事务执行失败,两个系统的DB事务都回滚了,相关的所有数据回滚到分布式事务执行之前的状态,就像这个分布式事务没有执行一样。

3.1.1 异常情况时序图

img

若准备阶段成功,则进入

3.2 提交阶段

这就只剩一条路,整个分布式事务只能成功,不能失败。

若该阶段发生如下异常:

网络传输失败

需反复重试,直到提交成功。

宕机

包括两个DB宕机或订单服务、促销服务节点宕机,还是可能出现订单库完成提交,但促销库因宕机自动回滚,导致数据不一致。但因提交的过程很简单,执行很快,出现这种情况的概率很小,所以,从实用角度,2PC实际的数据一致性还是很好的。

实现2PC时,没必要单独启动一个事务协调服务,该协调服务的工作最好和订单服务或优惠券服务放在同一进程,好处是:

  • 参与分布式事务的进程更少,故障点就更少,稳定性更好
  • 减少远程调用,性能也更好

2PC是一种强一致设计,它可保证原子性、隔离性。只要2PC事务完成,订单库、促销库中的数据一定是一致状态,即都成功/失败。

所以2PC适合那些对数据一致性要求较高场景,如订单优惠券,若一致性保证不好,有可能会被黑产利用,一张优惠券反复使用!

2PC的缺陷

整个事务的执行过程,需阻塞服务端的线程和数据库的会话,所以,2PC在并发场景下的性能不太高。

协调者是个单点,一旦协调者宕机,就会导致订单库或促销库的事务会话一直卡在等待提交阶段,直到事务超时自动回滚。

卡住的这段时间,DB可能会锁住一些数据,服务中会卡住一个数据库连接和线程,这些都会造成系统性能严重下降,甚至整个服务被卡住。

适用场景

所以,只有在需强一致、并发量不大,才考虑2PC。

3 本地消息表:订单与购物车的数据一致性问题

2PC适用场景很窄,更多情况下,只要保证数据最终一致。如购物流程中,用户在购物车选好商品,点击“去结算”按钮,进入订单页面创建一个新订单。这过程,我们的系统做了:

  1. 订单系统需创建一个新订单,订单关联的商品就是购物车中选择的那些商品
  2. 创建订单成功后,购物车系统需将订单中的这些商品从购物车删掉

这也是分布式事务问题,创建订单、清空购物车两个数据更新操作需保证都成功/失败。但清空购物车对一致性要求没扣减优惠券那么高,订单创建成功后,晚几s再清空购物车,完全可接受。只要保证经过小延迟后,最终的订单数据和购物车数据保持一致。

3.1 适用场景

分布式最终一致性问题。

3.2 实现思路

订单服务在收到下单请求后,正常使用订单库的事务去更新订单数据。执行这个DB事务过程中,在本地记录一条消息,即一个日志,内容:“清空购物车”。因为这日志记录在本地,不牵涉分布式问题,那这就是普通的单机事务,那我们就能让订单库的事务,来保证记录本地消息和订单库的一致性。完成这步后,就能给客户端返回成功响应。

然后,再用一个异步服务,读取刚记录的清空购物车的本地消息,调用购物车系统的服务清空购物车。购物车清空后,把本地消息的状态更新成已完成。异步清空购物车这个过程,若操作失败,可重试。最终,可保证订单系统和购物车系统它们的数据一致。

这里的本地消息表,可选择:

  • 存在订单库

    相对来说,放在订单库更简单

  • 也可用文件的形式,保存在订单服务所在服务器的本地磁盘

RocketMQ提供事务消息,就是本地消息表思想的实现。使用事务消息可达到和本地消息表一样的最终一致性,相比自己实现本地消息表,使用更简单。

本地消息表只满足D(持久性),A(原子性)C(一致性)、I(隔离性)都较差,但

优点突出

实现简单

在单机事务的基础上稍加改造,即可实现分布式事务。

性能非常好

和单机事务的性能几乎无差。在这基础,还提供大部分情况下都能接受的“数据最终一致性”的保证。

所以,本地消息表是更实用的分布式事务实现。即使能接受数据最终一致,本地消息表也不是银弹。

使用前提

异步执行的那部分操作,不能有依赖资源。如下单时,除了要清空购物车,还要锁定库存。

库存系统锁定库存的操作,虽能接受数据最终一致,但锁定库存有前提:库存中得有货。这就不适合本地消息表,不然就会出现用户下单成功后,系统的异步任务去锁定库存时,因为缺货导致锁定失败。这种case就很难处理。

4 总结

对订单和优惠券这种需强一致的分布式事务场景,可采用2PC。优点强一致,但性能和可用性都有缺陷。

本地消息表适用性更广,虽在数据一致性有所牺牲,只满足最终一致性,但有更好性能,实现简单,系统稳定性也很好。

无论是哪种分布式事务方法,其实都是把一个分布式事务,拆分成多个本地事务。本地事务可以用DB事务,那分布式事务就专注于解决如何让这些本地事务保持一致。

遇到分布式一致性问题的时候,也要基于这个思想来考虑问题,再结合实际的情况选择分布式事务实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/89877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Altova MissionKit Enterprise 2023 SP1 Crack

屡获殊荣的 XML、JSON、SQL 和 UML 工具套件 以低于 2 个的价格获得 7 个 XML、JSON SQL 和 UML 工具! Altova MissionKit 是面向信息架构师和应用程序开发人员的企业级 XML、JSON、SQL 和 UML 工具的软件开发套件。MissionKit 包括 Altova XMLSpy、MapForce、Styl…

Python 中的垃圾回收机制总结(1)

1.背景 对于Python来说,一切皆为对象,所有的变量赋值都遵循着对象引用机制。 程序在电脑上运行的时候,需要在内存中开辟出一块空间,用于存放运行时产生的临时变量,一方面,内存的容量是有限的;…

JNPF3.4.5消息模块:多渠道应用,配置灵活多样,满足更多使用场景

自11月15日,JNPF 3.4.5 JAVA版本上线,就受到了众多用户的广泛好评,此次更新为用户带来了不同以往的使用体验。 在本次更新中,所有工作流都可以实现自主配置消息模板的操作,同时包括站内信,也可以实现自主配…

sublime json美化

sublime 的插件 json美化感觉很难用,好多正常的json串都 不能正常解析 ,自己写了一个json解析插件,此插件跟网上教程的json美化插件 不同的是: 只对json的特殊字符进行格式化 { [ ] } : , 这种不是很严格但是正好解决了我的问…

【Redis】Redis 持久化

文章目录概述RDB触发机制如何恢复 rdb 文件?RDB 优点:RDB 缺点:AOFAOF 优点AOF 缺点概述 Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么服务器一旦进程退出,服务器中的数据库状态也会消失…

【C语言进阶】一文速通面试中的指针相关疑难杂症(内含模拟库函数 qsort 的实现)

目录 🥇前言🥇: 一、指向函数指针数组的指针🤯: 1.书写格式🦚: 2.指向函数指针数组指针示例🦩: 二、回调函数🧐: 1.回调函数的定义&#x1f99…

嵌入式软件工程师技能树——应用编程/网络编程/驱动开发/操作系统/计算机网络

文章目录Linux驱动开发1、Linux内核组成2、用户空间与内核的通讯方式有哪些?3、系统调用read/write流程4、内核态用户态的区别5、bootloader内核 根文件的关系6、BootLoader的作用7、BootLoader两个启动阶段1、汇编实现,完成依赖于CPU体系架构的设置&…

Win10安装Linux虚拟机-安装与使用

Win10安装Linux虚拟机-安装与使用 1、VMware 的下载 VMWare虚拟机软件是一个“虚拟PC”软件,它使你可以在一台机器上同时运行二个或更多Windows、DOS、LINUX系统。 下载地址:https://customerconnect.vmware.com/en/downloads/#all_products 在搜索中…

用 Charles 断点调试 HTTPS 请求,原理解析

现在的网站基本都是 https 的,而 charles 是常用的 http 抓包工具,所以用 charles 调试 https 请求是常见的需求。 今天就分享下如何用 charles 调试 https 请求,如何打断点。 首先安装 charles,点击 start recording&#xff1…

FineReport平台数据分析-图表显示部分系列接口

1. 概述 1.1 应用场景 当图表系列较多时,用户希望可以自己设置哪些系列显示,哪些系列不显示。以决策报表为例,实现效果如下图: 1.2 实现思路 通过FR.Chart.WebUtils.getChart("chartID").getChartWithIndex(chartInde…

静态HTML旅行主题网页作业——青岛民俗7页html+css+javascript+jquery 地方民俗网页设计与实现

👨‍🎓静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计👩‍🎓,一般的网页作业需要融入以下知识点:div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

web开发:linux常用命令总结

1.关于目录操作: (1)ls 列出当前目录下都有哪些文件/目录 也可以写成: ls 指定目录 列出指定目录下的文件/目录 还可以写成 ls -l 指定目录 以列表的形式列出 或缩写成 ll 指定目录 (2)pwd 查看当前…

shared_ptr

先看源码 template<typename _Tp> class shared_ptr : public __shared_ptr<_Tp> {template<typename... _Args>using _Constructible typename enable_if<is_constructible<__shared_ptr<_Tp>, _Args...>::value>::type;template<ty…

【TuyaOS开发之旅】环境搭建

前言 涂鸦最近更新了打磨良久的TuyaOS&#xff0c;整体使用感受非常的nice。所以决定写一个专栏讲解一下TuyaOS的入门使用&#xff0c;来方便小白快速的入门和熟悉TuyaOS的开发。 官方环境搭建教程 Tuya Wind IDE-TuyaOS-涂鸦开发者 报错和解决 暂无 补充 程序下载方法 …

MetaFormer实际上是你所需要的视觉

transformer在计算机视觉任务中显示出了巨大的潜力。人们普遍认为&#xff0c;他们基于注意力的token混合器模块对他们的能力贡献最大。然而&#xff0c;最近的工作表明&#xff0c;transformer中基于注意力的模块可以被空间mlp取代&#xff0c;得到的模型仍然表现相当好。基于…

11.关联容器

文章目录关联容器11.1使用关联容器使用map使用set11.2关联容器概述11.2.1定义关联容器初始化multimap或multiset11.2.2关键字类型的要求有序容器的关键字类型使用关键字类型的比较函数11.2.3pair类型创建pair对象的函数11.3关联容器操作11.3.1关联容器迭代器set的迭代器是const…

为什么Docker比VM虚拟机快?

(1)docker有着比虚拟机更少的抽象层 由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化&#xff0c;运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。 (2)docker利用的是宿主机的内核,而不需要加载操…

基于springboot招生管理系统设计与实现的源码+文档

摘 要 在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括招生管理系统的网络应用&#xff0c;在外国招生管理系统已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。招生管理系统具有招生公告信息管理功能…

实训任务一

文章目录实训任务一一、实训任务1、创建并且配置三个虚拟机2、创建SSH连接3、实现IP地址与主机名的映射4、关闭和禁用防火墙5、创建目录结构6、压缩打包7、安装软件包8、创建脚本文件9、直接运行脚本10、虚拟机相互免密登录11、远程拷贝文件实训任务一 需求&#xff1a;熟练掌…

java+MySQL 基于ssm高校创新实践学分认定系统

随着现代实践学分认定的快速发展,可以说实践学分认定已经逐渐成为现代实践学分认定过程中最为重要的部分之一。但是一直以来我国传统的实践学分认定并没有建立一套完善的行之有效的实践学分认定系统,传统的实践学分认定已经无法适应高速发展,无论是从效率还是从效果来看都远远的…