分布式事务基础理论解析

一、概述

1.1 定义

为了解决java 多个节点之间数据一致性问题。产生的核心原因是:资源存储的分布性。比如多个数据库,或者Mysql和Redis的数据一致性等。

1.2 产生场景

  1. 跨JVM进程产生分布式事务。即服务A和服务B分别有对应的数据库
  2. 跨数据库实例产生分布式事务。即单体应用系统访问不同的数据库
  3. 多服务访问同一数据库。

1.3 基础理论模型

1.3.1 CAP理论

Consistence(一致性): 数据在多个副本中要保持强一致性。一般指的是写操作后的读操作可以读取到最新的
数据状态
具体实现:
1. 写入主数据库后将数据同步到从数据库;
2. 写入主数据库后, 在向从数据库同步期间要将数据库锁定,待同步完成后再释放锁,以免在数据库同步期间
读取到旧数据
特点:
1. 由于数据库存在同步过程,写操作的响应会存在一定的延迟;
2. 为了保证数据的强一致性,会锁住数据库资源一段时间
3. 如果请求数据同步失败的节点则会返回错误信息,一定不会返回旧数据


Availability(可用性): 系统对外提供的服务必须一致处于可用状态,在任何故障下,客户端都能在合理时间
内获取到服务端非错误响应, 即不会出现响应超时或响应错误
具体实现:
1. 写入数据库后将数据同步到从数据库;
2. 由于要保证系统可用性,不可将数据库资源进行锁定
3. 即使数据还没有同步过来,也需要返回一个数据,那怕是旧数据
特点:所有请求都有响应,且不会出现响应超时或响应错误

Partition tolerance(分区容错性): 在分布式系统中遇到任何网络分区故障,系统仍然能够对外提供服务
具体实现:添加从数据库节点
特点:分区容忍性是分布式系统具备的基本能力

CAP组合方式:
1. CP方式: zookeeper就是追求强一致性。例如: 跨行转账
2. AP方式: 用户可以接受查询到的数据在一定时间内不是最新的即可. 例如: 订单退款

1.3.2 Base理论

是对AP的一个扩展。核心思想通过牺牲数据的强一致性来获得高可用性。有如下三个特性:
1. Basically Available(基本可用): 分布式系统在出现故障时,允许损失一部分功能的可用性,保证核心
功能的可用性。例如: 电商网站中退款服务出现问题,但商品可以正常浏览
2. Soft stata(软状态): 允许系统中的数据存在中间状态,也就是允许系统中不同节点的数据副本之间的同步
存在延时。例如: 订单的支付中, 数据同步中等状态
3. Eventually Consistent(最终一致性): 中间状态的数据经过一定时间后,会达到最终数据的一致性。
例如: 订单的支付中 最终变为 支付成功或支付失败

二、解决方案

2.1 基于CP的分布式事务解决机制方案

2.1.1 XA方案

基本采用java 2PC理论模型实现,分为准备Prepare阶段提交Commit阶段
准备阶段:TM(事务管理器)给每个RM(资源管理器)发送Prepare消息,每个RM执行本地事务,并写本地的Undo日志和Redo日志,但不提交,此时需要锁住资源;
提交阶段:TM若收到RM发送的执行失败或超时信息,则给每个RM发送回滚信息;否则发送提交信息,并释放锁。

优缺点:

优点:

  1. 保证了数据的强一致性

缺点:

  1. 同步阻塞。所有的事务都处于同步阻塞状态,占用的锁资源会一致被锁定;
  2. 过于保守。只要有一个节点出现问题,都会回滚;
  3. TM的单点故障。若处于Commit阶段,那么RM将一直处于锁定状态;
  4. 数据不一致问题【脑裂】。若TM向所有RM发送完消息后,中间由于网络问题,部分RM没有收到Commit消息,会导致数据不一致问题;
  5. 效率低下。性能与本地事务相差10倍。

2.1.2 三阶段提交协议

是二阶段协议的优化版本, 利用超时机制解决了同步阻塞问题。具体步骤为:

  1. CanCommit(询问阶段): 事务协调者向参与者发送事务执行请求, 询问是否可以完成指令,参与者只需回答是或不是即可,不需要执行真正的事务操作,这个阶段会有超时中止机制。
  2. Prepare(准备阶段):与两阶段一样,但增加了超时提交机制,一旦出现超时情况, 会继续提交事务。默认情况下认为成功的可能性很大
  3. DoCommit(提交或回滚阶段):与两阶段一样。

2.2 基于Base理论的分布式事务解决方案

2.2.1 TCC事务补偿

