SpringCloud Alibaba学习(四)——seata

Seata是一款开源的分布式解决方案,提供高性能和简单易用的额分布式事务服务。提供了AT、TCC、SAGA和XA事务模式

Seata事务管理中三个重要的角色:

1.TC(Transaction Coordinate)-事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚

2.TM(Transition Manager)-事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务

3.RM(Resource Manager)-资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚

 

Seata提供四种不同的分布式事务解决方案:

XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入

TCC模式:最终一致的分阶段事务模式,有业务侵入

AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式

SAGA模式:长事务模式,有业务侵入 

 解压Seata,修改registry.conf配置文件

1.选择自己要使用的配置中心(nacos)全部替换成nacos;

2.修改file.conf(存储模式)

Server的存储模式(mode)支持三种:

  1. file:(默认)单击模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
  2. db:高可用模式,全局事务会话信息通过db共享,相应性能差些
  3. Redis:Seata-server1.3以及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置合适当前场景的redis持久化配置资源目录

 在数据库中创建数据库seata,,创建数据库表

CREATE TABLE `branch_table` (
  `branch_id` bigint NOT NULL,
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint DEFAULT NULL,
  `resource_group_id` varchar(32) DEFAULT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `branch_type` varchar(8) DEFAULT NULL,
  `status` tinyint 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 COLLATE=utf8mb4_0900_ai_ci

CREATE TABLE `distributed_lock` (
  `lock_key` char(20) NOT NULL,
  `lock_value` varchar(20) NOT NULL,
  `expire` bigint DEFAULT NULL,
  PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

CREATE TABLE `global_table` (
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint DEFAULT NULL,
  `status` tinyint NOT NULL,
  `application_id` varchar(32) DEFAULT NULL,
  `transaction_service_group` varchar(32) DEFAULT NULL,
  `transaction_name` varchar(128) DEFAULT NULL,
  `timeout` int DEFAULT NULL,
  `begin_time` bigint 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 COLLATE=utf8mb4_0900_ai_ci

CREATE TABLE `lock_table` (
  `row_key` varchar(128) NOT NULL,
  `xid` varchar(128) DEFAULT NULL,
  `transaction_id` bigint DEFAULT NULL,
  `branch_id` bigint NOT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `table_name` varchar(32) DEFAULT NULL,
  `pk` varchar(36) DEFAULT NULL,
  `status` tinyint 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` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

 修改script-config-center文件中的config.txt,同样将存储模式改为db,修改具体信息;配置自己分组service.vgroup_mapping.my_test_tx_group=default改为service.vgroup_mapping.自己=default

将配置文件配置到nacos,使用git

 

 

 即配置成功!

下面进行模拟分布式事务:分别创建两个数据库(假设)-order订单数据库-money支付表数据库,即对应的订单表和支付表。分别创建两个项目:支付和订单

模拟之前一定要在两个数据库中加入undo_log表

CREATE TABLE `undo_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `branch_id` bigint NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int 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=3 DEFAULT CHARSET=utf8mb3

支付模块

server.port=8803
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url= jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username= root
spring.datasource.password= 123456
mybatis.configuration.map-underscore-to-camel-case= true

spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.application.name=money
spring.cloud.alibaba.seata.tx-service-group=guangzhou

#配置seata的注册中心,告诉seata client 怎么去访问seata servellr
seata.registry.type=nacos
#可不配服务名
seata.registry.nacos.application=seata-server
seata.registry.nacos.server-addr= localhost:8848
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos
#seata server所在的分组,默认就是这个,没有可以不配
seata.registry.nacos.group=SEATA_GROUP

#配置seata的配置中心,
seata.config.type=nacos
seata.config.nacos.server-addr=localhost:8848
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos
@Mapper
@Repository
public interface MoneyMapper {
    public int subMoney();
}
@Service
public class MoneyService {
    @Resource
    private MoneyMapper moneyMapper;
    public void subMoney(){
        moneyMapper.subMoney();
    }
}
@RestController
public class MoneyController {
    @Resource
    MoneyService moneyService;
    @RequestMapping("/money")
    public String money(){
        moneyService.subMoney();
        return "支付成功";
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.seatamoney.mapper.MoneyMapper">
    <update id="subMoney">
        update moneyTest set money=money-10 where id=1;
    </update>
</mapper>

订单模块

server.port=8180
provider.ribbon.NFLoadBalancerRuleClassName:com.example.consumer.configuration.NacosWeightedRule
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url= jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username= root
spring.datasource.password= 123456
mybatis.mapper-locations= classpath:com/example/consumer/mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case= true

spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.application.name=consumer
spring.cloud.alibaba.seata.tx-service-group=guangzhou


 #配置seata的注册中心,告诉seata client 怎么去访问seata server
seata.registry.type=nacos
 #可不配服务名
seata.registry.nacos.application=seat-server
seata.registry.nacos.server-addr= localhost:8848
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos
 #seata server所在的分组,默认就是这个,没有可以不配
seata.registry.nacos.group=SEATA_GROUP

#配置seata的配置中心,

seata.config.type=nacos
seata.config.nacos.server-addr=localhost:8848
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos

openFeign接口

@Component
@FeignClient(value = "money")
public interface MoneyFeign {
    @RequestMapping("/money")
    public String money();
}
@Repository
@Mapper
public interface OrderMapper {
    public int addOrder();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.consumer.mapper.OrderMapper">
  <update id="addOrder">
      update orders set num=num+1 where id=1;
  </update>
</mapper>
@Service
public class OrderService {
    @Resource
    private OrderMapper orderMapper;
    public void addOrder(){
        orderMapper.addOrder();
    }
}
@RestController
public class OrderController {
    @Resource
    OrderService orderService;
    @Resource
    MoneyFeign moneyFeign;
    @RequestMapping("/order")
    @GlobalTransactional
    public String Order(){
        moneyFeign.money();
        int i = 1/0;

        orderService.addOrder();
        return "下单成功";
    }
}
@SpringBootApplication
@EnableFeignClients
@MapperScan("com.example.consumer.mapper")
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

}

如果Controller不加@GlobalTransitional注解,最后支付表-10元,但是订单表不变;

加上分布式事务后,两表都不发生变化

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值