分布式事务

  • 痛点:一笔交易跨多个系统,无法用数据库事务

概念

  • 并没有一种分布式事务的服务或者组件,能帮我们很简单地就解决分布式系统下的数据一致性问题。
  • 在使用分布式事务时,更多的情况是,用分布式事务的理论来指导设计和开发,自行来解决数据一致性问题。
  • 分布式事务也是事务,也需要遵从 ACID 四个特性,但实际情况是,在分布式系统中,因为必须兼顾性能和高可用,所以是不可能完全满足 ACID 的。
  • 分布式事务的解决方案有很多,比如:2PC、3PC、TCC、Saga 和本地消息表等等。这些方法,它的强项和弱项都不一样,适用的场景也不一样。

2PC(两阶段提交)

  • 引入了事务协调者,比如订单系统和促销(优惠券系统)。协调者提供完整的下单服务,在内部再分别调用订单系统和促销系统
  • 二阶段指的是准备阶段和提交阶段。
  • 在准备阶段,协调者分别给订单系统和促销系统发送“准备”命令,订单系统和促销系统把事情都干了,只是不提交。
  • 如果两个系统都准备成功,则协调者再给这两个系统发送“提交”命令,每个系统提交自己的数据库事务,然后给协调者返回“提交成功”响应。
  • 如果任何一步失败,协调者就会给两个系统发送“回滚事务”请求。每个系统在收到请求之后,回滚自己的数据库事务,分布式事务执行失败,两个系统的数据库事务都回滚了。
  • 如果准备阶段成功,进入提交阶段,这个时候就“只有华山一条路”,整个分布式事务只能成功,不能失败
  • 如果发生网络传输失败的情况,需要反复重试,直到提交成功为止。如果这个阶段发生宕机,包括两个数据库宕机或者订单服务、促销服务所在的节点宕机,还是有可能出现订单库完成了提交,但促销库因为宕机自动回滚,导致数据不一致的情况。但是,因为提交的过程非常简单,执行很快,出现这种情况的概率非常小,所以,从实用的角度来说,2PC 这种分布式事务的方法,实际的数据一致性还是非常好的
  • 在实现时,事务协调者可以和订单系统或促销系统单独写到一起,这样对的好处是,参与分布式事务的进程更少,故障点也就更少,稳定性更好;减少了一些远程调用,性能也更好一些
  • 两阶段提交是强一致性的,它可以保证原子性和隔离性。只要 2PC 事务完成,订单库和促销库中的数据一定是一致的状态,也就是我们总说的,要么都成功,要么都失败。适合那些对数据一致性要求比较高的场景。
  • 缺陷在于整个事务的执行过程需要阻塞服务端的线程和数据库的会话,所以,2PC 在并发场景下的性能不会很高。只有在需要强一致、并且并发量不大的场景下,才考虑使用 2PC

本地消息表

  • 更多的情况下,只要保证数据最终一致就可以了。
  • 比如下单后清空购物车,清空购物车的操作不像优惠券那样需要同步完成,只需要在下单后清空即可,可以有一小段延迟。
  • 本地消息表非常适合解决这种分布式最终一致性的问题。
  • 本地消息表的实现思路是这样的,订单服务在收到下单请求后,正常使用订单库的事务去更新订单的数据,并且,在执行这个数据库事务过程中,在本地记录一条消息。这个消息就是一个日志,内容就是“清空购物车”这个操作。
  • 然后,再用一个异步的服务,去读取刚刚记录的清空购物车的本地消息,调用购物车系统的服务清空购物车。购物车清空之后,把本地消息的状态更新成已完成就可以了。异步清空购物车这个过程中,如果操作失败了,可以通过重试来解决。最终,可以保证订单系统和购物车系统它们的数据是一致的
  • 如果看事务的 ACID 四个特性,本地消息表这种方法,它只能满足 D(持久性),A(原子性)C(一致性)、I(隔离性)都比较差,但是,它的优点非常突出。首先,实现简单,在单机事务的基础上稍加改造就可以实现分布式事务,另外,本地消息表的性能非常好,和单机事务的性能几乎没有差别。在这个基础上,还提供了大部分情况下都能接受的“数据最终一致性”的保证,所以,本地消息表是更加实用的分布式事务实现方法
  • 有一个前提条件就是,异步执行的那部分操作,不能有依赖的资源。比如说,我们下单的时候,除了要清空购物车以外,还需要锁定库存。如果把请求都接进来,然后写到本地消息表,异步处理时发现没有库存了,这样就很麻烦了。

3PC(三阶段提交)

  • 在两阶段提交基础上增加了CanCommit阶段,并引入了超时机制。
  • 第一阶段就是CanCommit阶段,事务的协调者向所有参与者询问“你们是否可以完成本次事务?”,如果参与者节点认为自身可以完成事务就返回“YES”,否则“NO”。而在实际的场景中参与者节点会对自身逻辑进行事务尝试,其实说白了就是检查下自身状态的健康性,看有没有能力进行事务操作。
  • 然后是准备阶段,与2PC的准备阶段相比,增加了超时时间,如果有一个参与者超时了,事务协调者就向所有参与者发出中断信号。
  • 提交阶段与2PC相同。
  • 相比较2PC而言,`3PC对于协调者(Coordinator)和参与者(Partcipant)都设置了超时时间,而2PC只有协调者才拥有超时机制。这解决了一个什么问题呢?
  • 这个优化点,主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题

TCC(补偿事务)

  • 其核心思想是:“针对每个操作都要注册一个与其对应的确认和补偿(撤销操作)”。它分为三个操作:
  • Try阶段:主要是对业务系统做检测及资源预留。
  • Confirm阶段:确认执行业务操作。
  • Cancel阶段:取消执行业务操作。
  • TCC事务的处理流程与2PC两阶段提交类似,不过2PC通常都是在跨库的DB层面,而TCC本质上就是一个应用层面的2PC,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能
  • 而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口还必须实现幂等

总结

  • 无论是哪种分布式事务方法,其实都是把一个分布式事务,拆分成多个本地事务。本地事务可以用数据库事务来解决,那分布式事务就专注于解决如何让这些本地事务保持一致的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值