目录

  1. 概述
  2. 分布式事务基础理论
    1. CAP 原理
      1. 应用场景
      2. 一致性(Consistency)
      3. 可用性(Availability)
      4. 分区容错性(Partition tolerance)
      5. CAP 组合方式
      6. 总结
    2. BASE 理论
      1. 一致性再探究
      2. 理论探究
      3. 柔性事务
  3. 附录

事务小回顾:事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。事务应该具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。但是本文的重心并不在事务,而是分布式事务

概述

❓为什么会有分布式事务?

如今大部分的系统都是分布式的,一个项目可能存在众多的微服务,服务之间通过远程调用这就会涉及事务操作。比如:订单微服务和库存微服务,下单的同时订单微服务请求库存微服务减库存。本质是由于跨 JVM 进程产生分布式事务

单体系统访问多个数据实例时就会产生分布式事务。比如:用户信息和订单信息分别在两个 MySQL 实例存储,用户管理系统删除用户信息,需要分别删除用户信息及用户的订单信息,由于数据分布在不同的数据实例,需要通过不同的数据库链接去操作数据,此时产生分布式事务

多服务访问同一个数据库实例也会产生分布式事务。比如:订单微服务和库存微服务即使访问同一个数据库也会产生分布式事务,原因就是跨 JVM 进程,两个微服务持有了不同的数据库链接进行数据库操作,此时产生分布式事务

📓总结下来,存在三种场景会产生分布式事务

  • 跨 JVM 进程交互
  • 单体系统访问多个数据实例
  • 多服务访问同一个数据库实例

❓什么是分布式事务?

  • 通常所说的事务是单机事务,即一个事务包含的操作都在一个数据库内完成,但是如果事务调用了不同机器上的操作,此时事务就变为分布式事务

  • 分布式系统会把一个应用系统拆分未可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成的事务称之为分布式事务

本地事务依赖于数据库本身提供的事务特性来实现,因此以下逻辑可以控制本地事务:

1
2
3
4
begin transaction;
#1. 本地数据库操作:张三减少账户余额
#1. 本地数据库操作:李四增加账户余额
commit transaction;

在分布式环境下,事务操作会变成下边这样:

1
2
3
4
begin transaction;
## 1.本地数据库操作:张三减少金额
## 2.远程调用:让李四增加金额
commit transation;

🎶当远程调用请求发出之后,由于网络问题远程调用结果并没有返回,此时本地事务以为出现问题,提交失败,张三执行回滚操作,但是李四其实操作执行完成只不过是由于网络的问题没有被张三接收到而已,此时张三和李四的数据就产生了不一致现象

📓分布式系统中,传统数据库事务无法使用,网络的不稳定性是导致分布式事务产生的根本原因

分布式事务基础理论

本小节总结分布式场景下系统的事务特点,与传统数据库事务的 ACID 不同,分布式系统存在 CAP 和 BASE 两种常见理论,通过这两种理论可以更加深入的理解分布式系统中的事务模型

CAP 原理

CAP 是 ConsistencyAvailabilityPartition tolerance三个词语的缩写,分别表示一致性可用性分区容忍性

应用场景

结合电商系统中的一些业务场景来理解 CAP,如下图,是商品信息管理的执行流程:

⛵整体执行流程如下:

  1. 商品服务请求主数据库写入商品信息(添加商品、修改商品、删除商品)
  2. 主数据库向商品服务响应写入成功
  3. 商品服务请求从数据库读取商品信息

一致性(Consistency)

一致性是指:写操作后的读操作可以读取到最新的数据状态,当数据分布在多个节点上,从任意结点读取到的数据都是最新的状态

一致性要求:要么立刻读取到最新的一致数据,要么阻塞等待能够读取到最新的一致数据,甚至如果操作失败,允许返回操作失败的信息