将一个完整业务拆分为一下三个阶段:

  1. Try阶段:做业务检查和资源预留。主要完成业务逻辑
  2. Confirm阶段:Try阶段所有分支事务执行成功后开始执行Confirm。若Confirm执行失败,需要引入重试机制或人工处理
  3. Cancel阶段:在业务执行错误需要回滚下执行分支事务的业务取消。若Cancel执行失败,需要引入重试机制或人工处理

主要存在以下三种问题:
空回滚:在没有调用Try情况下,直接调用Cancel方法,会产生空回滚。产生原因: 一个分支事务出现宕机或网络异常,导致没有执行Try阶段,分支事务调用记录为失败。当故障恢复后,会调用Cancel方法,形成空回滚。解决思路: 利用分支事务记录表,Cancel方法中判断Try阶段是否有执行记录
幂等:二阶段Confirm或Cancel提交重试机制会引发数据不一致,因此,需要保证二阶段Confirm或Cancel的幂等型,这也被称为最终一致性事务的原因
悬挂:二阶段Concel比Try阶段先执行。执行Try方时通过RPC调用,RPC调用产生阻塞,导致事务超时回滚执行Cancel,但过一段时间后RPC请求达到执行Try方法。解决方案: 执行Try方法时,通过事务记录表判断Cancel方法是否已经执行。

2.2.2 基于可靠性消息的最终一致性

核心: 指的是事务发起方完成本地事务并发出一条消息,事务接收方(消息消费者) 一定能够接受消息并处理事务成功
主要面临以下三个问题:

  1. 本地事务和消息发送的原子性问题;
  2. 事务方接受消息的可靠性
  3. 消息重复消费的问题
2.2.2.1 基于本地消息表

核心: 利用本地事务保证业务数据和消息的一致性
基本原则:

  1. 采用Base原理,保证事务的最终一致性;
  2. 在一致性方面,允许一段时间内的不一致,但最终一致
  3. 在实际业务开发中,要根据实际业务来决定是否采用

主要流程:

  1. 基于本地消息表的方案,将本事务外的操作,记录在消息表中;
  2. 使用定时任务轮询本地消息表,将将未执行的消息发送给其他事务操作接口;
  3. 若操作成功,则定时任务会修改消息状态;否则,会重试
  4. 增加重试机制,设置重试次数,一旦重试次数超过阈值,则需人工介入处理。
2.2.2.2 基于MQ的最终一致性
1. producer向broker发送half消息,consumer不消费; -- 用于确认broker是正常的;
2. 收到broker返回的响应后,执行本地事务; 
3. 若本地事务执行成功, producer将本地事务执行成功的消息发送给broker,此事允许consumer消费消息
4. 若producer出现网络故障\宕机\网络超时等, broker未收到二次确认消息,则broker发送请求给producer进行消息回查。根据消息回查结果进行事务提交或事务回滚操作
2.2.2.3 最大努力通知型事务

核心: 发起通知方通过一定机制最大努力将业务处理结果通知到接收方。举例如下:充值,涉及账户系统(接受通知方)和充值系统(发送通知方)。

1. 账户系统记录充值信息,并将充值状态设为充值中;
2. 调用支付充值系统,充值系统完成充值后,向账户系统发送充值结果;
3. 若发送失败,则重复发送。发送一定次数后不发送数据;-- 消息重复通知机制
4. 若发送成功,接受通知方收到消息,将充值状态修改为充值成功,并返回一个处理状态给发送通知方。
5. 若接受通知方没有收到消息,则调用发送通知方提供的接口来查询充值情况。 -- 消息校对机制

可以发现,不需要任何的数据回滚。因为充值信息并不影响用户的金钱,只是增加了一条充值失败的信息,是可以接受的。

三、分布式事务对比

1. 2PC:需要阻塞,适用于强一致性且并发量低的系统。例如跨行转账;
2. TCC事务:相比于2PC2PC通常是在跨库层面,TCC在应用层面,因此,TCC可以在应用层自己定义操作数据的粒度,降低锁冲突,提高吞吐量。但对代码的侵入性比较强,一方面每个事务分支都需要实现try\confirm\concel操作,同时根据不同的故障类型提供不同的回滚策略。
3. 可靠性消息:适合执行【周期长且实时性不高】的场景。引入消息机制后,同步的事务变成异步操作,并实现了两个服务的解耦。
4. 最大努力通知型:适用于一些【最终一致性且时间敏感度低】的业务,可用于外部系统。例如:银行通知、支持结果通知

在这里插入图片描述

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桃花猿

客官,赏点打酒钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值