乐趣区

关于数据库:分布式事务实战一个完整的XA是什么样的

事务

某些业务要求,一系列操作必须全副执行,而不能仅执行一部分。例如,一个转账操作:

-- 从 id= 1 的账户给 id= 2 的账户转账 100 元
-- 第一步:将 id= 1 的 A 账户余额减去 100
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 第二步:将 id= 2 的 B 账户余额加上 100
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

这两条 SQL 语句必须全副执行,或者,因为某些起因,如果第一条语句胜利,第二条语句失败,就必须全副撤销。

这种把多条语句作为一个整体进行操作的性能,被称为数据库事务。数据库事务能够确保该事务范畴内的所有操作都能够全副胜利或者全副失败。如果事务失败,那么成果就和没有执行这些 SQL 一样,不会对数据库数据有任何改变。

更多事务介绍

微服务

如果一个事务波及的所有操作可能放在一个服务外部,那么应用各门语言里事务相干的库,能够轻松的实现多个操作作为整体的事务操作。

然而有些服务,例如生成订单波及做很多操作,包含库存、优惠券、赠送、账户余额等。当零碎复杂程度减少时,想要把所有这些操作放到一个服务内实现,会导致耦合度太高,保护老本十分高。

针对简单的零碎,以后风行的微服务架构是十分好的解决方案,该架构可能把简单零碎进行拆分,拆分后造成了大量微服务,独立开发,独立保护。

更多微服务介绍

尽管服务拆分了,然而订单自身的逻辑须要多个操作作为一个整体,要么全副胜利,要么全副失败,这就带来了新的挑战。如何把散落在各个微服务中的本地事务,组成一个大的事务,保障他们作为一个整体,这就是分布式事务须要解决的问题。

分布式事务

分布式事务简略的说,就是一次大的操作由不同的小操作组成,这些小的操作散布在不同的服务器上,且属于不同的利用,分布式事务须要保障这些小操作要么全副胜利,要么全副失败。实质上来说,分布式事务就是为了保障不同数据库的数据一致性。

更多分布式事务介绍

分布式事务计划包含:

  • xa
  • tcc
  • saga
  • 可靠消息

上面咱们看看最简略的 xa

XA

XA 是由 X /Open 组织提出的分布式事务的标准,XA 标准次要定义了 (全局) 事务管理器 (TM) 和(部分)资源管理器 (RM) 之间的接口。本地的数据库如 mysql 在 XA 中表演的是 RM 角色

XA 一共分为两阶段:

第一阶段(prepare):即所有的参与者 RM 筹备执行事务并锁住须要的资源。参与者 ready 时,向 TM 报告已准备就绪。
第二阶段 (commit/rollback):当事务管理者 (TM) 确认所有参与者 (RM) 都 ready 后,向所有参与者发送 commit 命令。

目前支流的数据库根本都反对 XA 事务,包含 mysql、oracle、sqlserver、postgre

咱们看看本地数据库是如何反对 XA 的:

第一阶段 筹备


XA start '4fPqCNTYeSG'
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG'
-- 当所有的参与者实现了 prepare,就进入第二阶段 提交
xa commit '4fPqCNTYeSG'

xa 实际

介绍了这么多,咱们来实际实现一个微服务上的 xa 事务,加深分布式事务的了解,这里采纳 dtm 作为分布式事务的管理者,来运行其中一个 xa 的 demo

装置 go
装置 mysql

获取 dtm

git clone https://github.com/yedf/dtm.git
cd dtm

配置 mysql

cp conf.sample.yml conf.yml
vi conf.yml

运行示例

go run app/main.go xa

从日志里,可能找到 XA 局部的输入,最初胜利提交实现了事务

# 服务 1 输入
XA start '4fPqCNTYeSG'
UPDATE `user_account` SET `balance`=balance - 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG'

# 服务 2 输入
XA start '4fPqCPijxyC'
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.493' WHERE user_id = '2'
XA end '4fPqCPijxyC'
XA prepare '4fPqCPijxyC'

# 服务 1 输入
xa commit '4fPqCNTYeSG'

#服务 2 输入
xa commit '4fPqCPijxyC'

整个交互的时序详情如下

总结

至此,一个残缺的 xa 分布式事务介绍实现。
在这篇简短的文章里,咱们大抵介绍了 事务,分布式事务,微服务解决 XA 事务。有趣味的同学能够通过 dtm 持续钻研分布式事务。

退出移动版