上面那个例子,商品信息的读写要满足一致性就是要实现如下目标:

  • 商品服务写入主数据库成功,则向从数据库查询新数据也成功
  • 商品服务写入主数据库失败,则向从数据库查询新数据也失败

✨分布式系统一致性满足的特点

  • 由于存在数据同步的过程,写操作的响应会有一定的延迟
  • 为了保证数据库一致性,会对资源暂时锁定,待数据同步完成释放锁定资源
  • 如果请求数据同步失败的结点则会返回错误信息,一定不会返回旧数据

❓如何实现一致性?

  • 写入主数据库后要将数据同步到从数据库
  • 写入主数据库后,在向从数据库同步期间要将从数据库锁定,待同步完成后再释放锁,以免在新数据库写入成功后,向从数据库查询到旧的数据

可用性(Availability)

可用性是指任何事务操作都可以得到响应结果,且不会出现响应超时或响应错误

上面那个例子,商品信息读取满足可用性就是要实现如下目标:

  • 从数据库接收到数据查询的请求则立即能够响应数据查询结果
  • 从数据库不允许出现响应超时或响应错误

❓如何实现可用性?

  • 写入主数据库后要将数据同步到从数据库
  • 由于要保证从数据库的可用性,不可将从数据库中的资源进行锁定
  • 即时数据还没有同步过来,从数据库也要返回要查询的数据,哪怕是旧数据,如果连旧数据也没有则可以按照约定返回一个默认信息,但不能返回错误或响应超时

✨分布式系统可用性的特点:所有请求都有响应,且不会出现响应超时或响应错误

分区容错性(Partition tolerance)

通常分布式系统的各各结点部署在不同的子网,这就是网络分区,不可避免的会出现由于网络问题而导致结点之间通信失败,此时仍可对外提供服务,这叫分区容忍性

上面那个例子,商品信息读写满足分区容忍性就是要实现如下目标:

  • 主数据库向从数据库同步数据失败,不影响从数据库的读写操作
  • 一个结点挂掉不影响另一个结点对外提供服务

❓如何实现分区容忍性?

  • 尽量使用异步取代同步操作,例如使用异步方式将数据从主数据库同步到从数据,这样结点之间能有效的实现松耦合
  • 添加从数据库结点,其中一个从结点挂掉其它从结点提供服务

✨分布式系统分区容忍性的特点:分区容忍性时分布式系统具备的基本能力

CAP 组合方式

❓上面商品管理的例子是否同时具备 CAP 的特性尼?

在所有的分布式事务场景中都不会同时具备 CAP 三个特性,因为在具备了分区容错性的前提下,可用性和一致性是不能共存的

商品管理的例子满足了分布容错性如图,本图中分区容错性的含义是:

主数据库通过网络向从数据同步数据,可以认为主从数据库部署在不同的分区,通过网络进行交互。当主数据库和从数据库之间的网络出现问题并不影响主数据库和从数据库对外提供服务。其中一个结点宕机也并不会影响另一个结点对外提供服务

如果要实现一致性,必须要保证主从数据库中数据的一致性,即:在数据同步的时候为了防止其他用户在从数据库查询到不一致的数据,需要将从数据库锁定,等待数据库同步完成后再将从数据库解锁。此时,如果数据同步失败,从数据库要返回错误信息或超时信息给主数据库或者被阻塞的查询方。

如果要实现可用性,则必须保证数据的高可用,不管在任何的时候,都可以向从数据库查询数据,并且从数据库并不会向客户端返回响应超时或错误信息。

📓通过以上分析可以确认,如果一个系统是在网络分区中,那么可用性和一致性是相互矛盾的,最终 CAP 理论可以使用下图描述

