Seata 简介

简介: Seata 的前身 Fescar 刚开源的时候,就看过相关的文章和代码,代码写得很好,我还在另一个自己的项目中,借鉴了它的很多设计风格。最近想总结一篇关于分布式事务的文章,所以就想以 Seata 为中心,围绕它来细述分布式事务的点点滴滴。本文作为该系列文章的开篇,先简单地介绍一下 Seata 的背景和使用方式。

引言

Seata 的前身 Fescar 刚开源的时候,就看过相关的文章和代码,代码写得很好,我还在另一个自己的项目中,借鉴了它的很多设计风格。最近想总结一篇关于分布式事务的文章,所以就想以 Seata 为中心,围绕它来细述分布式事务的点点滴滴。本文作为该系列文章的开篇,先简单地介绍一下 Seata 的背景和使用方式,其他 Seata 相关文章均收录于 <Seata系列文章>中。

背景

互联网系统最初的设计一般都是单库单表,但随着业务数据规模的快速发展,数据量越来越大,单库单表逐渐成为瓶颈。所以,在这个阶段一般都会对数据库进行水平拆分,将原单库单表拆分成多个数据库分片。

如下图所示,分库分表之后,原来在一个数据库上就能完成的写操作,可能就会跨多个数据库,这就产生了跨数据库事务问题。
hor-db
此外,在系统设计初期,一般都是将所有业务放在一个服务中,但是随着业务的快速发展,系统的访问量和业务复杂程度都在快速增长,这种单系统架构逐渐成为业务发展瓶颈,解决业务系统的高耦合、可伸缩问题的需求越来越强烈。
vir-db
如上图所示,本着面向服务(SOA)的设计原则,会将单系统拆分成多个业务系统,这降低了各个系统之间的耦合度,使不同的业务系统专注于自身业务,更有利于各个子业务的发展和子系统容量的伸缩。但是,业务系统按照服务拆分之后,一个完整的业务往往需要调用多个服务,如何保证多个服务间的数据一致性成为一个难题。

为了应对这种需求,在数据库领域发展出了一个 XA 协议,在数据库层面基于 2PC 来实现分布式事务,但是并不是所有的数据库都支持该协议,如果有任意一个子系统使用的数据库不支持 XA 协议的话,就无法保证整个业务流程的一致性。此外,XA 的执行效率也很差,而且因为它处于数据库实现领域,所以数据库的使用者对此毫无办法,当然您也可以直接定制化数据库实现,但是成本很大。

为了解决上述问题,专注于分布式事务的应用层中间件就应运而生,它们有的是 2PC 型无侵入方案,有的是 TCC 方案。而我们今天介绍的主角 Seata,将各种方案都整合到了一起,并针对性能进行了很多优化,可谓是集大成者。接下来就让我们一起看一看 Seata 带给我们的便利,以及 Seata 的实现原理。

试玩

前面提到了 Seata 会给开发带来极大的便利,这里就以官方Demo为例,先给大家演示一下如何使用 Seata。这里我使用了官方 Demo 中的 springboot-dubbo-seata,因为它涉及到前面提到的多服务场景,每个服务操作各自的 DB(名义上),使用 dubbo 进行 RPC,从而完成整个业务流程。

我的试玩流程:

  1. 下载代码
  2. 导入 IntelliJ IDEA,并下载 maven 依赖
  3. 下载 1.1.0 版本的 nacos,后面会用它进行 RPC 的服务发现
  4. 下载 0.8.0 版本的 seata-server,这里它扮演分布式事务协调者
  5. 在本地的 MySQL 服务中创建 seata 数据库,并将 springboot-dubbo-seata 中的样例 SQL 导入到 seata 数据库,完成后可以发现数据库中有 t_account,t_order,t_storage,undo_log 这四个表,并且 t_account 中有一条用户数据,t_storage 中有一条商品信息。
  6. 然后分别启动 3 个子服务 samples-account、samples-order、samples-storage,最后启动业务入口服务 samples-business
  7. 通过 curl 调用业务入口服务
