当前位置: 代码网 > it编程>编程语言>Java > Seata之分布式事务问题及解决方案

Seata之分布式事务问题及解决方案

2025年03月13日 Java 我要评论
seata–分布式事务解决方案简介seata 是阿里开源的分布式事务解决方案,提供 at、xa、tcc、saga 四种事务模式,支持微服务架构下的数据一致性。官网:https://seat

seata–分布式事务解决方案

简介

seata 是阿里开源的分布式事务解决方案,提供 atxatccsaga 四种事务模式,支持微服务架构下的数据一致性。

官网:https://seata.apache.org/zh-cn/

同类产品对比

方案核心特点适用场景
seata多模式支持,代码侵入性低,社区活跃复杂业务场景,需灵活选择模式
阿里云 gts商业版方案,功能全面,性能强企业级付费场景
rocketmq 事务消息基于消息队列实现最终一致性异步高吞吐场景
lcn基于代理模式,实现简单轻量级快速接入

环境搭建

1.微服务

创建 spring cloud 项目,推荐使用以下组件:

<!-- spring cloud alibaba 依赖 -->
<dependency>
    <groupid>com.alibaba.cloud</groupid>
    <artifactid>spring-cloud-starter-alibaba-seata</artifactid>
</dependency>

2.sql

每个微服务数据库需创建 undo_log 表(at模式必需):

