欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

分布式-事务

程序员文章站 2022-05-07 18:46:37
...

背景
事务:大多数情况下 指数据库的事务,事务处理定义。指运行在数据库上的一个逻辑的工作单元,SQL命令有原子性特点,完全执行或者撤销完全不执行(回滚)。

特性:
Atomic 原子性 事务必须是原子的工作单元
Consistent 一致性 事务完成时必须是所有的数据 保持一致的状态
ioslation 隔离性 并发事务所做的修改 必须和其他事务的修改隔离,通过锁
duration 持久性 事务完成后 对系统的影响是永久的

MySQL 事务处理过程
1、记录redo和undo 文件,确保日志在磁盘上持久化
2、更新数据记录
3、提交事务 redo 写入commit记录

redo 记录事务修改后的数据
undo 记录事务修改前的数据

产生原因
1、数据库的分库分表
拆分不同的database 一个操作会往两个库 更新。
在db1更新 db2添加数据

2、服务的SOA化,将独立的服务节点,拆分成不同的业务节点,各个节点通过RPC框架通信,数据库在各个节点做了处理,解耦的方式 完成处理的过程。
例如 电商系统 拆分成用户中心,库存中心,订单中心,商品中心
UserDB RepDB orderDB productDB
分布式-事务

概念
事务补偿机制: 在事务链中的任何一个正向事务操作, 都必须存在一个完全符合回滚规则的可逆事务.

CAP理论: CAP(Consistency, Availability, Partition Tolerance), 阐述了一个分布式系统的三个主要方面, 只能同时择其二进行实现. 常见的有CP系统, AP系统.

幂等性: 简单的说, 业务操作支持重试, 不会产生不利影响. 常见的实现方式: 为消息额外增加唯一ID.

BASE(Basically avaliable, soft state, eventually consistent): 是分布式事务实现的一种理论标准.

柔性事务 vs. 刚性事务

刚性事务是指严格遵循ACID原则的事务, 例如单机环境下的数据库事务.

柔性事务是指遵循BASE理论的事务, 通常用在分布式环境中,
常见的实现方式有: 两阶段提交(2PC), TCC补偿型提交, 基于消息的异步确保型, 最大努力通知型.

通常对本地事务采用刚性事务, 分布式事务使用柔性事务.

X/Open DTP 事务模型
x/open distributed Transacton Processing Reference Model
x/open 是一个机构 定义出的一套分布式事务标准
规范的api接口 ,具体实现由各个厂商实现

用来保证分布式事务的操作
J2EE遵循x/opent DTP 规范 实现了java的分布式事务编程接口规范 JTA
XA是X/Open DTP 定义的中间件与数据库之间的接口规范
XA接口函数由数据库厂商提供

角色
AP:application 应用节点
RM:resource manager 资源管理器 一般情况下是数据库 文件系统之类的
TM:transaction manager 事务管理器 事务协调者 负责解释ap发起的事务指令,调度协调参与者 所有RM的协调 确保事务正常完成

分布式-事务

RM 执行 特殊XA指令

2PC协议(two-phrase-commit)
分布式事务SQL逻辑执行完成,到了resource 提交事务关键时刻
避免分布式事务固有不可靠(CAP理论)因素 事务提交意外失败。
确定事务的提交。

阶段1:提交事务请求(事务的预提交 )
分布式-事务

协调者询问参与者事务是否执行成功,参与者发回事务执行结果。

1、TM向所有的AP发送事务指令 询问是否可以执行事务的提交操作 并等待各个AP的响应。中间的协调者才能知道两边的状态 等待AP的响应
2、执行事务
各个ap节点执行事务操作 将undo和redo信息记录写到事务日志中,
尽量提交过程中所消耗时间的操作和准备都提前完成后 确保后续事务提交的成功率。

3、各个AP向TM反馈事务询问的响应。
各个ap成功执行了事务操作 那么反馈给TM yes的response
如果ap没有成功执行事务 就反馈TM no的response

类似zookeeper 的投票 用到了事务的二阶段提交

阶段二:执行事务提交(修改状态)
分布式-事务
执行提交事务

如果事务在每个参与者上都执行成功,事务协调者发送通知让参与者提交事务;否则,协调者
发送通知让参与者回滚事务。
分布式-事务

中断事务提交
阶段一任何一个返回no 回滚
分布式-事务

分布式-事务

tm发送abort请求
undo日志 回滚
释放事务资源包括锁 返回ack响应给TM 统一回滚

优点:
事务提交过程30s,其中prepare操作需要28(事务日志 落地磁盘各种IO操作) 而真正commit只需要2s 那么 commit阶段发生错误的概率和prepare相比 2/28<10%
只要第一阶段成功 那么commit阶段出现失败的概率 非常小
大大增加了分布式事务的成功概率

缺点:
会产生数据一致性问题
当参与者 和协调者 都挂了的时候
第二个阶段参与者和协调者 都挂了
新选举协调者 commit 还是 rollback
参与者都执行 挂掉的参与者还没有恢复

存在的问题

  1. 同步阻塞
    所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作。
    同步阻塞,协调者故障,导致 所有参与者处于阻塞状态 导致性能问题
    等待协调者 处理

二阶段提交 发送请求过去 参与者 响应
响应执行事务请求 到参与者
网络中断 长时间等待 事务没有办法提交
等待阻塞 阻塞耗时 二阶段提交

  1. 单点问题
    协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响,特别是在阶段二发生故
    障,所有参与者会一直等待状态,无法完成其它操作。

  2. 数据不一致
    在阶段二,如果协调者只发送了部分 Commit 消息,此时网络发生异常,那么只有部分参与
    者接收到 Commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。

参与者和协调者故障会导致数据一致性问题
第二个阶段 提交过程中 协调者 向参与者 提交commmit请求 出现网络异常 协调者发生故障 导致只有部分的参与者 接受commit请求
有些节点 没有接收 出现部分节点的数据不一致的问题

发送commit 请求 发送 过去后
每个节点收到请求提交
其中一个节点 ap 挂掉 还没有执行
ap恢复以后
ack

  1. 太过保守
    任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

3PC (three phase commit)
两阶段过程中,
阶段一:canCommit 是不是能够提交事务
协调者询问参与者 询问是否可以执行该事务,任何其中一个返回No
去不了;

阶段二:preCommit
预执行,是否有时间 三人行
TM根据第一阶段反馈 决定是否执行事务操作
preCommit 请求 预执行

阶段三:doCommit
每一个参与者 告诉TM都可以执行 doCommit

询问各个阶段 是否能够执行
有些节点出现问题
第二个阶段 都挂了
参与者 协调者

2PC 超时机制 没有收到 正常的响应 事务执行失败

Commit 一旦执行 第一个阶段同一的 执行commit
确保后面操作
多一个步骤 确保可靠性

zookeeper 解决数据一致性问题 多阶段提交

分布式事务的实现

JOTM(java open transaction manager)
一个Object web 开源JTA规范实现

Atomikos(开源集成spring)

<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jdbc</artifactId>
    <version>3.9.3</version>
</dependency>
<denpency>
    <groupId>javax.transaction</groupId>
    <artifactId>jta</artifactId>
    <version>1.1</version>
</dependency>
<denpency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>1.1</version>
</dependency>

service-common.xml

TCC 事务 (DTS事务架构)

TCC分为三个阶段
trying
confirm
Caceling

开源的框架
tcc-traction
bytecc

相关标签: 分布式 事务