⚠️注意:我当时测试时,官方 Guide 中使用的 curl 命令有一些问题,其中使用的商品码有误,这里需要将其改为 DB 中保存的商品码 C201901140001,我已经给官方仓库提了 PR,但是可能还未合并。总之,最终完整的 curl 命令如下:
   curl -H "Content-Type:application/json" -X POST -d '{"userId":"1","commodityCode":"C201901140001","name":"风扇","count":2,"amount":"100"}' localhost:8104/business/dubbo/buy

事务提交

sample-success.png
当业务流程成功完成时,请求结果是成功。查看 DB 你会发现 t_account 中用户的余额减少了:4000 -> 3900,t_storage 中商品的数量减少了: 1000 -> 998,t_order 中新增了一条订单。
new-order

事务回滚

接下来我们测试一下事务回滚的效果,首先打开回滚异常。
rollback-check
然后重启入口服务 samples-business,并重新发送请求,请求结果变成了失败,此时查看 DB 你会发现它没有任何变化。
sample-failure
我们回过头来看看业务入口的代码,你会发现这一切特性的接入对开发者来说,只是将全局事务注解 GlobalTransactional 标在入口函数上,然后在所有服务中引入 Seata,并进行正确的配置,剩下的脏活累活 Seata 就自动帮我们完成了, 是不是感觉很神奇?

/**
 * 处理业务逻辑
 */
@Override
// 全局事务注解
@GlobalTransactional(timeoutMills = 300000, name = "dubbo-gts-seata-example")
public ObjectResponse handleBusiness(BusinessDTO businessDTO) {
    System.out.println("开始全局事务,XID = " + RootContext.getXID());
    ObjectResponse<Object> objectResponse = new ObjectResponse<>();
    //1、扣减库存
    CommodityDTO commodityDTO = new CommodityDTO();
    commodityDTO.setCommodityCode(businessDTO.getCommodityCode());
    commodityDTO.setCount(businessDTO.getCount());
    ObjectResponse storageResponse = storageDubboService.decreaseStorage(commodityDTO);
    //2、创建订单
    OrderDTO orderDTO = new OrderDTO();
    orderDTO.setUserId(businessDTO.getUserId());
    orderDTO.setCommodityCode(businessDTO.getCommodityCode());
    orderDTO.setOrderCount(businessDTO.getCount());
    orderDTO.setOrderAmount(businessDTO.getAmount());
    ObjectResponse<OrderDTO> response = orderDubboService.createOrder(orderDTO);

    //打开注释测试事务发生异常后,全局回滚功能
    if (!flag) {
        throw new RuntimeException("测试抛异常后,分布式事务回滚!");
    }

    if (storageResponse.getStatus() != 200 || response.getStatus() != 200) {
        throw new DefaultException(RspStatusEnum.FAIL);
    }

    objectResponse.setStatus(RspStatusEnum.SUCCESS.getCode());
    objectResponse.setMessage(RspStatusEnum.SUCCESS.getMessage());
    objectResponse.setData(response.getData());
    return objectResponse;
}

从业务服务的实现代码中可以看到,我们先调用了库存服务减少库存,然后调用订单服务创建订单,在订单服务里面,涉及到了减少用户余额(代码就不展示了),当所有的这一切都完成时,业务流程中抛出一个运行时异常,致使整个业务链路中的所有 DB 事务都回滚了。

至此,系统垂直扩展引入的分布式事务问题就解决了。
vir-db2
好了,实验课结束了,该学一下理论知识了。

文章说明

更多有价值的文章均收录于贝贝猫的文章目录

stun

版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

创作声明: 本文基于下列所有参考内容进行创作,其中可能涉及复制、修改或者转换,图片均来自网络,如有侵权请联系我,我会第一时间进行删除。

参考内容

[1] fescar锁设计和隔离级别的理解
[2] 分布式事务中间件 Fescar - RM 模块源码解读
[3] Fescar分布式事务实现原理解析探秘
[4] Seata TCC 分布式事务源码分析
[5] 深度剖析一站式分布式事务方案 Seata-Server
[6] 分布式事务 Seata Saga 模式首秀以及三种模式详解
[7] 蚂蚁金服大规模分布式事务实践和开源详解
[8] 分布式事务 Seata TCC 模式深度解析
[9] Fescar (Seata)0.4.0 中文文档教程
[10] Seata Github Wiki
[11] 深度剖析一站式分布式事务方案Seata(Fescar)-Server

