阿里技术(如何选择分布式事务解决方案?) https://mp.weixin.qq.com/s/2AL3uJ5BG2X3Y2Vxg0XqnQ## 起初看了这个分布式相关的信息,对于seata 有点想了解一下实现的精髓,之前公司内部也有大佬分享过seata 还不止一次的分享过 内部也实现了一个简单的分布式事务,借此机会了解一下这个鬼东西。 Seata (Simple Extensible Autonomous Transaction Architecture) AT (Automatic Transaction) 模式
官方的文档: https://seata.io/zh-cn/docs/overview/what-is-seata.html
AT 模式 完全是根据 上面 https://mp.weixin.qq.com/s/2AL3uJ5BG2X3Y2Vxg0XqnQ## 这篇博客copy 下来的,感觉比官方文档说明更加的清楚,两阶段提交的变异品,总体来说还是十分不错。Seata支持很多种模式 AT、TCC、XA、SAGA 但是AT具有创新性,我们就了解这个吧。
下面我们重点说一下 AT 模式的运行机制:
AT 模式通过自动生成回滚日志的方式,使得业务方接入成本低,对业务入侵度很低,但是应用 AT 模式也有一些限制:
java 环境变量
mysql 本地安装一台
nacos 安装,下载 nacos-1.2.1
https://github.com/alibaba/nacos/releases
启动脚本 ./bin startup.sh -m standalone
访问地址: http://127.0.0.1:8848/nacos/#
seata server 安装
https://github.com/seata/seata/releases
参考这个文档: https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
本地启动seata-server 使用db-server sql 初始化脚本
https://github.com/seata/seata/blob/1.2.0/script/server/db/mysql.sql
修改server的配置文件 模式修改为db,修改数据库密码
启动脚本 sh ./bin/seata-server.sh -p 8091 -h 127.0.0.1 -m db
at 模式客户端也需要undo_log 数据库创建,github seata example 目录下 也有sql
https://github.com/seata/seata/blob/1.2.0/script/client/at/db/mysql.sql
下载github seata example
https://github.com/seata/seata-samples/tree/master/springboot-dubbo-seata/
然后根据官方的文档: https://seata.io/zh-cn/docs/user/quickstart.html 即可体验一下子。
这里 客户端的服务端都使用一个数据库拉~
此时,我们已经下载好了 seata example 、启动好了 seata server、nacos等等。
官方的体验文档: https://seata.io/zh-cn/docs/user/quickstart.html 这里的前提是修改好了 数据库密码
然后去查看数据库,水杯的数据的变化
http://localhost:8104/business/dubbo/buy
{
"userId": "1",
"commodityCode": "C201901140001",
"name": "demoData",
"count": 1,
"amount": 1
}
从seata的逻辑流程图中可以看到一丝的痕迹,拦截要做一些的处理,传递context 信息,为后续业务接口的调用传递上下文信息。eg xid
/**
* init global transaction scanner
*
* @Return: GlobalTransactionScanner
*/
@Bean
public GlobalTransactionScanner globalTransactionScanner(){
return new GlobalTransactionScanner("dubbo-gts-seata-example", "my_test_tx_group");
}
io.seata.rm.datasource.DataSourceProxy,为啥要代理连接池?这个是执行sql的地方啊!从AT 模式: https://seata.io/zh-cn/docs/overview/what-is-seata.html 这个实践的原理中有过介绍 ,业务发起方会将分布式事务的上下文进行传递,如果当前执行事务有分布式的上下文信息,那么就会解析sql,查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据,执行业务 SQL:更新这条记录,询后镜像:根据前镜像的结果,通过 主键 定位数据。
这里对于sql的解析, 兼容性真的需要水平。(AT 模式是通过对 SQL 解析来完成的,对 SQL 语法的支持有限,使用复杂 SQL 时需要考虑兼容性。目前不支持复合主键,业务表在设计时注意添加自增主键。)
/**
* init datasource proxy
* @Param: druidDataSource datasource bean instance
* @Return: DataSourceProxy datasource proxy
*/
@Bean
public DataSourceProxy dataSourceProxy(DruidDataSource druidDataSource){
return new DataSourceProxy(druidDataSource);
}
@Bean
public DataSourceTransactionManager transactionManager(DataSourceProxy dataSourceProxy) {
return new DataSourceTransactionManager(dataSourceProxy);
}
{
"@class": "io.seata.rm.datasource.undo.BranchUndoLog",
"xid": "192.168.0.104:8091:2012950778",
"branchId": 2012950785,
"sqlUndoLogs": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.undo.SQLUndoLog",
"sqlType": "UPDATE",
"tableName": "t_storage",
"beforeImage": {
"@class": "io.seata.rm.datasource.sql.struct.TableRecords",
"tableName": "t_storage",
"rows": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Row",
"fields": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "id",
"keyType": "PRIMARY_KEY",
"type": 4,
"value": 1
},
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "count",
"keyType": "NULL",
"type": 4,
"value": 999
}
]
]
}
]
]
},
"afterImage": {
"@class": "io.seata.rm.datasource.sql.struct.TableRecords",
"tableName": "t_storage",
"rows": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Row",
"fields": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "id",
"keyType": "PRIMARY_KEY",
"type": 4,
"value": 1
},
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "count",
"keyType": "NULL",
"type": 4,
"value": 998
}
]
]
}
]
]
}
}
]
]
}
从程序的角度实践,简单的了解了一下seata的使用,了解了AT 模式对于二阶段提交的改进的使用。动手实践一下还是不错的,GlobalTransactionScanner 拦截全局事务,注册TM client、RM client 通过netty活server端通信,其中还有动态从配置中读出配置等等接入,简单的看看一下源代码,学习了一波。结合 https://mp.weixin.qq.com/s/2AL3uJ5BG2X3Y2Vxg0XqnQ## 这篇文章,理论和实践都玩了一下,seata example 中还玩了一下TCC 模式嗯。