2019 年 1 月,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback),和社区一起共建开源分布式事务解决方案。Fescar 的愿景是让分布式事务的使用像本地事务的使用一样,简单和高效,并逐步解决开发者们遇到的分布式事务方面的所有难题。
Fescar 开源后,蚂蚁金服加入 Fescar 社区参与共建,并在 Fescar 0.4.0 版本中贡献了 TCC 模式。
为了打造更中立、更开放、生态更加丰富的分布式事务开源社区,经过社区核心成员的投票,大家决定对 Fescar 进行品牌升级,并更名为 Seata,意为:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事务解决方案。
Seata 融合了阿里巴巴和蚂蚁金服在分布式事务技术上的积累,并沉淀了新零售、云计算和新金融等场景下丰富的实践经验,但要实现适用于所有的分布式事务场景的愿景,仍有很长的路要走。因此,我们决定建立一个完全中立的分布式事务组织,希望更多的企业、开发者能够加入我们,一起打造 Seata。
Maven
Git
JDK
IntelliJ IDEA
注意,IntelliJ IDEA 最好使用最新版本。目前艿艿使用的是 2019.1.2 ,避免出现奇怪的问题。= =~反正我是出了,所以做了升级。
MySQL
Nacos
本小节,我们需要拉取两个项目的源码:
使用 IntelliJ IDEA 从 https://github.com/seata/seata-samples 拉取代码。拉取完成后,Maven 会下载依赖包,可能会花费一些时间,耐心等待下。
从官方仓库 https://github.com/seata/seata Fork
出属于自己的仓库。为什么要 Fork
?既然开始阅读、调试源码,我们可能会写一些注释,有了自己的仓库,可以进行自由的提交。
本文基于 develop
分支,对应 Seata 的 0.6.0-SNAPSHOT 版本。
艿艿:现在开始,需要一些简单的骚操作,注意落。
1、打开命令行,使用 git clone https://github.com/seata/seata
命令,克隆 Seata 源码到本地。
如果胖友 Fork 了 Seata 项目,注意替换成自己的仓库地址。
2、打开 IntelliJ IDEA ,点击菜单 [File] -> [Module from Existing Sources]
,选择 Demo 项目。然后,使用 Maven 格式进行导入。最终效果如下图:
这么做是,方便后面 IDEA 调试 Seata 源码时,使用我们克隆的项目的源码。
3、修改 Demo 项目引用 Seata 的版本号,为克隆的 Seata 项目的版本号(例如本文为 0.6.0-SNAPSHOT)。如下图所示:
艿艿:下面,开始正式的表演。hohoho 。
比较简单,搜到 io.seata.server.Server
类,直接迅猛右键 main 方法,运行,启动完毕。可看到如下日志:
INFO [main]io.seata.core.rpc.netty.AbstractRpcRemotingServer.start:152 -Server started ...
Seata 提供了各种 Demo ,艿艿选择了 spring-boot-dubbo-seata
项目,基于 Spring Boot + Dubbo 的示例。
艿艿:目前 Seata 暂时只支持 MySQL ,所以胖友一定要注意噢。
db_gts_fescar
。spring-boot-dubbo-seata/sql/db_seata.sql
导入到数据库中,进行表的初始化。艿艿:可能胖友会有疑惑,使用单库怎么测试分布式事务呢?即使单库,如果多个服务进行事务操作,一样会形成分布式事务。
因为 spring-boot-dubbo-seata
示例,使用 Nacos 作为注册中心,所以需要胖友自己启动一个 Nacos 服务。
艿艿:保持耐心。Nacos 未来我们也是要学习的,现在就是提前演戏了一波。
详细可以参考教程:《官网文档 —— Nacos 支持三种部署模式》
1、打开 https://github.com/alibaba/nacos/releases 网页,下载 Nacos 。艿艿目前看到的最新版本是 1.0.0 ,所以当然下载它。
2、创建数据库,名字为 nacos_devtest
。然后,将 Nacos 所在目录/conf/nacos-mysql.sql
导入数据库中。
3、编辑 Nacos 所在目录/conf/application.properties
配置文件,增加 Nacos 数据库连接。例如如下:
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://180.167.213.26:13306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=你的密码
4、执行 nohup sh bin/startup.sh -m standalone &
命令,启动 Nacos 服务。
5、浏览器打开 http://127.0.0.1:8848/nacos
网页,输入 nacos / nacos 进行登录。
艿艿:至此,我们终于启动 Nacos 服务。此时,来听一首《爱的魔力转圈圈》,放松下心情。
后面,基本就没复杂步骤啦,淡定淡定。
搜到 io.seata.samples.integration.storage.StorageGtsFescarExampleApplication
类,直接迅猛右键 main 方法,运行,启动完毕。可看到如下日志:
INFO 29748 --- [imeoutChecker_1] i.s.core.rpc.netty.NettyPoolableFactory : NettyPool create channel to transactionRole:TMROLE,address:127.0.0.1:8091,msg:< RegisterTMRequest{applicationId='storage-gts-fescar-example', transactionServiceGroup='my_test_tx_group'} >
INFO 29748 --- [imeoutChecker_1] io.seata.core.rpc.netty.RmRpcClient : will connect to 127.0.0.1:8091
INFO 29748 --- [imeoutChecker_1] io.seata.core.rpc.netty.RmRpcClient : RM will register :jdbc:mysql://180.167.213.26:13306/db_gts_fescar?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
INFO 29748 --- [imeoutChecker_1] i.s.core.rpc.netty.NettyPoolableFactory : NettyPool create channel to transactionRole:RMROLE,address:127.0.0.1:8091,msg:< RegisterRMRequest{resourceIds='jdbc:mysql://180.167.213.26:13306/db_gts_fescar?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true', applicationId='storage-gts-fescar-example', transactionServiceGroup='my_test_tx_group'} >
INFO 29748 --- [imeoutChecker_1] io.seata.core.rpc.netty.RmRpcClient : register RM success. server version:0.6.0,channel:[id: 0x56592a3a, L:/127.0.0.1:62656 - R:/127.0.0.1:8091]
INFO 29748 --- [imeoutChecker_1] i.s.core.rpc.netty.NettyPoolableFactory : register success, cost 32 ms, version:0.6.0,role:TMROLE,channel:[id: 0xca65c481, L:/127.0.0.1:62657 - R:/127.0.0.1:8091]
INFO 29748 --- [imeoutChecker_1] i.s.core.rpc.netty.NettyPoolableFactory : register success, cost 41 ms, version:0.6.0,role:RMROLE,channel:[id: 0x56592a3a, L:/127.0.0.1:62656 - R:/127.0.0.1:8091]
搜到 io.seata.samples.integration.account.AccountGtsFescarExampleApplication
类,直接迅猛右键 main 方法,运行,启动完毕。
效果同 samples-storage
项目。
搜到 io.seata.samples.integration.order.OrderGtsFescarExampleApplication
类,直接迅猛右键 main 方法,运行,启动完毕。
效果同 samples-storage
项目。
搜到 io.seata.samples.integration.call.DubboGtsFescarExampleApplication
类,直接迅猛右键 main 方法,运行,启动完毕。
至此,我们已经把需要启动的项目,都启动完毕。此时,我们打开 Nacos 可以看到各个服务的状况。如下图:
下面,我们将测试两种情况:
因为,下面是要模拟调用 HTTP 接口,所以需要胖友有 Postman 。
在 Postman 中,模拟请求如下图:
请求地址:127.0.0.1:8104//business/dubbo/buy
请求数据:
{
"userId": "1",
"commodityCode": "C201901140001",
"name": "水杯",
"count": 1,
"amount": 0.01
}
请求成功后,我们看看数据的变化。如下图:
在 Postman 中,模拟请求如下图:
"commodityCode"
写错成了 "C201901140001xxxx"
,用于模拟分布式事务,因为库存不足,进行回滚。#handleBusiness(BusinessDTO businessDTO)
方法,第 XX 行,打了一个断点。如下图所示:做好了这些准备,我们点击 Postman ,执行请求。因为我们在 BusinessServiceImpl 打了断点,所以我们看看执行到此处,数据的变化。如下图:
此时,我们放开断点,执行下去,因为扣库存失败,所以会抛出 DefaultException 异常,从而回滚全局事务。然后呢,数据又恢复:
开始正式调试源码前,建议胖友能看看文章:
《Seata 官方文档》
一定一定一定要看官方文档,不要对自己太自信,哈哈哈哈。
特别是 《AT Mode》 文章。
《fescar 锁设计和隔离级别的理解》
《分布式事务中间件 Fescar - RM 模块源码解读》
《Fescar 分布式事务实现原理解析探秘》