一、什么是分布式事务
在早期的单体架构时期,所有的数据操作都在同一个数据库里面进行,比如:A给B转100块钱,A的账户余额-100,B的账户余额+100,这两个操作放在同一个事务里面即可,由数据库来保证事务的原子性、一致性、持久性、隔离性。但是随着业务量、数据量的加大,放在一个数据库里面很难支撑,所以需要对数据库按照业务来进行拆分,比如积分兑换商品下单操作涉及如下操作:
1.用户积分扣减(积分数据库)
2.商品库存扣减(商品库存数据库)
3.订单创建(订单数据库)
这三个操作在三个不同的数据库里面进行,这样就导致传统的数据库事务不能保证这三个操作的原子性了,于是就需要分布式事务来处理这类问题。
二、常见的分布式事务解决方案有哪些?
1.两阶段提交协议
由事务协调者和事务参与者构成,把分布式事务分成两个阶段:
一阶段:事务协调者调用各个事务参与者进行资源准备,这个阶段各个参与者会执行本地事务,进入prepare阶段,但是本地事务不会提交;
二阶段:事务协调者根据调用结果,来决定第二阶段是执行commit还是rollback操作,如果一阶段中只要有一个参与者返回失败,就执行rollback操作,只有当所有参与者都返回成功时才执行commit操作。
两阶段协议有什么缺点呢?
(1)性能较差:因为会阻塞性的锁定数据库资源,如果其中某个参与者执行很慢,其它的参与者也需要等着;
(2)可能导致数据不一致:如果参与者和协调者都挂了;
(3)可靠性较差:协调者存在单点故障的问题,如果出现故障,参与者就会一直处于阻塞状态。
2.三阶段提交协议
在两阶段提交的基础上多加了一个阶段:先问一下每个参与者是否可以提交事务,如果可以就会进入第二阶段,这个阶段会锁定数据库资源,后面两个阶段在两阶段协议的基础上增加了参与者如果等待协调者超时,可以直接提交事务的处理。
三阶段的优点:如果协调者出现问题,参与者不会一直阻塞;
缺点:没有解决数据一致性的问题,在第三阶段如果协调者出现问题时可能导致数据不一致。
3.TCC
一阶段为try,二阶段为confirm或者cancel;2PC和3PC都是数据库层面的,而 TCC 是业务层面的分布式事务,就像我前面说的分布式事务不仅仅包括数据库的操作,还包括发送短信等,这时候 TCC 就派上用场了!
TCC属于补偿型事务,一阶段会先预留资源,如果成功则确认,否则补偿退回就行。
TCC最大的缺点就是需要自己实现try、confirm、cancel三个方法,对业务侵入性较大,实现起来也会比较麻烦。使用TCC要注意一下几个问题:
(1)空回滚:如果try还没执行,cancel方法就执行了,这个时候没有资源可以补偿,需要允许这种case发生,直接发挥成功就好;
(2)防悬挂:上面说到了允许空回滚的发生,那try方法可能后面又会执行,如果不处理,会导致资源会锁住了,并且不会释放;
(3)幂等:confirm、cancel方法需要考虑网络等问题导致的执行失败,需要重试的问题。
4.本地事务表
缺点:需要增加本地消息表,对业务侵入较大。
5.事务性消息
不是所有的消息中间件都支持,目前主流的只有rocketMq支持,同时对业务也有一定的侵入。与TCC相比,二者使用的场景不太一样,TCC一阶段就会锁定所有资源,如果失败了解除资源锁定就好了,但是事务性消息并没有锁定所有资源,生产者发送成功了,通过重试的方式保证消费者也能消费成功,如果消费不成功需要告警然后人工介入处理。
文章评论