架构师之路 | 分布式事务的缘起缘落

Posted 无刀流

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了架构师之路 | 分布式事务的缘起缘落相关的知识,希望对你有一定的参考价值。

分布式事务在互联网技术领域算的上高阶的技术了,好比武功中的易筋经。掌握此技,左可出山门闯江湖,右可开山门收弟子。本文带大家浅入深出揭开分布式事务的神秘面纱。


01

事务是什么?

在生活中,事务是指我们将要做的,或正在做的,又或是已经做完了的一件事。比如我要吃小炒肉,我正在做鸡米花,我刚刚吃了顿霸王餐。讲的是一件事,这件事可大可小,事情的发生状态也不确定,可以是做完了,也可以没做完,非常宽泛的一个概念


而在编程领域,说到事务基本就特指数据库事务


休息一下,老夫做的菜,请欣赏


02

数据库事务

说到我了,数据库事务。是指一次数据库事务操作指令,可能包含了对数据库的一条或多条变更操作,要求这些操作,要么都做成功了,要么一个也不要成功。

        

展开分析下,比如我们支付宝花了一笔钱,简化这个场景,产生一条支出记录,同时账户余额应该也要减少,就拿这种情况分析下。

分析


A. 如果产生了一条支出记录,但是余额没有扣减。那么相当于我买到了东西,钱没有减少,所以,支付宝不干了

B. 如果没有产生支出记录,但是余额扣减了。那么相当于我花了钱,确没有买到东西,这样,我不干了

所以,对于一个数据库事务内的一系列操作,要么都做成功了,要么一个也不要做成功。这就是我们讲的数据库事务产生的需求背景


类似需求数不胜数,积分流水和积分账户要同时变更;商品份额和商品售卖记录也是,不然会产生超卖少买;转账时两个账户,一个增加的同时另一个要减少等等。所以,数据库支持事务是个历史选择的结果。

        

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 架构师之路 | 分布式事务的缘起缘落         

03

数据库事务 -- A I C D 特性

根据数据库事务要么都做,要么都不做的需求,会让数据库有AICD四大特性


A:原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。


I:隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

        比如我去花钱买包子的一个操作,不能去扣别人的钱,同时别人的钱只能再别人的花钱事务里面扣除。我们各自的事务操作是互相隔离的。


C:一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

        事务的执行结果是要满足预期的。比如支出记录10元,那么账户余额扣减也是10元。这里的一致,是满足数据在事务操作后符合预期变化的一致。


D:持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

        比如我支出10元,支出操作的过程中发现余额是扣减了的。过一会去查询,发现余额没有扣减。这说明这个数据变更没有持久化到存储中,之前只是在内存中进行了变更,这是不可以的。一但一个事务执行成功了,就要持久化。口头答应的,要写成文书嘛,对吧。


04

分布式事务产生的历史背景

传统数据库事务都是单机环境下发生的,数据库本身就支持了,所以我们在coding时只需很简单就可以实现事务功能。加一个注解,或者编程式事务,或者事务模板,总之都是很easy就可以实现事务功能。


随着互联网的兴起,传统单机架构模式已经支持不了海量高并发的业务需求。单机的性能瓶颈,单点问题,都满足不了互联网24小时不间断高可用服务。这时分布式架构应运而生。


分布式架构


A. 就应用层面,做了服务化拆分,把原来的单应用系统,按照领域来划分成多个独立子系统,系统间通过RPC调用、缓存服务等来实现通信。同时,每个应用部署多台,防止挂掉一台服务器会导致服务的不可用

B. 就数据库层面,按照不同领域垂直拆分成服务不同业务的数据库服务器,同时为了应对某一些单表海量数据,按照水平维度进行多库多表的拆分。单机环境下的数据库事务被打破。

C. 就中间件层面,引入消息服务器、RPC、文件服务器、缓存服务器、负载均衡服务器、服务治理工具等来实现分布式架构下的统一管理和维护。


画了一张简单的分布式架构图,便于大家理解分布式环境


在分布式架构下,原来单机数据库事务可以解决的问题,现在已经解决不了了。


