目录
TC(Transtaction coordinator)事务协调者
File: 单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高
Db: 高可用模式,全局事务会话信息通过db共享,相应性能差些
3修改seata conf/application.yml文件
引言
最近公司在做架构迁移分布式事务从at模式到tcc模式,近几年行业也比较严峻,裁了很多老人被裁,新人太多,很多小伙伴对分布式事务一直半解,老大让我做个技术文档分享本文由来,技术不精往大佬多多指教
概要
在微服务架构下,服务之间通过RPC远程调用,相对单机事务来说,多了“网络通信”这一不确定因素,使得本来服务的调用只有“成功”和“失败”这两种返回结果,变为“成功”、“失败”和“未知”三种返回结果。系统之间的通信可靠性从单一系统中的可靠变成了微服务架构之间的不可靠,分布式事务其实就是在不可靠的通信下实现事务的特性。一般因为网络导致的异常可能有机器宕机、网络异常、消息丢失、消息乱序、数据错误、不可靠的TCP、存储数据丢失、其他异常等等
分布式事务框架
- 阿里开源的 seata(本文主讲的框架)
- LCN(国产开源的分布式框架)ps:博主只是听说过没有用过
Seata简介
目前seata基本实现了最常用的各个场景的分布式事务解决方案,主要分为以下四种模式
XA模式
官方文档 : seataXA模式
缺点:需要数据库支持XA协议,长事务,持久占用资源,效率较低(分支事务需要在第二阶段执行后才进行提交或回
优点: 强一致性保证,不会有分布式事务的脏读、脏写发生
AT模式
官方文档:seata模式
优点: 灵活性非常高,TCC每个阶段都可以自己控制
缺点: try、confirm、cancel三个阶段都需要自己做控制,编写起来很麻烦,自己编写的过程中需要注意的点也很多,需要对TCC模式充分了解,业务侵入性很高TCC模式
官方文档:seataTCC模式
优点: AT模式也是基于2PC思想,但是他在第一阶段执行完后,分支事务就已经提交了,而不用等到第二阶段执行后再提交分支事务,解决了XA模式的持久占用数据库资源的重大缺陷。并且业务侵入性非常低
缺点: 会有一定的脏读和脏写问题 参考seta事务的隔离级别解读
Saga模式
官方文档:saga模式
优缺点:博主没有研究过有需要的大佬可以自己观看
Tcc 模式
优点:业务比较灵活,不依赖数据库
缺点:代码入侵比较大
seata三大角色
Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务 系统集成
TC(Transtaction coordinator)事务协调者
维护全局事务和分支事务的状态,驱动全局事务的回滚
TM(transtaction manager)事务管理器
定义全局事务的范围:开启全局事务,提交或者事务回滚
RM(Resource Manager) 资源管理器
管理分支事务处理的资源,与Tc通信注册分支事务和报告事务的状态,并驱动分支事务提交或者回滚
Seata端存储模式,
File: 单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高
Db: 高可用模式,全局事务会话信息通过db共享,相应性能差些
Redis:性能高但是要保证数据不丢失(数据持久化)
环境搭建
1:下载seata安装包博主用的是1.5.2的版本
官网地址Release v1.5.2 · seata/seata · GitHub
百度云链接:https://pan.baidu.com/s/1eGoc8nhI4QCsERdE7Zdrpg
提取码:ck3f
2:创建seata数据库执行sql脚本
解压文件目录
3修改seata conf/application.yml文件
server:
port: 7091 #默认的端口
spring:
application:
name: seata-server #服务端指定连接seata的服务名
logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
console:
user:
username: seata #seata配置网页端监控分布式事务其实就是把刚刚建表的数据拿出来
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos #指定服务注册中心为nacos
nacos: #服务分组指定从哪里拉取nacos配置
server-addr: 192.168.10.15:8848
namespace: 0f100e5c-00e2-4c05-b99f-1d3f22561fa4
group: SEATA_GROUP
data-id: seataServer.properties
username: nacos
password: nacos
registry: #把seata服务注册到naocs行
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 192.168.10.15:8848
group: SEATA_GROUP
namespace: 0f100e5c-00e2-4c05-b99f-1d3f22561fa4
cluster: default
username: nacos
password: nacos
#store:
# support: file 、 db 、 redis
# mode: file
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
4上传配置到nacos配置中心
这里需要修改的配置为
store.mode=db #指定mode为db存储
store.db.datasource=druid #指定连接池
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://192.168.10.15:3306/seata?useUnicode=true&rewriteBatchedStatements=true
service.vgroupMapping.default_tx_group=default
注意: rewriteBatchedStatements=true这个值需要配置seata是通过jdbc的executebatch来插入全局锁的指定这个参数可以批量插入性能会提高很多,jdbc驱动会把对应的SQL优化成`insert into () values (), ()`的形式来提升批量插入的性 能。
service.vgroupMapping 后面跟着的是事务分组的名称后面要用到默认 default_tx_group 统一分组其它子事务才能别tc管理和注册
修改好了上传到nacos配置中心博主用的nacos版本为2.0.3
5启动seata sever
进入bin目录
./seata.sh -h 192.168.10.15 -p 8091 >myout.log 2>&1 & #指定输出文件
-h指定ip -p指定端口
如果想要集群启动加一个 -n参数指定 id
Seata支持的参数
可以登录控制台查看
Ip:7091/#login 密码默认seata /seata
数据库配置
#每个业务库下
CREATE TABLE `branch_table` (
`branch_id` bigint(20) NOT NULL,
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime(6) DEFAULT NULL,
`gmt_modified` datetime(6) DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
服务端配置
例入现在又 A,B,C 三个服务 A 为外层服务 B,C为底层服务 A 调用BC
BC 服务正常使用transcation 注解,(所有的底层服务都要使用上面的yum配置) A服务使用注解GlobalTransactional
ps:业务需求,需要插入日志表可以解绑事务调用事务上下文
String xid =rootContext.getXid()
RootContext.unbind(xid);
//业务
RootContext.bind(xid);
代码地址: https://gitee.com/sword-flying/seata.git