分布式事务


title: 分布式事务
date: 2021-07-24 16:38:01


1 概述

  • CAP原理

  • ACID原理与BASE原理

  • 基于XA协议的两阶段提交

  • 事务补偿机制

  • 基于本地消息表的最终一致方案

  • 基于MQ消息队列的最终一致方案

2 CAP原理

2.1 简介

在分布式系统中,我们经常听到CAP原理这个词,它是什么意思呢?其实和C、A、P这3个字母有关,C、A、P分别是这3个词的首字母。下面我们就看一下这3个词分别是什么意思?

  • C - Consistent ,一致性。具体是指,操作成功以后,所有的节点,在同一时间,看到的数据都是完全一致的。所以,一致性,说的就是数据一致性。
  • A - Availability ,可用性。指服务一致可用,在规定的时间内完成响应。
  • P - Partition tolerance ,分区容错性。指分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供服务。

CAP原理指出,这3个指标不能同时满足,最多只能满足其中的两个。

2.2 详解

我们之所以使用分布式系统,就是为了在某个节点不可用的情况下,整个服务对外还是可用的,这正是满足P(分区容错性)。如果我们的服务不满足P(分区容错性),那么我们的系统也就不是分布式系统了,所以,在分布式系统中,P(分布容错性)总是成立的。那么,A(可用性)和C(一致性)能不能同时满足呢?我们看一下下面的图例。

A和B是两个数据节点,A向B同步数据,并且作为一个整体对外提供服务。由于我们的系统保证了P(分区容错性),那么A和B的同步,我们允许出现故障。接下来我们再保证A(可用性),也就是说A和B同步出现问题时,客户端还能够访问我们的系统,那么客户端既可能访问A也可能访问B,这时,A和B的数据是不一致的,所以C(一致性)不能满足。

如果我们满足C(一致性),也就是说客户端无论访问A还是访问B,得到的结果都是一样的,那么现在A和B的数据不一致,需要等到A和B的数据一致以后,也就是同步恢复以后,才可对外提供服务。这样我们虽然满足了C(一致性),却不能满足A(可用性)。

所以,我们的系统在满足P(分区容错性)的同时,只能在A(可用性)和C(一致性)当中选择一个不能CAP同时满足。我们的分布式系统只能是AP或者CP。

3 ACID与BASE

在关系型数据库中,最大的特点就是事务处理,也就是ACID。ACID是事务处理的4个特性。

  • A - Atomicity(原子性),事务中的操作要么都做,要么都不做。

  • C - Consistency(一致性),系统必须始终处在强一致状态下。

  • I - Isolation(隔离性),一个事务的执行不能被其他事务所干扰。

  • D - Durability(持久性),一个已提交的事务对数据库中数据的改变是永久性的。

ACID强调的是强一致性,要么全做,要么全不做,所有的用户看到的都是一致的数据。传统的数据库都有ACID特性,它们在CAP原理中,保证的是CA。但是在分布式系统大行其道的今天,满足CA特性的系统很难生存下去。ACID也逐渐的向BASE转换。那么什么是BASE呢?

BASE是Basically Available(基本可用), Soft-state(软状态), Eventually consistent(最终一致)的缩写。

  • Basically Available,基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。

    电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。

  • 软状态( Soft State)

    软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有两到三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。

  • 最终一致性( Eventual Consistency)

    最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

BASE模型是传统ACID模型的反面,不同与ACID,BASE强调牺牲高一致性,从而获得可用性,数据允许在一段时间内的不一致,只要保证最终一致就可以了。

在分布式事务的解决方案中,它们都是依赖了ACID或者BASE的模型而实现的。像基于XA协议的两阶段提交和实物补偿机制就是基于ACID实现的。而基于本地消息表和基于MQ的最终一致方案都是通过BASE原理实现的。这几种分布式事务的解决方案,我们会在视频的课程中给大家讲解。

4 由分库分表引发的事物问题和解决方案

4.1 由分库分表引发的事物问题

传统的应用都是单一数据库事物,所有的业务表都在同一数据库内,这时候数据库的事物可以得到很好的支持,如下图所示:

image-20210724171356938

然后在同一个业务内,再把数据库进行水平切分多个数据库,多个数据库之间是没有办法无法统一事务管理的,就会造成数据不一致的情况。如果按照垂直切分成多个数据库,如下图所示:

image-20210724172152429