比如,原来购买一件商品的流程,涉及创建交易订单,扣减份额,支付,添加物流信息,更改订单状态等操作,都是在一个数据库事务内完成,或成功或失败。现在创建订单在交易系统里,扣份额在商品系统里,支付在支付系统里等,都在独立的系统里,如何协调这些系统达到统一的状态,就是非常困难的问题。


再举一个常见的例子,跨行转账也是一个分布式事务,从A银行转账到B银行,A银行钱扣了,B银行有没有加成功,又或者A银行没有扣钱,B银行确显示转账成功。这些都是分布式环境下所带来的事务一致性问题。


这时,就需要分布式事务来解决分布式环境下一致性的问题了


05

分布式事务要解决哪些问题

CAP原则

讲到分布式事务,绕不开的一个原则--CAP原则。指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。


CAP原则


一致性(C):在分布式系统中各个系统的数据,在任何时刻都达到预期的状态。比如订单是已完成状态,支付是支付中状态,就没有达到预期状态。订单是完成状态,那么支付也应该是完成的状态,这是才达到了一致性,一致性=客户预期。

可用性(A):分布式系统任何时候都是可以查询的使用的,不能阻塞卡死

分区容错性(P):分区问题就是网络环境是不稳定的,一个请求过去,可能就超时了,可能就出错了,或者网络重发,各种情况都会发生。如果等待网络恢复,那么这个时候系统就是不可用的。所以分区问题发生时,系统要是可用的,所以要支持分区容错。

CAP原则的核心问题是,CAP三者不能同时满足,而这三个又都是我们要满足的,这里就有个矛盾点了。


所以,分布式事务要解决的核心问题就是CAP问题。所有的分布式事务解决方案都是围绕CAP原则,从不同场景下,折中CAP,来解决分布式事务的问题。


完全满足CAP不现实的,系统不可能在任何网络环境下,都保持时刻可用,还能第一时间达到数据的一致性。


随便举例子,一个请求过去了,网络断掉了,怎么知道对方是什么状态,对方可能没有接到请求,可能请求处理失败了,可以一直处于处理中,可能请求处理成功了,也可能处理完再返回结果时网络断掉了,各种情况都有可能。调用方也就不能第一时间达到一致性。所以,C 这个条件,时刻满足一致性是不可能的。


既然完全满足CAP是不现实的,根据实践经验,可以总结适合我们去处理分布式事务的原则。


协调者 + 最终一致性 + 中间状态服务 + 软可用 + 幂等


可行分布式原则


协调者:在分布式环境中负责协调各个子系统达到最终一致性的系统

最终一致性:各个子系统在协调者的协调下,经过一段时间,最终满足用户预期的状态

中间服务状态:分布式各个子系统,在没有到达最终状态前,对于不确定的结果,以中间终态--处理中,来进行过度

软可用:支持任何时刻的可查询,如果不是终态,返回服务中间状态

幂等性:所有系统支持幂等性调用,参考:


06

DDTX-分布式事务解决方案


分布式事务解决方案有很多,每种解决方案都适应一种或几种应用场景,没有完美的一种解决方案可以解决所有的分布式事务问题。


TUS:只有一种最终状态,幂等重试达到最终一致性(补偿事务),TUS = try until         success(自主开发的DDTX里面的事务类型)

2PC:两阶段提交,单一协调者模式

3PC:三阶段提交,解决单一协调者问题,产生的模式

TCC:有两种最终状态,幂等重试达到最终一致性(补偿事务)

MQ消息:异步消息事务(补偿事务)

本地消息表:记录每步执行结果,重试(补偿事务)



分布式事务前世今生,缘起缘落,至此,本文尘埃落定!


有缘人,感谢您的支持


以上是关于架构师之路 | 分布式事务的缘起缘落的主要内容,如果未能解决你的问题,请参考以下文章

当年,我的架构师之路差点完蛋,幸亏了它

当年,我的架构师之路差点完蛋,幸亏了它

几年的架构师生涯,掏心掏肺分享在分布式“刚性事务和柔性事务”中思维逻辑!

Java架构师,不懂这些分布式事务,就别想着跳槽!

聊一下分布式事务

用MQ消息实现分布式事务关键点