分布式系统的数据一致性方案

1、在出现一致性问题时如果系统的并发或不一致情况较少,可以先使用重试来解决
a、同步重试
b、异步重试
c、入库,定时任务重试

2、分布式事务
基于数据库 XA 协议的 2PC、3PC,基于业务层的TCC,基于消息队列+消息表的最终一致性方案,基于阿里的分布式事务框架SeaTa的AT模式方案。

基于XA协议的2pc和3pc,是依靠数据库层面解决分布式事务的问题,这种方案是单应用连接多库,不适用于现在的微服务架构,适用于单应用多库的场景。

TCC 是在业务层编写代码实现的两阶段提交。TCC 分别指 Try、Confirm、Cancel ,一个业务操作要对应的写这三个方法。
例如额度占用,try阶段是冻结额度,confirm是真正的占用额度,cancel是解冻冻结额度。是一种补偿性事务。这种方式对系统侵入性大,且增加了业务复杂度和开发量。

MQ有好几种方式:
第一种:MQ+本地消息表:在写入数据库的同时,写入一张本地消息表。这张表,用来记录MQ消息处理的状态,可以有发送中和已完成两种状态。由于消息表和正常的业务表在一个DB中,所以可以达成本地事务,确保同时完成。存在一个定时任务,持续扫描本地消息表中,状态为发送中的消息(注意延时),并再次把这些消息发送到MQ。
这种方式与业务耦合性强,但是容易实现。
第二种:可靠消息事务:与本地消息表类似,但是消息表是存与MQ中的,rocketMQ有半消息机制。发起方先给MQ发送一个半消息,然后执行本地事务,执行完之后给MQ发提交或者回滚,提交的话MQ会将半消息设置为可投递的状态,回滚的话则会删除半消息。
若被动方多次执行本地事务失败,则使用定时任务进行补偿。
发起方需要提供回查事务状态的方法。
优点:消息表与业务系统松耦合,吞吐量会增大。缺点:需要提供事务状态回查接口。

SEATA框架
每个应用系统需要创建undo_log表,将业务数据在更新前后的数据镜像组织成回滚日志,备份在 UNDO_LOG 表中,以便业务异常能随时回滚。
file.conf 文件用于配置持久化事务日志的模式,目前提供 file、db、redis 三种方式。
在选择 db 方式后,需要在对应数据库创建 globalTable(持久化全局事务)、branchTable(持久化各提交分支的事务)、 lockTable(持久化各分支锁定资源事务)三张表。
registry.conf 文件设置 注册中心 和 配置中心
@GlobalTransactional 注解开启一个全局事务
分为两个阶段:第一阶段:把业务数据在更新前后的数据镜像组织成回滚日志,将业务数据的更新和回滚日志在同一个本地事务中提交,分别插入到业务表和 UNDO_LOG 表中。在本地事务提交前,各分支事务需向 全局事务协调者 TC 注册分支 ( Branch Id) ,为要修改的记录申请 全局锁 ,要为这条数据加锁,利用 SELECT FOR UPDATE 语句。而如果一直拿不到锁那就需要回滚本地事务。TM 开启事务后会生成全局唯一的 XID,会在各个调用的服务间进行传递。有了这样的机制,本地事务分支(Branch Transaction)便可以在全局事务的第一阶段提交,并马上释放本地事务锁定的资源。相比于传统的 XA 事务在第二阶段释放资源,Seata 降低了锁范围提高效率,即使第二阶段发生异常需要回滚,也可以快速 从UNDO_LOG 表中找到对应回滚数据并反解析成 SQL 来达到回滚补偿。最后本地事务提交,业务数据的更新和前面生成的 UNDO LOG 数据一并提交,并将本地事务提交的结果上报给全局事务协调者 TC
第二阶段:
根据各分支的决议做提交或回滚
如果决议是全局提交,此时各分支事务已提交并成功,这时 全局事务协调者(TC) 会向分支发送第二阶段的请求。收到 TC 的分支提交请求,该请求会被放入一个异步任务队列中,并马上返回提交成功结果给 TC。异步队列中会异步和批量地根据 Branch ID 查找并删除相应 UNDO LOG 回滚记录。如果决议是全局回滚,过程比全局提交麻烦一点,RM 服务方收到 TC 全局协调者发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。这里删除回滚日志记录操作,一定是在本地业务事务执行之后
AT模式

a、2PC-XA协议(两阶段提交)
在这里插入图片描述
分两个阶段:准备阶段(投票反馈阶段)和 提交阶段(执行阶段)
准备阶段参与者在本地执行事务,在本地写redo\undo log,但不提交,有点万事俱备只欠东风的态势。提交阶段由协调者发出

缺点:
commit丢失/超时导致数据不一致、性能低(同步阻塞)、在任意阶段协调者发生故障都会导致分布式事务无法进行

b、3PC(三阶段提交)
3PC通过在参与者加入超时机制解决2PC中的协调者单点带来的事务无法进行的问题,但是性能和一致性仍没有解决。
三阶段即canCommit、preCommit、doCommit。三阶段提交解决了资源阻塞问题,但仍然存在单点故障和数据不一致的问题

二阶段和三阶段都不适合微服务下的事务管理,原因有三个:

  • 由于微服务间无法直接进行数据访问,微服务间互相调用通常通过RPC(Dubbo)或Http API(Spring Cloud)进行,所以已经无法使用TM统一管理微服务的RM。
  • 不同的微服务使用的数据源类型可能完全不同,如果微服务使用了NoSQL之类不支持事务的数据库,则事务根本无从谈起。
  • 即使微服务使用的数据源都支持事务,那么如果使用一个大事务将许多微服务的事务管理起来,这个大事务维持的时间,将比本地事务长几个数量级。如此长时间的事务及跨服务的事务,将为产生很多锁及数据不可用,严重影响系统性能。

微服务下的方案
a、同步事件通知
b、异步事件通知(本地事件通知、外部事件通知)
c、最大努力通知
d、业务补偿模式
偿模式的上游服务依赖于下游服务的运行结果,而事件通知模式上游服务不依赖于下游服务的运行结果
e、TCC模式
TCC模式是一种优化了的业务补偿模式,它可以做到完全补偿,既进行补偿后不留下补偿的纪录,就好像什么事情都没有发生过一样。同时,TCC的软状态时间很短,原因是因为TCC是一种两阶段型模式,只有在所有的服务的第一阶段(try)都成功的时候才进行第二阶段确认(Confirm)操作,否则进行补偿(Cancel)操作,而在try阶段是不会进行真正的业务处理的。
最终一致性
在这里插入图片描述

核心分为2个阶段:1.Try 2.Confirm or Cancel。先尝试(Try)操作数据,如果都成功则全部确认(Confirm)该修改,如果有任意一个尝试失败,则全部取消(Cancel)。简单点说就是增加了中间态和可回改能力。
通过重试机制保障Confirm和Cancel一定能成功。TCC解决了性能问题,但是业务系统想要实现对业务代码的侵入性很大。

在这里插入图片描述

3、兜底核对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值