-- 每个业务数据库均需执行
create table if not exists `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,
    primary key (`id`),
    unique key `ux_undo_log` (`xid`, `branch_id`)
) engine = innodb
  auto_increment = 1
  default charset = utf8;

3.seata-server

  • 1.下载 :https://seata.apache.org/zh-cn/download/seata-server
  • 2.解压并启动:seata-server.bat
  • 3.控制台:http://127.0.0.1:7091/#/transaction/list

4.微服务配置

依赖

除基础依赖外需添加:

<dependency>
  <groupid>com.alibaba.cloud</groupid>
  <artifactid>spring-cloud-starter-alibaba-seata</artifactid>
</dependency>

配置

每个微服务创建 file.conf文件,完整内容如下;

【微服务只需要复制 service 块配置即可】

#
# licensed to the apache software foundation (asf) under one or more
# contributor license agreements.  see the notice file distributed with
# this work for additional information regarding copyright ownership.
# the asf licenses this file to you 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.
#

transport {
  # tcp, unix-domain-socket
  type = "tcp"
  #nio, native
  server = "nio"
  #enable heartbeat
  heartbeat = true
  # the tm client batch send request enable
  enabletmclientbatchsendrequest = false
  # the rm client batch send request enable
  enablermclientbatchsendrequest = true
   # the rm client rpc request timeout
  rpcrmrequesttimeout = 2000
  # the tm client rpc request timeout
  rpctmrequesttimeout = 30000
  # the rm client rpc request timeout
  rpcrmrequesttimeout = 15000
  #thread factory for netty
  threadfactory {
    bossthreadprefix = "nettyboss"
    workerthreadprefix = "nettyservernioworker"
    serverexecutorthread-prefix = "nettyserverbizhandler"
    sharebossworker = false
    clientselectorthreadprefix = "nettyclientselector"
    clientselectorthreadsize = 1
    clientworkerthreadprefix = "nettyclientworkerthread"
    # netty boss thread size
    bossthreadsize = 1
    #auto default pin or 8
    workerthreadsize = "default"
  }
  shutdown {
    # when destroy server, wait seconds
    wait = 3
  }
  serialization = "seata"
  compressor = "none"
}
service {
  #transaction service group mapping
  vgroupmapping.default_tx_group = "default"
  #only support when registry.type=file, please don't set multiple addresses
  default.grouplist = "127.0.0.1:8091"
  #degrade, current not support
  enabledegrade = false
  #disable seata
  disableglobaltransaction = false
}

client {
  rm {
    asynccommitbufferlimit = 10000
    lock {
      retryinterval = 10
      retrytimes = 30
      retrypolicybranchrollbackonconflict = true
    }
    reportretrycount = 5
    tablemetacheckenable = false
    tablemetacheckerinterval = 60000
    reportsuccessenable = false
    sagabranchregisterenable = false
    sagajsonparser = "fastjson"
    sagaretrypersistmodeupdate = false
    sagacompensatepersistmodeupdate = false
    tccactioninterceptororder = -2147482648 #ordered.highest_precedence + 1000
    sqlparsertype = "druid"
    branchexecutiontimeoutxa = 60000
    connectiontwophaseholdtimeoutxa = 10000
  }
  tm {
    commitretrycount = 5
    rollbackretrycount = 5
    defaultglobaltransactiontimeout = 60000
    degradecheck = false
    degradecheckperiod = 2000
    degradecheckallowtimes = 10
    interceptororder = -2147482648 #ordered.highest_precedence + 1000
  }
  undo {
    datavalidation = true
    onlycareupdatecolumns = true
    logserialization = "jackson"
    logtable = "undo_log"
    compress {
      enable = true
      # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip
      type = zip
      # if rollback info size > threshold, then will be compress
      # allow k m g t
      threshold = 64k
    }
  }
  loadbalance {
      type = "xid"
      virtualnodes = 10
  }
}
log {
  exceptionrate = 100
}
tcc {
  fence {
    # tcc fence log table name
    logtablename = tcc_fence_log
    # tcc fence log clean period
    cleanperiod = 1h
  }
}

事务模式

1.at模式(推荐:自动补偿)

二阶提交协议原理

原理:基于反向sql补偿,自动生成回滚日志

使用

@service
public class orderservice {
    @globaltransactional(name = "createorder", timeoutmills = 60000)
    public void createorder(orderdto order) {
        // 1. 扣减库存(调用库存服务)
        storagefeignclient.deduct(order.getproductid());
        // 2. 创建订单(本地事务)
        ordermapper.insert(order);
        // 3. 模拟异常触发回滚
        int i = 1 / 0; 
    }
}

关键机制

  • 一阶段:提交本地事务,生成回滚日志(undo_log)
  • 二阶段:成功则异步删除日志,失败则通过日志反向补偿

特点

  • 对代码无侵入
  • 需创建undo_log表
  • 适用于大多数crud场景

2.xa模式(强一致)

原理:基于数据库xa协议的两阶段提交

配置

seata:
  data-source-proxy-mode: xa  # 默认at

特点:

  • 基于数据库xa协议
  • 两阶段提交(2pc)
  • 事务持有锁时间较长,适合短事务

适用场景:强一致性需求,支持xa协议的数据库(如mysql 5.7+)

3.tcc模式(手动补偿)

原理:try-confirm-cancel 三阶段控制

实现

// 1. 定义tcc接口
public interface storagetccservice {
    @twophasebusinessaction(name = "deduct", 
                          commitmethod = "confirm", 
                          rollbackmethod = "cancel")
    boolean deduct(@businessactioncontextparameter(paramname = "productid") string productid,
                   @businessactioncontextparameter(paramname = "count") integer count);
    
    boolean confirm(businessactioncontext context);
    boolean cancel(businessactioncontext context);
}

// 2. 实现try逻辑
@service
public class storagetccserviceimpl implements storagetccservice {
    @override
    public boolean deduct(string productid, integer count) {
        // try阶段:资源预留(例如冻结库存)
        return storagemapper.freezestock(productid, count) > 0;
    }
    
    @override
    public boolean confirm(businessactioncontext context) {
        // confirm阶段:真实扣减(例如删除冻结记录)
        string productid = context.getactioncontext("productid");
        integer count = context.getactioncontext("count");
        return storagemapper.reducestock(productid, count) > 0;
    }
    
    @override
    public boolean cancel(businessactioncontext context) {
        // cancel阶段:释放资源(例如恢复冻结库存)
        string productid = context.getactioncontext("productid");
        integer count = context.getactioncontext("count");
        return storagemapper.unfreezestock(productid, count) > 0;
    }
}

使用限制:

  • 需自行实现try/confirm/cancel方法
  • confirm和cancel需保证幂等性

特点:高性能,但需手动编写补偿逻辑

4.saga模式(长事务)

实现方式:

通过状态机配置补偿策略:

@sagastart
public void createordersaga(order order) {
    // 1. 创建订单
    orderservice.create(order);
    // 2. 调用支付服务(若失败则触发逆向操作)
    paymentservice.pay(order.getid());
}
// 定义补偿方法
@compensate
public void compensateorder(order order) {
    orderservice.delete(order.getid());
}

原理:长事务拆分+逆向补偿

适用场景:跨系统长时间操作(如订单+物流+支付)

总结

模式选型对照表:

模式一致性性能侵入性适用场景
at弱一致常规业务(库存扣减、订单创建)
tcc强一致资金交易、需精准控制
xa强一致银行转账、短事务
saga最终一致跨系统长流程(订单+物流+支付)

核心要点:

分类要点说明
选型at模式适用于大多数场景,tcc适合高性能要求,xa适合强一致性
配置确保seata-server与微服务的registry配置一致
事务id通过rootcontext.getxid()可获取当前事务id
排错检查undo_log表记录,查看seata-server控制台日志

最佳实践:

  1. 生产环境建议使用nacos作为配置中心
  2. at模式需要开启数据库的本地事务支持(如mysql的innodb引擎)
  3. 全局事务超时时间建议设置:seata.tx.timeout=60000(单位毫秒)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com