百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Seata概述

mhr18 2025-08-05 19:51 3 浏览 0 评论

什么是Seata

Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务

也是Spring Cloud Alibaba提供的组件

Seata官方文档 https://seata.io/zh-cn/

下载Seata

  • https://github.com/seata/seata/releases
  • https://github.com/seata/seata/releases/download/v1.4.2/seata-server-1.4.2.zip

为什么需要Seata

我们首先简单复习一下事务的概念

事务的4个特性:ACID特性

  • 原子性
  • 一致性
  • 隔离性
  • 永久性

我们再业务中,必须保证数据库操作的原子性,也就是当前业务的所有数据库操作要么都成功,要么都失败

之前我们使用Spring声明式事务来解决本地的事务问题

但是现在是微服务环境,一个业务可能涉及多个模块的数据库操作

这种情况就需要专门的微服务状态下解决事务问题的"分布式事务"解决方案

我们学习的Seata就是这样的产品

Seata将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

Seata的运行原理(AT模式)

观察下面事务模型

上面结构是比较典型的远程调用结构

如果account操作数据库失败需要让order模块和storage模块撤销(回滚)操作

声明式事务不能完成这个操作

需要Seata来解决

解决模型如下

Seata构成部分包含

  • 事务协调器TC
  • 事务管理器TM
  • 资源管理器RM

我们项目使用AT(自动)模式完成分布式事务的解决

AT模式运行过程

1.事务的发起方(TM)会向事务协调器(TC)申请一个全局事务id,并保存

2.Seata会管理事务中所有相关的参与方的数据源,将数据操作之前和之后的镜像都保存在undo_log表中,这个表是seata框架规定的,方便提交(commit)或回滚(roll back)

3.事务的发起方(TM)会连同全局id一起通过远程调用运行资源管理器(RM)中的方法

4.资源管理器(RM)接收到全局id,并运行指定的方法,将运行的状态同步到事务协调器(TC)

5.如果运行整体没有发生异常,发起方(TM)会通过事务协调器通知所有分支,将本次事务所有对数据库的影响真正生效,反之如果任何一个RM运行发生异常,那么都会通知事务协调器,再由事务协调器通知所有分支,回滚数据中的数据

回滚时可以使用undo_log表中的数据来实现回滚

其他模式简介

AT模式运行有一个非常明显的条件

就是事务分支都必须是操作关系型数据库(mysql\MariaDB\Oracle)

但是如果一个事务中有操作例如Redis这样的非关系型数据库时就不能使用AT模式了

除了AT模式之外还有TCC、SAGA 和 XA 事务模式

TCC模式

这个模式简单来说就是自己编写代码进行事务的提交和回滚

我们需要在各个分支业务逻辑层代码中编写一组三个方法(prepare\commit\rollback)

prepare:准备 commit:提交 rollback:回滚

prepare方法是无论事务成功与否都会运行的代码

commit当整体事务运行成功时运行的方法

rollback当整体事务运行失败是运行的方法

优点:虽然代码是自己写的,但是事务整体提交或回滚的机制仍然可用

缺点:每个业务都要编写3个方法来对应,代码冗余,而且业务入侵量大

SAGA模式

SAGA模式的思想是编写一个类,当指定的事务发生问题时,运行SAGA编写的回滚类

这样编写代码不影响已经编写好的业务逻辑代码

一般用于修改已经编写完成的老代码

缺点是每个事务分支都要编写一个类来回滚业务,

类数量多,开发量大

XA模式

支持XA协议的数据库分布式事务,使用比较少

使用Seata

配置Seata

cart\stock\order都是具备数据库操作的模块配置过程如下

<!-- seata和SpringBoot整合依赖 -->
<dependency>
  <groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</dependency>
<!-- Seata完成分布式事务需要的两个相关依赖(Seata需要下面两个依赖中的资源) -->
<dependency>
  <groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>

下面修改application-dev.yml

代码如下

seata:
  tx-service-group: csmall_group #定义分组名称
  service:
    vgroup-mapping:
      csmall_group: default  # 使用seata默认事务配置
    grouplist: 
      default: localhost:8091 # 8091是seata默认的地址

注意同一个事务必须在同一个tx-service-group中

同时指定相同的seata地址和端口

business模块配置更简单

因为它是服务的发起者,不需要数据库操作,所以配置更简单

但是它是TM的角色,不配置肯定是不行的

<dependency>
  <groupId>io.seata</groupId>
  <artifactId>seata-spring-boot-starter</artifactId>
</dependency>

application-dev.yml是一样的

seata:
  tx-service-group: csmall_group #定义分组名称
  service:
    vgroup-mapping:
      csmall_group: default  # 使用seata默认事务配置
    grouplist:
      default: localhost:8091 # 8091是seata默认的地址

seata标记事务的开始有一个专用的注解

在事务模型中,TM(事务管理器)的业务逻辑层方法上添加这个注解即可

business的业务逻辑层buy方法上添加注解

@Service
@Slf4j
public class BusinessServiceImpl implements IBusinessService {

  // Dubbo在获取order模块的业务逻辑层实现类
  @DubboReference
  private IOrderService dubboOrderService;

