分布式事务

参考原文:两天,我把分布式事务搞完了

2PC和3PC的区别

  1. 3PC在2PC基础上,引入了协调者超时和参与者超时机制。

协调者超时:当协调者接收不到参与者的反馈时即协调者超时,协调者会默认回滚所有参与者。属于悲观型

参与者超时:当协调者挂了后,参与者一直收不到协调者的指令。那么参与者会默认提交事务,因为当前参与者有理由相信所有参与者是同意3PC的第一个阶段canCommit的,所以它大概率是可以提交的。这个参与者超时机制,可以解决当协调者挂了之后,2PC协议的所有参与者一直阻塞的问题,以及顺便解决了2PC的协调者单点问题

总结:

  1. 3PC只是针对2PC的特殊情况做了优化,比如:协调者挂了后,参与者没法推进下去的问题。但是3PC并没有从根本上解决2PC的性能问题,相反由于新增一次网络交互,它的性能更差了。所以,目前并没有3PC的实现。XA实现的是2PC。

Seata的AT、TCC、SAGA模式之间的区别

AT模式

Seata框架的默认模式,属于两阶段提交。但是呢,它在第一个阶段就直接提交了事务,不让数据库占用事务资源。直接提交了,万一其他分支事务有一个或多个执行失败,想回滚咋办呢?这个就是AT模式牛逼的地方,它会创建undo_log表,在执行事务提交的sql时,seata框架会默认改造sql,得到执行前数据的快照,然后执行后再次得到数据快照。用这两个快照,构造一个undo log保存在undo_log表。这个表,一定是要和执行事务的表在一个数据库,属于一个本地事务,保证它们的原子性。

回滚的数据(叫补偿更合适)已经保存好了,就算当前事务提交了,我也能明明白白的回滚数据。但是还有个问题,当前分支事务提交了,但是其他分支事务还在执行,相当于整个分布式事务还在进行中。那么又来一个分布式事务,之前执行完成的分支事务是不是就可以为这个分布式事务服务了,但是前面的分布式事务还在执行中,它还不知道最终执行是commit还是rollback呢。这个时候,那个提交的分支事务就不能为其他任何分布式事务服务,所以还需要一个全局lock表,用来阻塞并发的分布式事务。把分布式事务从并发变成串行执行。注意:这个串行可不是表级别,而是行级别,lock表只是锁住行。如果其他分布式事务想要操作该表的其他行数据,能够拿到全局锁,可以并发执行。

TCC模式

TCC 分为指代 Try、Confirm、Cancel,是一种业务层面或者是应用层的两阶段提交。所以,在Try阶段数据库层面的事务就已经提交了,所以每个阶段都无需占用数据库资源。

Try阶段需要引入临时状态,比如:冻结状态,预添加等等字段,用来保存try阶段执行的结果。这个中间态的引入,对业务的数据库设计有非常大的侵入。同时,每个服务都需要改造成Try、Confirm、Cancel三个阶段的服务,对代码侵入也很大。

比如有一个扣款服务,我需要写 Try 方法,用来冻结扣款资金,还需要一个 Confirm 方法来执行真正的扣款,最后还需要提供 Cancel 来进行冻结操作的回滚,对应的一个事务的所有服务都需要提供这三个方法。

TCC 的注意点

幂等问题,因为网络调用无法保证请求一定能到达,所以都会有重调机制,因此对于 Try、Confirm、Cancel 三个方法都需要幂等实现,避免重复执行产生错误。

空回滚问题,指的是 Try 方法由于网络问题没收到超时了,此时事务管理器就会发出 Cancel 命令,那么需要支持 Cancel 在未执行 Try 的情况下能正常的 Cancel。

悬挂问题,这个问题也是指 Try 方法由于网络阻塞超时触发了事务管理器发出了 Cancel 命令,但是执行了 Cancel 命令之后 Try 请求到了,你说气不气。
这都 Cancel 了你来个 Try,对于事务管理器来说这时候事务已经是结束了的,这冻结操作就被“悬挂”了,所以空回滚之后还得记录一下,防止 Try 的再调用。

Saga 模式

参考原文:Saga模式

这个 Saga 是 Seata 提供的长事务解决方案,适用于业务流程多且长的情况下,这种情况如果要实现一般的 TCC 啥的可能得嵌套多个事务了。

Saga的组成
每个Saga由一系列sub-transaction Ti 组成
每个Ti 都有对应的补偿动作Ci,补偿动作用于撤销Ti造成的结果
可以看到,和TCC相比,Saga没有“预留”动作,它的Ti就是直接提交到库。

Saga的执行顺序有两种:
执行成功:T1, T2, T3, ..., Tn
执行失败:T1, T2, ..., Tj, Cj,..., C2, C1,其中0 < j < n

Saga定义了两种恢复策略:

  • backward recovery,向后恢复,补偿所有已完成的事务,如果任一子事务失败。即上面提到的第二种执行顺序,其中j是发生错误的sub-transaction,这种做法的效果是撤销掉之前所有成功的sub-transation,使得整个Saga的执行结果撤销。
  • forward recovery,向前恢复,重试失败的事务,假设每个子事务最终都会成功。适用于必须要成功的场景,执行顺序是类似于这样的:T1, T2, ..., Tj(失败), Tj(重试),..., Tn,其中j是发生错误的sub-transaction。该情况下不需要Ci。

显然,向前恢复没有必要提供补偿事务,如果你的业务中,子事务(最终)总会成功,或补偿事务难以定义或不可能,向前恢复更符合你的需求。

理论上补偿事务永不失败,然而,在分布式世界中,服务器可能会宕机,网络可能会失败,甚至数据中心也可能会停电。在这种情况下我们能做些什么? 最后的手段是提供回退措施,比如人工干预。

对于ACID的保证:
Saga对于ACID的保证和TCC一样:

  • 原子性(Atomicity):不支持
  • 一致性(Consistency),在某个时间点,会出现A库和B库的数据违反一致性要求的情况,但是最终是一致的。
  • 隔离性(Isolation):不支持,A事务能够读到B事务部分提交的结果。
    持久性(Durability):和本地事务一样,只要commit则数据被持久。
    Saga不提供ACID保证,因为原子性和隔离性不能得到满足。原论文描述如下:
    full atomicity is not provided. That is, sagas may view the partial results of other sagas

通过saga log,saga可以保证一致性和持久性。

和TCC对比

Saga相比TCC的缺点是缺少预留动作,导致补偿动作的实现比较麻烦:Ti就是commit,比如一个业务是发送邮件,在TCC模式下,先保存草稿(Try)再发送(Confirm),撤销的话直接删除草稿(Cancel)就行了。而Saga则就直接发送邮件了(Ti),如果要撤销则得再发送一份邮件说明撤销(Ci),实现起来有一些麻烦。

如果把上面的发邮件的例子换成:A服务在完成Ti后立即发送Event到ESB(企业服务总线,可以认为是一个消息中间件),下游服务监听到这个Event做自己的一些工作然后再发送Event到ESB,如果A服务执行补偿动作Ci,那么整个补偿动作的层级就很深。

不过没有预留动作也可以认为是优点:

  • 有些业务很简单,套用TCC需要修改原来的业务逻辑,而Saga只需要添加一个补偿动作就行了。
  • TCC最少通信次数为2n,而Saga为n(n=sub-transaction的数量)。
  • 有些第三方服务没有Try接口,TCC模式实现起来就比较tricky了,而Saga则很简单。
  • 没有预留动作就意味着不必担心资源释放的问题,异常处理起来也更简单(请对比Saga的恢复策略和TCC的异常处理)。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342