咖啡厅网站开发目标,济南网约车平台,购物商城名字,装修123网一、介绍#xff1a;
Seata是阿里巴巴旗下的产品#xff0c;是一款开源的分布式事务解决方案#xff0c;旨在解决分布式事务问题。
我们有必要先了解一下分布式事务#xff1a;
在微服务体系中#xff0c;每一个模块都有连接一个数据库#xff0c;这一点与单体项目是不…一、介绍
Seata是阿里巴巴旗下的产品是一款开源的分布式事务解决方案旨在解决分布式事务问题。
我们有必要先了解一下分布式事务
在微服务体系中每一个模块都有连接一个数据库这一点与单体项目是不同的单体项目就连接一个数据库。
那么如果有多个模块之间相互调用怎样保证各个模块之间的事务一致性由此引出了分布式事务。
在同一个数据库中我们要保证事物的一致性是很简单的。因为MySQL是基于单机事物的所以一旦遇到跨库的场景那么MySQL数据库就无能为力了。在这种情景下seata蕴育而生。
二、Seata的下载和启动
seata的官网Apache Seata
seata的下载地址
https://github.com/apache/incubator-seata/releases/download/v2.0.0/seata-server-2.0.0.zip 有三个概念要先了解 TC是事务协调器就是Seata本身负责管理全局事务的执行过程。它生成全局唯一的事务ID并协调各个分支事务的提交或回滚以确保数据的一致性。有且仅有一个 TM是事务管理器标注全局GlobalTransactional启动入口动作的微服务模块负责发起全局事务的提交或回滚请求并与TC交互以执行相应操作。它与业务逻辑代码交互触发分支事务的执行并根据TC的指示来决定全局事务的最终状。有且仅有一个 .RM是资源管理器各个模块的MySQL数据库本身负责管理分支事务的资源如数据库、消息队列、缓存等。它接收TC的指令并执行相应的事务操作以确保分支事务的一致性。可以有多个
总的来说TC负责全局事务的协调和管理TM负责全局事务的发起和控制RM负责具体资源的管理和事务操作。它们共同协作实现了Seata分布式事务框架的核心功能确保分布式系统中事务的一致性和可靠性。
下载完seata之后要使用seata要现在本地的MySQL数据库中新建一个数据库seata来记录seata在运行过程中的信息
CREATE DATABASE seata;USE seata;
sql脚本
create table branch_table
(branch_id bigint not nullprimary key,xid varchar(128) not null,transaction_id bigint null,resource_group_id varchar(32) null,resource_id varchar(256) null,branch_type varchar(8) null,status tinyint null,client_id varchar(64) null,application_data varchar(2000) null,gmt_create datetime(6) null,gmt_modified datetime(6) null
);create index idx_xidon branch_table (xid);create table distributed_lock
(lock_key char(20) not nullprimary key,lock_value varchar(20) not null,expire bigint null
);INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES (AsyncCommitting, , 0);
INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES (RetryCommitting, , 0);
INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES (RetryRollbacking, , 0);
INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES (TxTimeoutCheck, , 0);create table global_table
(xid varchar(128) not nullprimary key,transaction_id bigint null,status tinyint not null,application_id varchar(32) null,transaction_service_group varchar(32) null,transaction_name varchar(128) null,timeout int null,begin_time bigint null,application_data varchar(2000) null,gmt_create datetime null,gmt_modified datetime null
);create index idx_status_gmt_modifiedon global_table (status, gmt_modified);create index idx_transaction_idon global_table (transaction_id);create table lock_table
(row_key varchar(128) not nullprimary key,xid varchar(128) null,transaction_id bigint null,branch_id bigint not null,resource_id varchar(256) null,table_name varchar(32) null,pk varchar(36) null,status tinyint default 0 not null comment 0:locked ,1:rollbacking,gmt_create datetime null,gmt_modified datetime null
);create index idx_branch_idon lock_table (branch_id);create index idx_statuson lock_table (status);create index idx_xidon lock_table (xid);
创建好库和表之后更改seata的内容来启动seata 在seata的conf文件夹下更改application.yml文件启动seata # Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the License);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${log.home:${user.home}/logs/seata}extend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: seatapassword: seata
seata:
# 配置方式nacosconfig:type: nacos# support: nacos, consul, apollo, zk, etcd3nacos:server-addr: localhost:8848namespace:group: SEATA_GROUPusername: nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:data-id: seataServer.properties
# 注册方式 nacosregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacos# preferred-networks: 30.240.*nacos:application: seata-serverserver-addr: localhost:8848group: SEATA_GROUPnamespace:cluster: defaultusername: nacospassword: nacos
# 存储方式 db mysqlstore:mode: db# support: file 、 db 、 redis 、 raftdb:datasource: druiddb-type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db2024?characterEncodingutf-8useSSLfalseserverTimezoneGMT%2B8rewriteBatchedStatementstrueallowPublicKeyRetrievaltrueuser: rootpassword: 123456min-conn: 10max-conn: 100global-table: global_tablebranch-table: branch_tablelock-table: lock_tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000# server:# service-port: 8091 #If not configured, the default is ${server.port} 1000security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/**
根据你nacos、MySQL表的信息进行相应的更改
先启动nacos、再启动seataseata的启动在bin下的seata-server.bat
可以看到seata已经作为一个模块注册进了nacos中 访问7091端口可以看到seata的图形化界面用户名和密码都是seata 三、Seata测试DemoAT模式 业务说明订单服务→库存服务→支付服务下订单 ---减库存----扣余额----修改订单状态
maven依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactId
/dependency
配置文件applicationseata相关:
seata:registry:type: nacosnacos:server-addr: localhost:8848namespace: group: SEATA_GROUPapplication: seata-servertx-service-group: default_tx_group #事务组由他获得TC服务的集群名称service:vgroup-mapping: #源码默认名字 default_tx_group defaultdefault_tx_group: default #事务组与TC服务集群的映射关系data-source-proxy-mode: AT #默认是AT 如果是AT可不写logging:level:io:seata: info主要业务方法
其中int i 10/0;用于测试异常情况
OverrideGlobalTransactional(name create-order-transaction, rollbackFor Exception.class)public void create(Order order) {// xid全局事务检查String xid RootContext.getXID();// 1. 新建订单log.info(------------- 开始新建订单, XID: {}, xid);order.setStatus(0);int result orderMapper.insertSelective(order);Order orderFromDB;if (result 0) {orderFromDB orderMapper.selectOne(order);log.info(------------- 新建订单成功, OrderInfo: {}, orderFromDB);// 2. 扣减库存log.info(------------- 开始扣减库存);storageFeignApi.decrease(orderFromDB.getProductId(), orderFromDB.getCount());log.info(------------- 扣减库存成功);// 3. 扣减账户余额log.info(------------- 开始扣减余额);accountFeignApi.decrease(order.getUserId(), order.getMoney());log.info(------------- 扣余额存成功);int i 10/0;// 4. 修改订单状态log.info(------------- 开始修改订单状态);Example whereCondition new Example(Order.class);Example.Criteria criteria whereCondition.createCriteria();criteria.andEqualTo(id, orderFromDB.getId());criteria.andEqualTo(status, 0);orderFromDB.setStatus(1);int updateResult orderMapper.updateByExampleSelective(orderFromDB, whereCondition);log.info(------------- 修改订单状态成功);}log.info(------------- 结束新建订单, XID: {}, xid);}
调用接口前三个数据库三张表以及对应数据库undo_log表如下 执行过程中(断点在异常语句处)数据库及seata控制台 执行完成 结果可以看到在过程中记录添加进数据库并进行了相关记录异常后进行了回滚。 四、总结
我们之前的步骤都是建立在seata的AT模式上
AT 模式是 Seata 创新的一种非侵入式的分布式事务解决方案Seata 在内部做了对数据库操作的代理层我们使用 Seata AT 模式时实际上用的是 Seata 自带的数据源代理 DataSourceProxySeata 在这层代理中加入了很多逻辑比如插入回滚 undo_log 日志检查全局锁等。
整体机制
两阶段提交协议的演变
一阶段业务数据和回滚日志记录在同一个本地事务中提交释放本地锁和连接资源。二阶段 提交异步化非常快速地完成。回滚通过一阶段的回滚日志进行反向补偿。
在一阶段Seata 会拦截“业务 SQL”
1 解析 SQL 语义找到“业务 SQL”要更新的业务数据在业务数据被更新前将其保存成“before image”
2 执行“业务 SQL”更新业务数据在业务数据更新之后
3 其保存成“after image”最后生成行锁。
以上操作全部在一个数据库事务内完成这样保证了一阶段操作的原子性。 二阶段分为两种情况
1、正常提交
二阶段如是顺利提交的话
因为“业务 SQL”在一阶段已经提交至数据库所以Seata框架只需将一阶段保存的快照数据和行锁删掉完成数据清理即可。 2、异常回滚
二阶段如果是回滚的话Seata 就需要回滚一阶段已经执行的“业务 SQL”还原业务数据。
回滚方式便是用“before image”还原业务数据但在还原前要首先要校验脏写对比“数据库当前业务数据”和 “after image”
如果两份数据完全一致就说明没有脏写可以还原业务数据如果不一致就说明有脏写出现脏写就需要转人工处理。