比如:

  • 一个下单操作,用户使用积分购买商品

  • 用户库扣减积分,订单库生成订单,商品库扣减库存

  • 由于它们不在同一数据库,不能改保证事务统一

  • 任何一个环节出错,其他两个数据的事务将不能回滚

4.2 解决方案

那么如何解决呢?

  • 基于XA协议的两阶段提交
  • 事务补偿机制
  • 基于本地消息表+定时任务的最终一致性方案
  • 基于MQ的最终一致方案

4.2.1 基于XA协议的两阶段提交

XA 协议原理简介

  • XA 是由 X/Open 组织提出的分布式事务的规范

  • 有一个事务管理器(TM)和多个资源管理器(RM)组成

    TM:数据源,RM:数据库

  • 提交阶段分为两个阶段:prepare 和 commit

    也就是说在提交之前,让所有的数据库先进行准备,准备好了之后通知事务管理器,然后由事务管理器统一的提交事务,如下图所示:

    image-20210724175921780

    image-20210724180456245

  • XA协议保证了数据的强一致性

  • commit 阶段出现问题,事务不一致,需人工处理

  • 但是两阶段提交效率低下,性能与本地事务相差 10 倍

  • MySql5.7 及以上均支持XA协议

  • Mysql Connector/J 5.0以上支持XA协议

  • Java系统中,数据源可以采用 Atomikos(充当事务管理器)

4.2.1.1 使用Mycat 或者Sharding-Jdbc

配置Mycat

通过修改conf/server.xml配置分布式事务,如下图所示:

至于Sharding-Jdbc则默认为我们开启了分布式事务

4.2.2 事务补偿机制

什么事务补偿机制?

其实就是针对每个操作,都要注册一个与其对应的补偿(撤销)操作,在执行失败时,调用补偿操作,撤销之前的操作。

例如一个A给B转账的例子:

image-20210725155803128

  • A 和 B 在不两家不同的银行
  • A 账户减 200元,B 账户加 200 元
  • 两个操作要保证原子性,要么都成功,要么都失败
  • 由于A和B在两家不同的银行,所以存在分布式事务问题
  • 转账接口需要提供补偿机制
  • 如果A在扣减的过程中出现问题,直接抛出异常,事务回滚
  • B在增加余额的过程中,出现问题,要调用A的补偿接口
  • A之前的扣减操作,得到了补偿,进行了撤销
  • 保证了A和B的帐是没有问题的

如果A补偿操作也失败了呢?

我们可以为A补偿操作添加有限次数的重试机制,超出重试次数后,人工介入。

事务补偿机制看起来有点繁琐,不推荐使用。

事务补偿机制的优缺点:

  • 优点:逻辑清晰、流程简单

  • 缺点:数据一致性比XA还要差,可能出错的点比较多

  • TCC属于应用层的一种补偿方式,程序员需要写大量的代码

4.2.3 基于本地消息表的的最终一致性方案

image-20210726213335173

  • 采用BASE原理,保证事务最终一致
  • 在一致性方面,允许一段时间内的不一致,但最终会一致
  • 在实际的系统中,要根据具体情况,判断是否采用
  • 基于本地消息表的方案中,将本事务外操作,记录在消息表中
  • 其他的事务要提供操作接口(例如支付宝、微信支付的接口)
  • 定时任务轮训本地消息表,将未执行的的消息发送给操作接口
  • 操作接口处理成功,返回成功标识,处理失败返回失败标识
  • 定时任务接到标识,更新消息的状态
  • 定时任务按照一定的周期反复执行
  • 对于屡次失败的消息,可以设置最大失败次数
  • 超过最大失败次数的消息,不再进行接口调用
  • 等待人工处理

那么这个方案有什么优缺点呢?

  • 优点:避免了了分布式事务,实现了最终一致性
  • 缺点:要注意重试时的幂等性操作

4.2.4 基于MQ的最终一致性方案

  • 原理、流程与本地消息表类似
  • 不同点1:本地消息表改为 MQ
  • 不同点2:定时任务改为MQ的消费者

这样就不在依赖于定时任务了,架构图如下所示:

image-20210728232239034

  1. 首先,业务系统将数据保存到数据库中

  2. 然后,业务系统把另外一条消息存放到消息队列中

  3. 消费者从消息队列中去取消息

  4. 消费者执行分布式事务的第二段的服务,把数据落入到数据库中去

优点

  • 不依赖于定时任务,基于MQ更高效、更可靠
  • 适合公司内部的系统
  • 不同公司之间无法基于MQ,本地消息表更合适
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值