背景
四月初,去面试了本市的一家之前在做办公室无人货架的公司,虽然他们现在在面临着转型,但是对于我这种想从传统企业往互联网行业走的孩子来说,还是比较有吸引力的。
在面试过程中就提到了分布式事务问题。我又一次在没有好好整理的问题上吃了亏,记录一下,还是长记性 !!!
先看面试过程
面试官先是在纸上先画了这样一张图:
让我看这张图按照上面的流程走,有没有什么问题?面试官并没有直接说出来这里面会有分布式事务的问题,而是让我来告诉他,这就是面试套路呀。
我回答了这中间可能存在分布式事务的问题,当步骤 2 在调用 B 系统时,可能存在B 系统处理完成后,在响应的时候超时,导致 A 系统误认为 B 处理失败了,从而导致A 系统回滚,跟 B 系统存在数据不一致的情况。
ok ,我回答到这里,应该回答了面试官的第一层意思,至少我有这种意识,他点了点头。
接着,他继续问:“那你有什么好的解决方式吗?”
此时我脑子里面只有两阶段提交的大概流程图的印象,然后巴卡巴拉的跟他说了一番,什么中间来个协调者呀,先预提交什么的,如果有失败,就 rollback,如果 ok,再真正的提交事务,就是网上这些大神们说的这些理论。
然后面试官就继续问:那A 在调用 B 的这条线断了,你们代码具体是怎么处理的呢 ?怎么来做到 rollback 的呢 ?说说你代码怎么写的。
此时,我懵了。
最后结果,大家肯定也能猜到,凉凉。
什么是事务
这里我们说的事务一般是指 数据库事务,简称 事务,是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。维基百科中这么说的。
用转账的例子来说,A 账户要给 B 账户转 100块,这中间至少包含了两个操作:
- A 账户 减 100 块
- B 账户 加 100 块
在支持事务的数据库管理系统来说,就是得确保上面两个操作(整个“事务”)都能完成,不能存在,A 的100块扣了,然后B 的账户又没加上去的情况。
数据库事务包含了四个特性,分别是:
- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。对于转账来说,A账户扣钱,B 账户加钱,要么同时成功,要么同时失败。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。其他账户在转账的时候,不能影响到上面的 A 跟 B 之前的交易。
- 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。
什么是分布式事务
我们知道,上面的转账 我们是在一个数据库中的事务操作。我们可以使用一些框架 比如 Spring 的事务管理器来给我们统一搞定。
但是如果我们系统中出现垮库操作,比如一个操作中,我需要操作多个库,或者说这个操作会垮应用之前的调用,那么Spring 的事务管理机制就对这种场景没有办法了。
就像上面面试题中出现的问题一样,在系统 A 的步骤 2 在远程调用 B 的时候,由于网络超时,导致B 没有正常响应,但是A 这边调用失败,进行了回滚,而 B 又提交了事务。此时就可能会导致数据不一致的情况,参生分布式事务的问题。
分布式事务的存在,就是解决数据不一致的情况。
为什么我们要保证一致性
CAP 理论
分布式系统中有这么一个广为流传的理论:CAP 定理
这个定理呀,起源于加州大学柏克莱分校(University of California, Berkeley)的计算机科学家埃里克·布鲁尔在 2000年的分布式计算原理研讨会(PODC)上提出的一个猜想。后来在2002年,麻省理工学院(MIT)的赛斯·吉尔伯特和南希·林奇发表了布鲁尔猜想的证明,使之成为一个定理。【摘自维基百科】
他说呀,对于一个分布式计算系统来说,不可能同时满足以下三点:
- 一致性(Consistency)
- 可用性(Availability)
- 分区容错性(Partition tolerance)
而一个分布式系统最多只能满足其中的两项。
那么,上面的三点分别是什么玩意儿?为什么又只能同时满足两项呢?