所以在生产中对分布式事务处理时要根据需求来确定满足 CAP 的哪两个方面,常见的 CAP 组合方式由以下三种:

  • CA(强一致性、可用性)是传统的 Oracle 数据库,单点集群,不用考虑由于网络不通或结点挂掉的问题,此时系统不是一个标注年度分布式系统,平时最常用的关系型数据库就满足了 CA

  • AP(可用性、分区容错性)大多数网站架构的选择,通常实现 AP 都会保证最终一致性,一些业务场景比如:订单退款,今日退款成功,明日账户到账,只要用户可以接受在一定时间内到账即可

  • CP(强一致性、分区容错性)Redis、Mongodb

总结

📓CAP 理论核心:一个分布式系统不可能同时很好的满足一致性、可用性和分区容错性这三个需求,最多只能同时较好的满足两个。尤其对于多数大型互联网应用的场景,结点众多、部署分散,而且现在的集群规模越来越大,所以节点故障、网络故障是常态,而且要保证服务可用性达到 N 个 9(99.99…%),并要达到良好的响应性能来提高用户体验,因此一般都会做出如下选择:保证 P 和 A ,舍弃 C (强一致),保证最终一致性

❓为什么只能满足两个?
而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是存储系统必须实现的,所以常常只能在一致性可用性之间进行权衡,不存在任何一个系统能够同时保证这三点

✨一致性和可用性之间必须做出一个取舍,所幸当前大多数 Web 应用,其实并不需要强一致性,因此牺牲 C 换取 P,这是目前分布式数据库产品的方向

BASE 理论

CAP 理论告诉我们一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容忍性(Partition tolerance)这三项中的两项,其中 AP 在实际应用中较多,AP 即舍弃一致性,保证可用性和分区容忍性,但是在实际生产中很多场景都要实现一致性,比如前边举的例子主数据库向从数据库同步数据。

一致性再探究

即使分布式系统损失一致性,但是最终也要将数据同步成功来保证数据一致,其实这种一致性和 CAP 中的一致性不同,CAP 中的一致性要求在任何时间查询每个结点数据都必须一致,它强调的是强一致性,但是最终一致性是允许可以在一段时间内每个结点的数据不一致,经过一段时间每个结点的数据必须一致,它强调的是最终数据的一致性

🆚强一致性和最终一致性的异同

  • CAP 中的一致性要求在任何时间每个结点数据都必须一致,它强调的是强一致性

  • BASE 中的一致性是允许可以在一段时间内每个结点的数据不一致,但是经过一段时间每个结点的数据必须一致,它强调的是最终结果的一致性

📖其实除了以上说的强一致性和最终一致性外,还存在弱一致性

📓一致性总结

  • 强一致性:任何一次读都能读到某个数据的最近一次写的数据。系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。简言之,在任意时刻,所有节点中的数据是一样的

  • 弱一致性:数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性

  • 最终一致性:不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。简单说,就是在一段时间后,节点间的数据会最终达到一致状态

理论探究

❓什么是 BASE 理论

BASE 是 Basically Available(基本可用), Soft-state(软状态), Eventually consistent(最终一致性)的缩写,BASE 理论是对 CAP 中 AP 的一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终一致性,称之为柔性事务

❓什么是Basically Available(基本可用)

基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。如:电商网站交易付款出现问题了,商品依然可以正常浏览

❓什么是Soft-state(软状态)

软状态:由于不要求强一致性,所以 BASE 允许系统中存在中间状态(也叫软状态),这个状态不影响系统可用性,如订单的支付中数据同步中等状态,待数据最终一致后状态改为成功状态

❓什么是Eventually consistent(最终一致性)

最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。如订单的支付中状态,最终会变为支付成功或者支付失败,使订单状态与实际交易结果达成一致,但需要一定时间的延迟、等待

柔性事务

不同于 ACID 的刚性事务,在分布式场景下基于 BASE 理论,就出现了柔性事务的概念。要想通过柔性事务来达到最终的一致性,就需要依赖于一些特性,这些特性在具体的方案中不一定都要满足,因为不同的方案要求不一样;但是都不满足的话,是不可能做柔性事务的

附录

分布式事务,这一篇就够了
浅谈 CAP
The CAP FAQ