Spark 3.0 中七个必须知道的 SQL 性能优化

本文提纲如下

  • 0. 前言

  • 1. 单数据源事务 & 多数据源事务

  • 2. 常见分布式事务解决方案

  • 2.1. 分布式事务模型

  • 2.2. 二将军问题和幂等性

  • 2.3. 两阶段提交(2PC) & 三阶段提交(3PC)方案

  • 2.4. TCC 方案

  • 2.5. 事务状态表方案

  • 2.6. 基于消息中间件的最终一致性事务方案

  • 3. Seata in AT mode 的实现

  • 3.1. Seata in AT mode 工作流程概述

  • 3.2. Seata in AT mode 工作流程详述

  • 4. 结束语


image.png

0. 前言

从 CPU 到内存、到磁盘、到操作系统、到网络,计算机系统处处存在不可靠因素。工程师和科学家努力使用各种软硬件方法对抗这种不可靠因素,保证数据和指令被正确地处理。在网络领域有 TCP 可靠传输协议、在存储领域有 Raid5 和 Raid6 算法、在数据库领域有基于 ARIES 算法理论实现的事务机制……

这篇文章先介绍单机数据库事务的 ACID 特性,然后指出分布式场景下操作多数据源面临的困境,引出分布式系统中常用的分布式事务解决方案,这些解决方案可以保证业务代码在操作多个数据源的时候,能够像操作单个数据源一样,具备 ACID 特性。文章在最后给出业界较为成熟的分布式事务框架——Seata 的 AT 模式全局事务的实现。

1. 单数据源事务 & 多数据源事务

如果一个应用程序在一次业务流中通过连接驱动和数据源接口只连接并查询(这里的查询是广义的,包括增删查改等)一个特定的数据库,该应用程序就可以利用数据库提供的事务机制(如果数据库支持事务的话)保证对库中记录所进行的操作的可靠性,这里的可靠性有四种语义:

  • 原子性,A

  • 一致性,C

  • 隔离性,I

  • 持久性,D

笔者在这里不再对这四种语义进行解释,了解单数据源事务及其 ACID 特性是读者阅读这篇文章的前提。单个数据库实现自身的事务特性是一个复杂又微妙的过程,例如 MySQL 的 InnoDB 引擎通过 Undo Log + Redo Log + ARIES 算法来实现。这是一个很宏大的话题,不在本文的描述范围,读者有兴趣的话可自行研究。

单数据源事务也可以叫做单机事务,或者本地事务。

在分布式场景下,一个系统由多个子系统构成,每个子系统有独立的数据源。多个子系统之间通过互相调用来组合出更复杂的业务。在时下流行的微服务系统架构中,每一个子系统被称作一个微服务,同样每个微服务都维护自己的数据库,以保持独立性。

例如,一个电商系统可能由购物微服务、库存微服务、订单微服务等组成。购物微服务通过调用库存微服务和订单微服务来整合出购物业务。用户请求购物微服务商完成下单时,购物微服务一方面调用库存微服务扣减相应商品的库存数量,另一方面调用订单微服务插入订单记录(为了后文描述分布式事务解决方案的方便,这里给出的是一个最简单的电商系统微服务划分和最简单的购物业务流程,后续的支付、物流等业务不在考虑范围内)。电商系统模型如下图所示:

image.png

在用户购物的业务场景中,shopping-service 的业务涉及两个数据库:库存库(repo_db)和订单库(repo_db),也就是 g 购物业务是调用多数据源来组合而成的。作为一个面向消费者的系统,电商系统要保证购物业务的高度可靠性,这里的可靠性同样有 ACID 四种语义。

但是一个数据库的本地事务机制仅仅对落到自己身上的查询操作(这里的查询是广义的,包括增删改查等)起作用,无法干涉对其他数据库的查询操作。所以,数据库自身提供的本地事务机制无法确保业务对多数据源全局操作的可靠性。

基于此,针对多数据源操作提出的分布式事务机制就出现了。

分布式事务也可以叫做全局事务。

2. 常见分布式事务解决方案

2.1. 分布式事务模型

image.png

描述分布式事务,常常会使用以下几个名词:

  • 事务参与者:例如每个数据库就是一个事务参与者

  • 事务协调者:访问多个数据源的服务程序,例如 shopping-service 就是事务协调者

  • 资源管理器(Resource Manager, RM):通常与事务参与者同义

  • 事务管理器(Transaction Manager, TM):通常与事务协调者同义

在分布式事务模型中,一个 TM 管理多个 RM,即一个服务程序访问多个数据源;TM 是一个全局事务管理器,协调多方本地事务的进度,使其共同提交或回滚,最终达成一种全局的 ACID 特性。

2.2. 二将军问题和幂等性

二将军问题是网络领域的一个经典问题,用于表达计算机网络中互联协议设计的微妙性和复杂性。这里给出一个二将军问题的简化版本:

一支白军被围困在一个山谷中,山谷的左右两侧是蓝军。困在山谷中的白军人数多于山谷两侧的任意一支蓝军,而少于两支蓝军的之和。若一支蓝军对白军单独发起进攻,则必败无疑;但若两支蓝军同时发起进攻,则可取胜。两只蓝军的总指挥位于山谷左侧,他希望两支蓝军同时发起进攻,这样就要把命令传到山谷右侧的蓝军,以告知发起进攻的具体时间。假设他们只能派遣士兵穿越白军所在的山谷(唯一的通信信道)来传递消息,那么在穿越山谷时,士兵有可能被俘虏。

image.png

只有当送信士兵成功往返后,总指挥才能确认这场战争的胜利(上方图)。现在问题来了,派遣出去送信的士兵没有回来,则左侧蓝军中的总指挥能不能决定按命令中约定的时间发起进攻?

答案是不确定,派遣出去送信的士兵没有回来,他可能遇到两种状况:

1)命令还没送达就被俘虏了(中间图),这时候右侧蓝军根本不知道要何时进攻;

2)命令送达,但返回途中被俘虏了(下方图),这时候右侧蓝军知道要何时进攻,但左侧蓝军不知道右侧蓝军是否知晓进攻时间。

类似的问题在计算机网络中普遍存在,例如发送者给接受者发送一个 HTTP 请求,或者 MySQL 客户端向 MySQL 服务器发送一条插入语句,然后超时了没有得到响应。请问服务器是写入成功了还是失败了?答案是不确定,有以下几种情况:

1)可能请求由于网络故障根本没有送到服务器,因此写入失败;

2)可能服务器收到了,也写入成功了,但是向客户端发送响应前服务器宕机了;

3)可能服务器收到了,也写入成功了,也向客户端发送了响应,但是由于网络故障未送到客户端。

无论哪种场景,在客户端看来都是一样的结果:它发出的请求没有得到响应。为了确保服务端成功写入数据,客户端只能重发请求,直至接收到服务端的响应。

类似的问题问题被称为网络二将

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值