  // 一旦编写这个注解@GlobalTransactional
  // seata就会将这个方法当做一个分布式事务的起点
  // 之后所有远程Dubbo调用的数据库操作要么都成功,要么都失败
  @GlobalTransactional
  @Override
  public void buy() {
    // 暂时模拟一个下单业务
    // 创建OrderAddDTO类,赋值并输出信息
    OrderAddDTO orderAddDTO=new OrderAddDTO();
    orderAddDTO.setCommodityCode("PC100");
    orderAddDTO.setUserId("UU100");
    orderAddDTO.setMoney(500);
    orderAddDTO.setCount(8);
    // 因为没有持久层,只能输出一下,表示运行正常
    log.info("新增订单信息为:{}",orderAddDTO);
    // dubbo调用生成订单方法
    dubboOrderService.orderAdd(orderAddDTO);
    // 为了验证我们seata是有效果的
    // 在当前业务逻辑层方法中随机发生异常
    // 我们可以通过观察正常运行时数据是否提交和发生异常是数据是否回滚来判断seata是否工作
    if(Math.random()<0.5){
      throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,
                                          "发生随机异常");
    }
  }
}

启动seata

seata也是java开发的,启动方式和nacos很像

只是启动命令不同

解压后路径不要用中文,不要用空格

也是解压之后的bin目录下

在路径上输入cmd进入dos窗口

G:\pgm\seata\seata-server-1.4.2\bin>seata-server.bat -h 127.0.0.1 -m file

要想启动,需要启动所有4个服务cart\stock\order\business

利用knife4j访问business模块,否则无法触发事务效果,business模块是seata事务的启动

在windows系统中运行seata可能出现不稳定的情况,重启seata即可解决

根据是否发生随机异常,来判断seata是否有效

学习记录,如有侵权请联系删除

相关推荐

IM群聊消息如此复杂,如何保证不丢不重?

群聊是多人社交的基本诉求,不管是QQ群,还是微信群,一个群友在群内发了一条消息:(1)在线的群友能第一时间收到消息(2)离线的群友能在登陆后收到消息群消息的复杂度要远高于单对单消息。群消息的实时性,可...

Python 网络爬虫实战:从零到部署的完整流程

适用人群:初-中级Python开发者、数据分析师、运维/测试自动化工程师工具栈:Python3.11+requests+BeautifulSoup/lxml+pandas+(...

用上Kiro之后,完全没理由为Cursor续费了

替Cursor续费前最后一秒,免费IDEKiro把钱包按死在屏幕前五位数年费的AI编程助手,被一匹黑马零元秒杀。用过Kiro的人,开note第一件事就是删掉Cursor的自动续费,动作快到连...

分布式微服务中的搜索引擎:架构与实战盘点

01、为什么微服务需要分布式搜索?在单体应用时代,我们通常使用单一数据库的全文检索功能(如MySQL的LIKE语句)或简单的搜索引擎(如早期的Lucene)。但随着业务规模扩大,这种架构暴露出诸多问题...

产品列表获取API接口详解

在现代软件开发中,API(应用程序编程接口)是获取产品列表的核心工具,它允许开发者从远程服务器高效地检索数据。本文将逐步介绍如何设计和使用产品列表获取API接口,包括核心概念、实现步骤、代码示例以及最...

企业和个人基于业务知识和代码库增强的大模型生成代码实践

作者:京东零售杨亚龙1.源起李明是今年刚加入某互联网公司的研发新人,满怀期待地开始了他的职业生涯。然而,短短两周后,他的热情就被现实浇了一盆冷水。第一周:当他第一次接手需求时,mentor只是简单...

从零到一:独立运行若依框架系统并进行本地二次开发

####一、环境准备1.**基础环境**:-JDK1.8+(推荐JDK17)-Maven3.6+-MySQL5.7+(推荐8.0)-Redis5.0+-Node.js16...

一文教你高效优化在Spring Boot3中遇到深度分页查询性能难题?

你有没有这样的经历?在使用SpringBoot3开发项目时,深度分页查询操作让程序运行得越来越慢,页面加载时间变得难以忍受,不仅影响用户体验,还可能导致项目进度受阻。明明代码逻辑看起来没问题,可...

JAVA面试|如何优化limit分页

我们来详细通俗地聊聊如何优化LIMIToffset,size分页。核心问题在于OFFSET的值很大时,性能会急剧下降。想象一下数据库的工作方式,你就明白为什么了。一、为什么OFFSET大时慢?假...

MySQL(143)如何优化分页查询?

优化分页查询是提升数据库性能和用户体验的重要手段。特别是在处理大数据集时,分页查询的效率对系统性能有显著影响。以下是优化分页查询的详细步骤和代码示例。一、传统分页查询传统的分页查询使用OFFSET...

Seata概述

什么是SeataSeata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务也是SpringCloudAlibaba提供的组件Seata官方文档https...

Docmost:一款开源的Wiki和文档协作软件

是一款开源的团队协作Wiki与文档管理工具,定位为Confluence和Notion的开源替代品,专注于提供高效、安全且可定制的知识库解决方案。Docmost的核心优势在于开源免...

B端系统管理「字典管理」模块实战指南

字典管理听起来像“后端杂务”,其实是B端系统配置能力的关键支点。本指南将从真实业务场景出发,系统拆解该模块的设计逻辑、关键字段与典型坑位,让你一文读懂如何搭建一个能跑得久、配得稳的字典模块。一、字典管...

Spring Boot 整合 Redis BitMap 实现 签到与统计

要在SpringBoot中实现RedisBitMap来进行签到和统计,您需要按照以下步骤进行操作:添加Redis依赖:在pom.xml文件中添加Redis依赖:<dependen...

周期性清除Spark Streaming流状态的方法

在SparkStreaming程序中,我们经常需要使用有状态的流来统计一些累积性的指标,比如各个商品的PV。简单的代码描述如下,使用mapWithState()算子:valproductPvSt...

取消回复欢迎 发表评论: