4000-9696-28

分布式事务那些事儿

2023年08月16日 08:59供稿中心:北大青鸟总部

摘要: 事务就是用户定义的一系列数据库操作,这些操作可以视为一个完成的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元。所谓分布式事务,就是指事务的资源分别位于不同的分布式系统的不同节点之上的事务。

提到事务两个字,相信每一个开发人员都不陌生,从我们第一次开始接触数据库的时候,也就开始和事务打交道;而且是一直打交道,很可能要打一辈子交道。

为什么这么说呢,大家都知道,互联网经过这么几年快速的发展,互联网技术也更新迭代了很多个版本,从最初的单体架构,到现在的分布式、微服务架构。

系统同样也越来越复杂了,也就意味着问题越来越多了,原来单体架构时的一个小问题,放在了现在可能就是个大问题,需要系统的去解决,就不能像之前那样,凑合过呗,毕竟夫妻和谐也是很重要的。



所以,单体阶段可能只需要处理好数据库的本地事务就可以了,但是到了分布式系统中,事务的事儿,也就变成了一件大事儿。

这篇文章,我们就来聊聊怎么来处理好这个大事儿,以及现在业内常用的解决方案有哪些?


什么是事务?

为了让大家更好的能理解分布式的那些儿,我们还是先来回顾一下基础的知识,比如第一个概念,什么是事务?咱们先来看下官方的解释。

事务就是用户定义的一系列数据库操作,这些操作可以视为一个完成的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元。

说人话就是,事务是指程序中一系列严密的逻辑操作,而且所有操作必须全部成功完成,否则在每个操作中所做的所有更改都会被撤销。

可以通俗理解为,大家要一起去抢银行,要么都活着回来,要都永远别回来了(牢里),就是一根绳上的蚂蚱,不求同年同月同日生,但求同年同月同日死,听上去还颇有些悲壮的感觉。



什么是分布式事务?

好了,事务我们知道怎么回事儿了,那什么是分布式事务呢?它有特殊在哪里呢?接下来我们就来一探究竟。

所谓分布式事务,就是指事务的资源分别位于不同的分布式系统的不同节点之上的事务;这个又是啥意思嘞?举个栗子


动图封面


在早期单体架构时,通常情况下都是单库单表场景,但是现在不是到了分布式环境下了嘛,业务数据非常庞大,所以当业务数据量达到单库单表的极限时,就需要考虑分库分表,将之前的单库单表拆分成多库多表;分库分表之后,原来在单个数据库上的事务操作,可能就变成跨多个数据库的操作,此时就需要使用分布式事务。如果你还不明白,那就再举个栗子



我们的一个系统有 3个功能模块:用户模块商品模块和订单模块,我们现在有一个操作需要按顺序去调用完成这3个模块中的接口,这个操作是一个整体,包含在一个事务中,要么同时成功要么同时失败回滚。不成功便成仁,这个都没有问题。

但是当我们把这个系统拆分成分布式系统架构的时候,事务就不是上面那么玩儿了,原来的用户模块、商品模块和订单模块,都升级变成了用户系统、商品系统和订单系统,每个系统都是独立部署,甚至拥有独立的数据库。

这么一来,分布式事务就复杂多了,怎么才能保证三个不同的系统,针对同一个操作能保持一致性,因为这个三个系统之间要么是RPC通讯,要么是HTTP通信,这就增加了事情的难度。不过,方法总比问题多,程序员是一帮聪明绝顶的人!


分布式事务常见解决方案

分布式事务常见的解决方案,现在通用的基本就如下这三种:

· 两阶段提交(2PC, Two Phase Commit)

· 本地消息表(eBay模式)

· 补偿模式TCC


接下来我们就分别来看下几种解决方案的特点。


两阶段提交(2PC,Two Phase Commit)方案

我们先来看下两阶段提交,两阶段提交其实就是为了保证分布在不同节点上的分布式事务的一致性,我们需要引入一个协调者来管理所有的节点,负责各个本地资源的提交和回滚,并确保这些节点正确提交操作结果,若提交失败则放弃事务。



它有两个阶段

· 第一阶段:准备阶段(prepare) 协调者通知参与者准备提交订单,参与者开始投票。参与者完成准备工作向协调者回应Yes

· 第二阶段:提交(commit)/回滚(rollback)阶段 协调者根据参与者的投票结果发起最终的提交指令。如果有参与者没有准备好则发起回滚指令


本地消息表(eBay模式)

本地消息表,为什么又称为eBay模式呢?那是因为eBay的架构师Dan Pritchett,曾在一篇解释BASE原理的论文《Base:AnAcid Alternative》中提到一个eBay分布式系统一致性问题的解决方案。

它的核心思想是将需要分布式处理的任务通过消息或者日志的方式来异步执行,消息或日志可以存到本地文件、数据库或消息队列,再通过业务规则进行失败重试,它要求各服务的接口是幂等的。

本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。

· 在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。

· 之后将本地消息表中的消息转发到 Kafka 等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。

·在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。


TCC补偿事务

TCC补偿事务,全称Try-Confirm-Cancel,又叫做柔性事务。TCC补偿事务方案可能是目前最火的一种柔性事务方案了。它的核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。

关于TCC(Try-Confirm-Cancel)的概念,最早是由PatHelland于2007年发表的一篇名为《Lifebeyond Distributed Transactions:an Apostate’s Opinion》的论文提出。

在该论文中,TCC还是以Tentative-Confirmation-Cancellation命名。正式以Try-Confirm-Cancel作为名称的是Atomikos公司,其注册了TCC商标(外国人的版权意识真强)。


它也分三个阶段:

· Try阶段主要是对业务系统做检测及资源预留。

· Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。

· Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。



好了,到这里基本就把分布式事务的事儿,翻了个底朝天,其实也就那么回事儿;理论都有了,剩下的就是我们自己在真实的业务场景中去实战了!


标签:
关于我们
公司简介
发展历程
青鸟荣誉
联系我们
加入我们
青鸟课程
BCVE视频特效课程
BCUI全链路UI设计
BCSP软件开发专业
BCNT网络工程师
启能职业教育基础课程
学习客户端下载
青鸟优师
青鸟云课堂
微信 公众号 咨询 顶部 首页
官方新版意见收集

*

官方新版意见收集

提交成功,感谢您的反馈。

我们会认真阅读和考虑每个用户的反馈。