seata安装配置
下载
下载中心 | Seata
上传到linux
解压seata压缩包
tar -zxvf seata-server-1.6.1.tar.gz
nacos配置
创建seata的命名空间
id: seata-id
配置seata
备份application.yml
进入/usr/local/software/springcloud/seata/conf文件夹
备份application.yml
mv application.yml application.yml.bak
修改application.example.yml为application.yml
mv application.example.yml application.yml
修改application.yml
添加seata.security模块
seata:#新添加内容,不加会报错security:secretKey: "securityKey"tokenValidityInMilliseconds: 1000000000
配置seata.config模块
37 config: 38 # support: nacos 、 consul 、 apollo 、 zk 、 etcd339 type: nacos40 nacos:41 server-addr: 192.168.198.128:777742 namespace: seata-id43 group: SEATA_GROUP44 username:45 password:46 context-path:47 ##if use MSE Nacos with auth, mutex with username/password attribute48 #access-key:49 #secret-key:50 data-id: seataServer.properties
配置seata.registry模块
72 registry:73 # support: nacos 、 eureka 、 redis 、 zk 、 consul 、 etcd3 、 sofa74 type: nacos75 # preferred-networks: 30.240.*76 nacos:77 application: seata-server78 server-addr: 192.168.198.128:777779 group: SEATA_GROUP80 namespace: seata-id81 cluster: default82 username:83 password:84 context-path:85 ##if use MSE Nacos with auth, mutex with username/password attribute86 #access-key:87 #secret-key:
配置seata.store模块
使用redis存储
redis:mode: singledatabase: 1min-conn: 10max-conn: 100password:max-total: 100query-limit: 1000single:host: 192.168.198.128port: 6379sentinel:master-name:sentinel-hosts:
添加console模块
新版本中如果不添加此项会报错。
32 console:33 user:34 username: seata35 password: 123
修改批处理文件
进入/usr/local/software/springcloud/seata/script/config-center/nacos, 修改nacos-config.sh文件
53 if [ -z ${tenant} ]; then54 tenant="seata-id"55 fi
启动脚本:
sh nacos-config.sh -h nacos服务器地址
sh nacos-config.sh -h 192.168.198.128
启动seata服务
进入/usr/local/software/springcloud/seata/bin文件夹
-rwxr-xr-x. 1 502 games 3779 12月 16 2022 seata-server.bat
-rwxr-xr-x. 1 502 games 5795 12月 16 2022 seata-server.sh
-rwxr-xr-x. 1 502 games 0 6月 28 2022 startup.sh
[root@localhost bin]# pwd
/usr/local/software/springcloud/seata/bin
./seata-server.sh
[root@localhost bin]# ./seata-server.sh
apm-skywalking not enabled
seata-server is starting, you can check the /usr/local/software/springcloud/seata/logs/start.out
[root@localhost bin]#
springcloud整合seata
数据库设计
创建undo表,放入要执行分布式事务的数据库
CREATE TABLE `undo_log` (`branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',`xid` varchar(128) NOT NULL COMMENT 'global transaction id',`context` varchar(128) NOT NULL COMMENT 'undo_log context,such as serialization',`rollback_info` longblob NOT NULL COMMENT 'rollback info',`log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',`log_created` datetime(6) NOT NULL COMMENT 'create datetime',`log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AT transaction mode undo table';
引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-all</artifactId></exclusion><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.6.1</version></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.6.1</version></dependency>
bootstrap.yml配置文件
seata:enabled: truetx-service-group: default_tx_groupservice:vgroup-mapping:default_tx_group: defaultgrouplist:default: 192.168.198.128:8091
#已经在nacos中配置了,不需要再次配置
# config:
# nacos:
# server-addr: ${spring.cloud.nacos.config.server-addr}
# namespace: seat-id
# group: SEATA_GROUP
# registry:
# nacos:
# application: seata-service
# server-addr: ${spring.cloud.nacos.config.server-addr}
# namespace: seat-id
# group: SEATA_GROUP
订单模块
订单模块添加分布式事务
启动订单模块
主从TM
2023-12-10 23:24:28.728 INFO 13176 --- [ main] i.s.core.rpc.netty.NettyPoolableFactory : NettyPool create channel to transactionRole:TMROLE,address:192.168.198.128:8091,msg:< RegisterTMRequest{applicationId='ssc-cloud-order', transactionServiceGroup='default_tx_group'} >
初始化资源管理(RM)
发起事务请求
使用@GlobalTransactional
package com.wnhz.ssc.cloud.order.service.impl;import cn.hutool.core.lang.Snowflake;
import com.wnhz.ssc.cloud.order.IOrderDao;
import com.wnhz.ssc.cloud.order.service.IOrderService;
import com.wnhz.ssc.cloud.store.feign.IStoreFeign;
import com.wnhz.ssc.domain.entity.po.Order;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;@Slf4j
@Service
public class OrderServiceImpl implements IOrderService {@Autowiredprivate IOrderDao orderDao;@Autowiredprivate IStoreFeign storeFeign;@GlobalTransactional@Overridepublic Long createOrder(long productId, int num) {Order order = new Order();order.setProduct(productId);order.setQuantity(num);order.setCreateBy("test");order.setCreateTime(new Date());order.setUpdateTime(new Date());log.debug("创建order对象成功:{},准备存入数据库....", order);orderDao.insert(order);log.debug("订单对象存入数据库成功,准备扣库存....");storeFeign.decreaseStore(productId, num);log.debug("库存更成功,商品号:{},扣库存:{}个", productId,num);long orderId = new Snowflake().nextId();order.setOrderNum(orderId);orderDao.updateById(order);log.debug("订单号更新完成:{}", orderId);return orderId;}
}
Begin new global transaction [172.18.1.1:8091:8269074957769797653]
:
:
rm handle branch rollback process:xid=172.18.1.1:8091:8269074957769797653,branchId=8269074957769797654,branchType=AT,resourceId=jdbc:mysql://192.168.198.128:3306/ssc_db,applicationData={"skipCheckLock":true}
Branch Rollbacking: 172.18.1.1:8091:8269074957769797653 8269074957769797654 jdbc:mysql://192.168.198.128:3306/ssc_db
Branch Rollbacked result: PhaseTwo_Rollbacked
Suspending current transaction, xid = 172.18.1.1:8091:8269074957769797653
[172.18.1.1:8091:8269074957769797653] rollback status: Rollbacked
[172.18.1.1:8091:8269074957769797653] rollback status: Finished
自定义异常捕获
由于分布式调用返回的异常可能为OpenFeign的异常,分布式事务异常捕获失败。
定义切面捕获分布式 事务异常
package com.wnhz.ssc.cloud.order.aop;import io.seata.core.context.RootContext;
import io.seata.core.exception.TransactionException;
import io.seata.tm.api.GlobalTransactionContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;@Aspect
@Component
@Slf4j
public class SeataExceptionAop {@Pointcut("@annotation(io.seata.spring.annotation.GlobalTransactional)")public void transactionPointCut(){}@AfterThrowing(throwing = "e",pointcut = "transactionPointCut()")public void globalTransactionalExceiton(Throwable e) throws TransactionException {log.debug("分布式事务异常:{}", e.getMessage());String xid = RootContext.getXID();if(StringUtils.hasText(xid)){log.debug("XID:{}执行回滚操作", xid);GlobalTransactionContext.reload(xid).rollback();log.debug("事务:{}回滚完成", xid);throw new TransactionException("事务处理失败,回滚完成........");}}
}