一篇教你通过Seata解决分布式事务问题
1 Seata介绍Seata是由阿里中间件团队发起的开源分布式事务框架项目,
依赖支持本地 ACID 事务的关系型数据库,
可以高效并且对业务0侵入的方式解决微服务场景下面临的分布式事务问题,
目前提供AT模式(即2PC)、TCC、SAGA 和 XA 的分布式事务解决方案。2 Seata的设计思想
Seata的设计目标其一是对业务无侵入,因此从业务无侵入的2PC方案着手,在传统2PC的基础上演进,并解决2PC方案面临的刚性事务问题。2.1 Seata术语&实现原理TC (Transaction Coordinator) - 事务协调者 它是独立的中间件,需要独立部署运行,它维护全局事务的运行状态,接收TM指令发起全局事务的提交与回滚, 负责与RM通信协调各各分支事务的提交或回滚。 TM (Transaction Manager) - 事务管理器 - 事务发起者 TM需要嵌入应用程序中工作,它负责开启一个全局事务,并最终向TC发起全局提交或全局回滚的指令。 RM (Resource Manager) - 资源管理器 - 事务参与者 控制分支事务,负责分支注册、状态汇报,并接收事务协调器TC的指令,驱动分支(本地)事务的提交和回滚。2.2 AT模式 工作机制
首先:AT模式是由2PC演变而来,在2PC的基础上增加了数据镜像(undolog表)的功能来实现分布式事务的回滚。
流程:TM要求TC开始一项新的事务分支。TC生成代表全局事务的XID返回给TM。 TM请求其它服务时携带XID参数通过微服务的调用链传播。 RM将本地事务注册为XID到TC的相应全局事务的分支。 TM要求TC提交或回滚XID的相应全局事务。 TC驱动XID对应的全局事务下的所有分支事务以完成分支提交或回滚。 如果需要回滚的话,需要用到"undolog回滚日志"表进行回滚操作。2.3 undolog回滚日志表详解(前置、后置镜像)
案例:
1、user业务表CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into user values(1, "王明", 19); insert into user values(1, "王亮", 10);
2、执行业务SQL:update user set age = 20 where name = "王明";
3、Seata会拦截该业务SQL,对该SQL添加前置镜像、后置镜像并将前置、后置镜像得到的数据记录到undolog表中:
前置镜像:业务SQL修改之前的数据;
后置镜像:业务SQL修改之后的数据。前置镜像:select id, name, age from user where name = "王明"; 业务SQL:update user set age = 20 where name = "王明"; 后置镜像:select id, name, age from user where id = #{前置镜像得到的主键id};
前置镜像的到的数据:
后置镜像得到的数据:
4、如果执行回滚操作,则根据XID读取undolog表中的前置镜像和业务SQL信息,并生成回滚SQL语句执行:生成的回滚SQL语句:update user set age = 19 where id = 1;
5、如果执行提交,则直接把undolog表中,相关镜像删除即可。3 Seata环境搭建3.1 Seata服务器搭建
本次实践为seata最新版本为v1.5.1 ,
下载地址 http://seata.io/zh-cn/blog/download.html, 下载下来进行解压,目录结构如下:
3.1.1 Seata简单安装 - 单机
进入bin目录直接启动seata ,
seata服务默认端口是8091、客户端端口7091
window下双击运行seata-server.bat
linux下运行seata-server.sh
输出以下信息表示启动成功,默认Seata服务端口8091
4.1.1 seata高可用安装 - 集成Nacos、DB
Seata服务端支持三种存储模式(store.mode):file:单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高 db:高可用模式,全局事务会话信息通过db共享,相应性能差些 redis:Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置适合当前场景的redis持久化配置4.1.2 创建Seata依赖的数据库实例
新建一个seata数据库实例,然后导入以下SQL,或者导入学习资料中提供的seata.sql。
注意:seata数据库字符集需要是utf8mb4 -- UTF-8 Unicode SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for branch_table -- ---------------------------- DROP TABLE IF EXISTS `branch_table`; 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; -- ---------------------------- -- Records of branch_table -- ---------------------------- -- ---------------------------- -- Table structure for distributed_lock -- ---------------------------- DROP TABLE IF EXISTS `distributed_lock`; CREATE TABLE `distributed_lock` ( `lock_key` char(20) NOT NULL, `lock_value` varchar(20) NOT NULL, `expire` bigint(20) DEFAULT NULL, PRIMARY KEY (`lock_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of distributed_lock -- ---------------------------- INSERT INTO `distributed_lock` VALUES ("AsyncCommitting", " ", "0"); INSERT INTO `distributed_lock` VALUES ("RetryCommitting", " ", "0"); INSERT INTO `distributed_lock` VALUES ("RetryRollbacking", " ", "0"); INSERT INTO `distributed_lock` VALUES ("TxTimeoutCheck", " ", "0"); -- ---------------------------- -- Table structure for global_table -- ---------------------------- DROP TABLE IF EXISTS `global_table`; CREATE TABLE `global_table` ( `xid` varchar(128) NOT NULL, `transaction_id` bigint(20) DEFAULT NULL, `status` tinyint(4) NOT NULL, `application_id` varchar(32) DEFAULT NULL, `transaction_service_group` varchar(32) DEFAULT NULL, `transaction_name` varchar(128) DEFAULT NULL, `timeout` int(11) DEFAULT NULL, `begin_time` bigint(20) DEFAULT NULL, `application_data` varchar(2000) DEFAULT NULL, `gmt_create` datetime DEFAULT NULL, `gmt_modified` datetime DEFAULT NULL, PRIMARY KEY (`xid`), KEY `idx_status_gmt_modified` (`status`,`gmt_modified`), KEY `idx_transaction_id` (`transaction_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of global_table -- ---------------------------- -- ---------------------------- -- Table structure for lock_table -- ---------------------------- DROP TABLE IF EXISTS `lock_table`; CREATE TABLE `lock_table` ( `row_key` varchar(128) NOT NULL, `xid` varchar(128) DEFAULT NULL, `transaction_id` bigint(20) DEFAULT NULL, `branch_id` bigint(20) NOT NULL, `resource_id` varchar(256) DEFAULT NULL, `table_name` varchar(32) DEFAULT NULL, `pk` varchar(36) DEFAULT NULL, `status` tinyint(4) NOT NULL DEFAULT "0" COMMENT "0:locked ,1:rollbacking", `gmt_create` datetime DEFAULT NULL, `gmt_modified` datetime DEFAULT NULL, PRIMARY KEY (`row_key`), KEY `idx_status` (`status`), KEY `idx_branch_id` (`branch_id`), KEY `idx_xid_and_branch_id` (`xid`,`branch_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;4.1.2 启动nacos
可以使用资料中的nacos-2.4.5.jar 文件,通过java -jar nacos-2.4.5.jar的方式启动nacos服务,启动nacos前需要修改数据源地址。
学习资料中提供了nacos依赖的数据库SQL文件:nacos.sql
资料下载地址: https://pan.baidu.com/s/16YFbXeRpOzNWIO_jhyH0-g?pwd=1bvd 4.1.3 在nacos配置中心添加Seata配置seataServer.properties
Data ID: seataServer.properties
Group: SEATA_GROUP
添加 seataServer.properties 内容,需要自行修改seata数据库连接。service.vgroupMapping.default-tx-group=default service.default.grouplist=127.0.0.1:8091 service.enableDegrade=false service.disableGlobalTransaction=false store.mode=db store.db.datasource=druid store.db.dbType=mysql store.db.driverClassName=com.mysql.jdbc.Driver store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true store.db.user=root store.db.password=root store.db.minConn=5 store.db.maxConn=30 store.db.globalTable=global_table store.db.branchTable=branch_table store.db.queryLimit=100 store.db.lockTable=lock_table store.db.maxWait=50004.1.4 修改Seata配置文件application.yml
修改seata-server-1.5.1seataconfapplication.yml配置文件 ,修改config、registry的type值为nacos
注意:如果使用了Nacos作为配置中心,那么就不需要在该配置文件中配置store,Seata会从Nacos配置中心读取。server: port: 7091 spring: application: name: seata-server 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 password: seata seata: config: # support: nacos, consul, apollo, zk, etcd3 type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: group: SEATA_GROUP username: nacos password: nacos ##if use MSE Nacos with auth, mutex with username/password attribute #access-key: "" #secret-key: "" data-id: seataServer.properties registry: # support: nacos, eureka, redis, zk, consul, etcd3, sofa type: nacos nacos: application: seata-server server-addr: 127.0.0.1:8848 group: SEATA_GROUP namespace: cluster: default username: nacos password: nacos # store: # support: file 、 db 、 redis # mode: db # db: # datasource: druid # db-type: mysql # driver-class-name: com.mysql.jdbc.Driver # url: jdbc:mysql://${MY_MYSQL_URL}/seata?rewriteBatchedStatements=true # user: ${MY_MYSQL_USERNAME} # password: ${MY_MYSQL_PASSWORD} # min-conn: 5 # max-conn: 100 # global-table: global_table # branch-table: branch_table # lock-table: lock_table # distributed-lock-table: distributed_lock # query-limit: 100 # max-wait: 5000 # 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/login4.1.5 启动Seata服务
进入bin目录启动Seata , Seata服务默认端口是8091、客户端端口7091
window下双击运行seata-server.bat
linux下运行seata-server.sh 5.1 Seata客户端搭建5.1.1 在业务数据库中需要加入undo_log表CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `branch_id` bigint(20) NOT NULL, `xid` varchar(100) NOT NULL, `context` varchar(128) NOT NULL, `rollback_info` longblob NOT NULL, `log_status` int(11) NOT NULL, `log_created` datetime NOT NULL, `log_modified` datetime NOT NULL, `ext` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;5.1.2 Seata依赖 com.alibaba.cloud spring-cloud-starter-alibaba-seata 2.2.3.RELEASE 5.1.3 application.yml配置server: port: 8080 spring: application: name: kexuekt-mamber datasource: url: jdbc:mysql://${MY_MYSQL_URL}/mamber?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT username: ${MY_MYSQL_USERNAME} password: ${MY_MYSQL_PASSWORD} driver-class-name: com.mysql.jdbc.Driver seata: enabled: true enable-auto-data-source-proxy: true tx-service-group: default-tx-group service: vgroup-mapping: default-tx-group: default disable-global-transaction: false client: rm: report-success-enable: false
注意:
5.1.4 使用时在TM发起方的方法上添加注解@GlobalTransactional,即可。
自媒体的乱象,中国足球的悲哀这两天在头条想写一些关于足球的东西,分享下自己对足球的浅显见解。当我接触到自媒体后,才越发理解自媒体上的乱象。自媒体的收益离不开的就是流量。有时候挺羡慕那些引战的自媒体号,随便抛出
跳台滑雪大跳台日本新星无缘第二金,我国选手宋祺武止步资格赛北京时间2月12日消息,北京冬奥会跳台滑雪结束男子个人大跳台决赛争夺,挪威选手林德维克发挥出色,以总成绩296。1分夺得金牌,日本选手小林陵侑以292。8分获得银牌,无缘个人第二金
深圳队官方公告李章洙出任主教练北京时间2月12日,深圳队官方宣布李章洙出任主教练!公告写道为持续提升球队战斗力,深圳市足球俱乐部经与市相关部门股东及战略合作伙伴讨论商议决定,即日起聘请李章洙(LeeJangso
连扳两球险些逆转,中国男冰2比3惜败给世界第5,遭遇2连败北京时间2月12日,2022年北京冬奥会男子冰球继续进行小组赛,中国队遭遇2连败。面对世界排名第5的德国队,中国队虽然先丢三球,但他们打得非常顽强,连扳两球以2比3惜败给对手。这一
冬奥最新金牌榜美国4金排第6,中国再添1铜排第7,韩国第162022年北京冬奥会进入第8个比赛日,并将在单板滑雪越野滑雪速度滑冰冬季两项跳台滑雪钢架雪车等项目决出6枚金牌,精彩正在不断上演,一起领略冬奥的魅力。其中,中国队旗手高亭宇将向速度
赵心童第7!斯诺克排名范争一狂飙49位升至第31丁俊晖第332021年斯诺克欧洲大师赛战罢,新的世界排名,范争一夺冠后攀升49个名次,从第80位升至第31位。塞尔比奥沙利文和特鲁姆普排名前三,赵心童位列第七,颜丙涛排名第13,丁俊晖跌至第3
喝红茶很久,却没买到过正宗的金骏眉?或许你该反思这3件事丨本文由小陈茶事原创丨首发于头条号小陈茶事丨作者村姑陈1过完情人节,过完元宵节,年就正式过完了。今年正式开始了。以前每年元旦村姑陈都会立个flag,无外乎几大项读书,写作,减肥,旅
酱牛肉怎么做好吃?酱牛肉想必是我们家常非常常见的一道凉菜,平时的宴席,过年过节餐桌上必不可少的一道凉菜!一般居家会做酱牛肉的不多,今天就分享给大家将怎么样才能做出,咸淡适中酱香浓郁的酱牛肉!酱牛肉一
古村寨,我们该如何走近它?越来越多的人从喧嚣繁华的大都市走入海滨,又从城镇走进农村,现在,又从农村走入了古村寨。古村不同于寻常农村,它因建筑年代久远,且具有历史文化科学艺术乃至极高的经济价值。随着旅游资源的
6张图,让你明白一生人活一世草木一秋,哭着降临人世,在亲人的泪眼中离开,在转瞬即逝的流年中,有辛酸,有无奈,有苦累,有幸福,冷暖自知。相遇,相识,相知,相随,一生相伴,然后相濡以沫到白头,接着一人先离
孩子该不该报兴趣班?前提是,你不要被教育焦虑传染文全文共1933字,阅读时间约3分钟看到一位粉丝的留言,她说我儿子今年4岁,身边的很多小朋友都报了兴趣班。我担心儿子会落后,没有才艺,也是也给他报了几个兴趣班。希望他能够在这些兴趣
北京徒步登山寻迹山间冰溪冰瀑自然美景,门头沟西胡林自驾游出行日期2022年1月5日,周三先上总结门票无停车免费位置北京门头沟斋堂镇西胡林村导航东胡林人遗址总里程17公里左右(环线)累计爬升430米左右用时6小时左右(正常比我们快)路况穿
黄金城道上有家昆虫酒店,蝴蝶在前台迎宾在喧嚣的城市里静静聆听昆虫鸟鸣,观察昆虫习性,甚至是领一袋种子回家种植,这一切在古北黄金城道变成了现实。黄金城道最新微更新项目街区自然研习小径,让社区居民在家门口就能拥抱大自然。观
领略巴马的风情后,你悟出了怎样的养生之道?一条盘阳河,宛若天仙少女撒落到人间的碧色长袖,穿梭在错落的村屯间,绮丽的溶洞中,奇骏的峰峦下,她就是巴马的母亲河。这里特殊的喀斯特地形,生成了享誉世界的天然矿泉水,这种被地磁化了的
市区近郊大片金灿灿菜心花盛开,成为一道冬日美景最近天气晴好,不少市民都趁着好天气出门游玩,在大塘镇有一处菜心花正在悄然绽放,田园上金灿灿一片,让人心旷神怡,成为一道冬日美景。在大塘镇黄仕头村,有一片菜心花田,放眼望去,一片金黄
传世元神手游你最熟悉的铁血版本,元神无战力无VIP打金攻略大家好今天小编来和大家说一说传世怀旧服,一直有人心心念念的铁血版本啊,他终于来了,而且也是带元神的。人气很高。最受关注的一个问题当然就是能不能打金了,答案当然是可以的,那么今天就来
伊涅斯塔官宣代言足球手游最佳11人玩家直呼圆梦了继费尔南多托雷斯之后,国产策略足球手游最佳11人官方再爆重磅全球代言人。近日,前巴萨巨星安德烈斯伊涅斯塔(AndrsIniesta)通过最佳11人手游官方公众号宣布我将成为最佳11
射击游戏超级人类新手快速入门技巧分享超级人类新手怎么玩?很多小伙伴刚入坑超级人类的时候不知道怎么玩,里面的一些枪械和系统不知道有什么用,今天为大家带来了超级人类新手游玩技巧,一起来看看吧。超级人类新手游玩技巧分享一个
新疆拌面,新疆人百吃不厌的家常主食新疆拌面,俗称拉条子,因其制作的时候以菜拌面而得名成新疆拌面。是包括新疆以及西北各省各族群众都喜欢的一种面食,深受当地人民喜爱。拌面与抓饭是众多新疆人的主食,如同南方人喜欢米饭一样
安吉绝美徒步道在这里安吉这个江浙沪人民度假的后花园,拥有竹林云海群山等景致,卧虎藏龙绣春刀等影视作品都被它独特的自然风光吸引,前来取景,悦榕庄JW万豪等品牌酒店也纷纷扎堆。安吉既能让你赏景又能避开游人
文化名山莫过于三山五岳,五岳分居全国,但每个省都有自己的三山中国是世界上数一数二的多山国家,山地和丘陵地貌占了全部领土的近乎一半。这些数不清的山也分三六九等,但要说到文化名山,非五岳三山莫属。五岳分居东西南北中,三山(黄山庐山和雁荡山)则在
球迷怒斥我不在乎失利,但是起码输得有尊严,至少有去争取欢迎各位阅读本期的快船Jrs之声!人手短缺的快船主场迎来了缺兵少将的灰熊,但是遗憾的是他们没能捍卫主场,108123大比分输给了对手,惨遭三连败。外国的快船球迷为球队糟糕的表现感到