seata(分布式事务框架)在实际项目中的初体验

概述

项目框架:Spring Framwork(4.3.10.RELEASE) + Dubbo(2.5.6)+ Mybatis Plus(2.3.3)
数据库:Postgresql

涉及的项目模块分为:
app-webservice(对外提供接口)
base(存放通用类和配置文件)
content-server(主要的业务模块,游戏、加速相关业务逻辑)
log-server(日志分析)

模拟业务场景:用户使用加速器加速,加速服务器(VPN服务器)上报用户加速请求,并且上报自身的一些状态信息(单纯为了验证 Seata 接入是否正常,不要计较场景是否合理)。

步骤1:本地启动Seata,并初始化相关表结构

  1. 下载windows Seata 安装包,默认使用本地文件存储元数据和配置,直接启动即可
    在这里插入图片描述
  2. 每个数据库都需要初始化一张undo 表(比如在这次初体验中,用到了两个数据库:content 和 log,需要在每个数据库中都创建一张undo 表),表结构从官网下载即可,我使用的是postgresql,需要稍微修改下表结构:
CREATE TABLE "public"."undo_log" (
"id" SERIAL NOT NULL primary key,
"branch_id" int8 NOT NULL,
"xid" varchar(100) COLLATE "default" NOT NULL,
"context" varchar(128) COLLATE "default" NOT NULL,
"rollback_info" bytea NOT NULL,
"log_status" int4 NOT NULL,
"log_created" timestamp(6) NOT NULL,
"log_modified" timestamp(6) NOT NULL,
"ext" varchar(100) COLLATE "default" DEFAULT NULL::character varying,
CONSTRAINT "unq_idx_ul_branchId_xid" UNIQUE ("branch_id", "xid")
)
WITH (OIDS=FALSE)
;
ALTER TABLE "public"."undo_log" OWNER TO "postgres";

步骤2:Spring 整合 Seata,使用XML 配置文件方式

  1. base 项目引入Seata 所需配置文件,这两个配置文件从Seata 官方Demo 中获取即可,地址:seata demo

在这里插入图片描述

  1. Spring XML 配置整合Seata

在这里插入图片描述
右侧红框中是必须的,主要是让Seata 能扫描到哪些方法需要使用分布式事务,可以类比Spring-tx 是如何扫描@Transaction 注解的。

  1. Mybatis 配置文件整合 Seata

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上三个截图,总结来说,就是不管你DAO 层使用什么样的数据源,都需要让Seata 提供的数据源代理类来包装一下,然后以前注入的数据源都替换成Seata 提供的代理数据源。
简单来说是因为Seata 的代理数据源对原本的数据源做了增强,在执行原本的SQL 语句的事务中,一并插入Seata 提供的Undo log。

步骤3:测试分布式事务

  1. 相关代码
    在这里插入图片描述
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:applicationContext-*.xml", "classpath:dispatcher-servlet.xml"})
public class SeataTest {

    @Autowired
    private SeataSupport seataSupport;


    @Test
    public void testSeataTx() {
        seataSupport.setaTx();
    }
}

====================================================================================

import com.alibaba.dubbo.config.annotation.Reference;
import com.hanhua.base.api.content.BoosterServerOnlineService;
import com.hanhua.base.api.log.BoosterConnectLogService;
import com.hanhua.base.api.user.UserDayFreeSpeedTaskService;
import com.hanhua.base.model.content.BoosterServerOnline;
import com.hanhua.base.model.log.BoosterConnectLog;
import com.hanhua.base.model.user.UserDayFreeSpeedTask;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.util.Date;

@Component
public class SeataSupport {
    @Reference
    private BoosterServerOnlineService boosterServerOnlineService;
    @Reference
    private BoosterConnectLogService boosterConnectLogService;
    @Reference
    private UserDayFreeSpeedTaskService userDayFreeSpeedTaskService;

    @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")
    public void setaTx() {
        BoosterConnectLog connectLog = new BoosterConnectLog();
        connectLog.setUserId(123);
        connectLog.setServerId(9999);
        connectLog.setGameId(9999);
        connectLog.setStatus(1);
        connectLog.setCreateTime(new Date());
        boosterConnectLogService.save(connectLog);

//        UserDayFreeSpeedTask task = new UserDayFreeSpeedTask();
//        task.setUserId(9999L);
//        task.setDayFreeSpeedTaskId(1);
//        task.setCreateTime(new Timestamp(System.currentTimeMillis()));
//        userDayFreeSpeedTaskService.insert(task);
		
		# 数据库ID 9999 已经存在,这里插入会报错主存
        BoosterServerOnline online = new BoosterServerOnline();
        online.setId(9999);
        online.setWorking(1);
        online.setPersonCount(10);
        online.setContectedCount(online.getPersonCount());
        boosterServerOnlineService.insert(online);

    }
}

在该实验中,BoosterServerOnline 所在表的id 为9999 的记录已经存在,因此BoosterConnectLog 这条记录会被回滚。

遇到的坑(有遇到就记录)

1、Seata 使用fastjson 序列化,如果数据库字段是Timestamp类型,由于fastjson 序列化是导致精度丢失,在回滚的时候,会回滚失败

解决:不使用fastjson,使用默认的jackson 即可,因为jackson 考虑到了Timestamp 的精度问题
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值