相关文章
|
27天前
|
存储 机器学习/深度学习 开发工具
私有知识库工程化建设方法:一套五阶段流程值得采用
本文提出一套私有知识库工程化建设方法论:以“五阶段流程”(定约定、搭骨架、建索引、做校验、管演化)为路径,以“三条治理原则”(派生可重建、职责单一、双向对账)为根基,用轻量工具(如AiPy)低成本实现可持续维护,有效对抗知识库熵增,让知识库从“文档坟场”升级为可演化的治理工程。(239字)
|
21天前
|
缓存 API 开发工具
Qwen3.8-Max/Flash/Omni 选型落地:RAG 知识库搭建、模型微调、Agent 开发、API 调用教程
目前生成式AI已经从简单问答对话,进化为可以处理超长文档、图文音视频混合输入、自主拆解目标完成多步骤业务的通用智能底座。通义千问Qwen3.8完整家族形成了分层能力矩阵,覆盖旗舰推理、均衡通用、高速高吞吐、原生全模态视听、专项编程多类基座,既可以普通用户网页端直接交互体验,也可以通过百炼平台API集成进业务系统,同时开放开源权重,支持本地私有化部署,覆盖个人创作者、独立开发者、中小企业、大型政企的差异化诉求。很多业务团队在落地过程中,会遇到模型选型混淆、百万上下文使用误区、Agent工具调用不稳定、多模态解析异常、成本不可控、私有化硬件评估不到位等问题。本文完整梳理Qwen3.8家族各模型定位
454 0
|
1月前
|
弹性计算 人工智能 安全
2026年阿里云服务器优惠活动整理汇总及参数说明
2026年阿里云服务器最新优惠汇总:新用户轻量服务器低至38元/年,学生享300元无门槛券,企业u1实例199元起,含ECS、建站套餐及GPU服务选型指南。(239字)
217 0
|
2月前
|
人工智能 自然语言处理 机器人
告别回复慢、流失高:真正适合电商的智能客服产品推荐
电商客服困于响应慢、回答浅、难闭环。阿里云瓴羊Quick Service以AI Agent技术实现“能答更能干”,支持查物流、改地址、退换货等全流程自动办理,问答准确率93%,大促峰值稳定支撑,助力企业降本增效、提升转化。
209 0
|
11月前
|
人工智能 自然语言处理 运维
免费智能客服系统盘点与企业建设成本全解析
本文盘点主流免费智能客服系统,解析企业建设成本构成,对比瓴羊Quick Service、亿捷云客服、Zendesk电商版等产品在不同场景下的适配性与服务能力,为中小微、中大型及跨境企业提供科学选型建议,助力低成本实现服务智能化升级。
|
Prometheus Kubernetes Cloud Native
Flagger(应用自动发布)介绍和原理剖析
## 简介 [Flagger](https://github.com/weaveworks/flagger)是一个能使运行在k8s体系上的应用发布流程全自动(无人参与)的工具, 它能减少发布的人为关注时间, 并且在发布过程中能自动识别一些风险(例如:RT,成功率,自定义metrics)并回滚. ## 主要特性 ![features](https://intranetproxy.ali
5487 0
idea java类文件左下角出现红色的J标识(已解决)
如下图所示,类文件左下角有个J,项目也不报错
3367 0
idea java类文件左下角出现红色的J标识(已解决)
|
存储 Java 文件存储
ZooKeeper 避坑实践:SnapCount 设置不合理导致磁盘爆满,服务不可用
本篇通过深入解读 ZooKeeper 数据文件生成机制,以及 ZooKeeper 中和数据文件生成相关的参数,探究一下 解决 ZooKeeper 磁盘问题的最佳实践。
ZooKeeper 避坑实践:SnapCount 设置不合理导致磁盘爆满,服务不可用
|
监控 安全 搜索推荐
网址被QQ拦截后应该怎么做才可能尽快解除拦截
作为一个多元化的应用平台,QQ拥有着庞大的基础用户群,腾讯旗下任何一个新兴的网络应用都会受到QQ用户的广泛认可,因此,QQ应用平台一直是网站推广的理想选择。
1520 0
网址被QQ拦截后应该怎么做才可能尽快解除拦截