事务

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

-- 从id=1的账户给id=2的账户转账100元-- 第一步:将id=1的A账户余额减去100UPDATE accounts SET balance = balance - 100 WHERE id = 1;-- 第二步:将id=2的B账户余额加上100UPDATE 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.gitcd dtm

配置mysql

cp conf.sample.yml conf.ymlvi 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 持续钻研分布式事务。