微服务-seata分布式事件

[复制链接]
发表于 2025-12-11 16:26:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1.简述

1.1.什么是分布式事件



  • 事件:是应用步调中一系列精密的操纵,全部操纵必须乐成完成,要么全部失败,ACID 特性。
  • 当地事件:关系型数据库中,由一组SQL构成的一个实行单元,该单元要么团体乐成,要么团体失败;它有一个缺点:仅支持单库事件,并不支持跨库事件。
  • 分布式事件:指事件的到场者、支持事件的服务器、资源服务器以及事件管理器分别位于差别的分布式体系的差别节点之上。一个应用某个功能必要操纵多个库,差别的库中存储差别的业务数据。是指一个业务必要同时操纵多个数据库的环境下,而且必须保持ACID的特性。一样平常应用于微服务的多服务处理处罚。
1.2.为什么必要分布式事件

一个网站的访问量越来越大,按照商品、订单、用户、店肆等业务为单元举行数据库拆分,以及按照业务为单元提供服务接口。为了完成一个简朴的业务功能,好比:购买商品后扣款,有大概必要高出多个服务,涉及用户订单、商品库存、付出等多个数据库,而这些操纵又必要在同一个事件中完,这就涉及到到了分布式事件。
分布式事件就是为了包管差别资源服务器的数据划一性。
关于具体的分布式事件具体理论知识,请自行移步干系文章学习。
2.分布式事件

我们模拟一个业务流程:

由于订单、购物车、商品分别在三个差别的微服务,而每个微服务都有自己独立的数据库,因此下单过程中就会跨多个数据库完成业务。而每个微服务都会实行自己的当地事件:


  • 生意业务服务:下单事件
  • 购物车服务:清算购物车事件
  • 库存服务:扣减库存事件
整个业务中,各个当地事件是有关联的。因此每个微服务的当地事件,也可以称为分支事件。多个有关联的分支事件一起就构成了全局事件。我们必须包管整个全局事件同时乐成或失败。
我们知道每一个分支事件就是传统的单体事件,都可以满足ACID特性,但全局事件超过多个服务、多个数据库,是否还能满足呢?
我们模拟一次业务操纵,微服务项目中,在不使用分布式事件管理时:

  • 进入购物车页面
  • 然结算下单,进入订单结算页面:
  • 将购物车中某个商品的库存修改为0
  • 提交订单,终极因库存不敷导致下单失败
  • 去查察购物车列表,发现购物车数据依然被清空了,并未回滚
事件并未遵照ACID的原则,归其缘故原由就是到场事件的多个子业务在差别的微服务,超过了差别的数据库。固然每个单独的业务都能在当地遵照ACID,但是它们相互之间没有感知,不知道有人失败了,无法包管最闭幕果的同一,也就无法遵照ACID的事件特性了。
这就是分布式事件标题,出现以下环境之一就大概产生分布式事件标题:


  • 业务跨多个服务实现
  • 业务跨多个数据源实现
接下来先容怎样办理分布式事件标题。
2.1.认识Seata

办理分布式事件的方案有许多,但实现起来都比力复杂,因此我们一样平常会使用开源的框架来办理分布式事件标题。在浩繁的开源分布式事件框架中,功能最美满、使用最多的就是阿里巴巴在2019年开源的Seata了。
Seata官方网址:Seata 是什么? | Apache Seata
着实分布式事件产生的一个告急缘故原由,就是到场事件的多个分支事件相互无感知,不知道相互的实行状态。因此办理分布式事件的头脑非常简朴:
就是找一个同一的事件和谐者,与多个分支事件通讯,检测每个分支事件的实行状态,包管全局事件下的每一个分支事件同时乐成或失败即可。大多数的分布式事件框架都是基于这个理论来实现的。
2.1.1.摆设TC服务

摆设详情请移步该文章:docker摆设seata-CSDN博客
2.2.微服务集成Seata

到场分布式事件的每一个微服务都必要集成Seata,我们以trade-service0(订单服务)为例。
2.2.1.引入依赖

为了方便各个微服务集成seata,我们必要把seata设置共享到nacos,因此trade-service模块不但仅要引入seata依赖,还要引入nacos依赖:
  1. <!--统一配置管理-->
  2.   <dependency>
  3.       <groupId>com.alibaba.cloud</groupId>
  4.       <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  5.   </dependency>
  6.   <!--读取bootstrap文件-->
  7.   <dependency>
  8.       <groupId>org.springframework.cloud</groupId>
  9.       <artifactId>spring-cloud-starter-bootstrap</artifactId>
  10.   </dependency>
  11.   <!--seata-->
  12.   <dependency>
  13.       <groupId>com.alibaba.cloud</groupId>
  14.       <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  15.   </dependency>
复制代码
2.2.2.改造设置

起首在nacos控制台上添加一个共享的seata设置,定名为share-seata.yaml:
内容如下:
  1. seata:
  2.   registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
  3.     type: nacos # 注册中心类型 nacos
  4.     nacos:
  5.       server-addr: 192.168.230.128:8848 # nacos地址
  6.       namespace: "" # namespace,默认为空
  7.       group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
  8.       application: seata-server # seata服务名称
  9.       username: nacos
  10.       password: nacos
  11.   tx-service-group: hmall # 事务组名称
  12.   service:
  13.     vgroup-mapping: # 事务组与tc集群的映射关系
  14.       hmall: "default"
复制代码
改造trade-service服务,在bootstrap.yaml文件中添加内容:
  1. spring:
  2.   application:
  3.     name: trade-service # 服务名称
  4.   profiles:
  5.     active: dev
  6.   cloud:
  7.     nacos:
  8.       server-addr: 192.168.150.101 # nacos地址
  9.       config:
  10.         file-extension: yaml # 文件后缀名
  11.         shared-configs: # 共享配置
  12.           - dataId: shared-jdbc.yaml # 共享mybatis配置
  13.           - dataId: shared-log.yaml # 共享日志日志配置
  14.           - dataId: shared-swagger.yaml # 共享日志日志配置
  15.           - dataId: shared-seata.yaml # 共享seata配置
复制代码
可以看到这里加载了共享的seata设置。
在你其他必要的服务中举行此类设置,这里不在逐一叙述。
2.2.3.添加数据库表

seata的客户端在办理分布式事件的时间必要纪录一些中心数据,生存在数据库中。因此我们要先预备一个如许的表seata-at.sql。分别将文件导入每个微服务地点的数据库中:
表具体内容如下:
  1. -- for AT mode you must to init this sql for you business database. the seata server not need it.
  2. CREATE TABLE IF NOT EXISTS `undo_log`
  3. (
  4.     `branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',
  5.     `xid`           VARCHAR(128) NOT NULL COMMENT 'global transaction id',
  6.     `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
  7.     `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
  8.     `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
  9.     `log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',
  10.     `log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',
  11.     UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
  12. ) ENGINE = InnoDB
  13.   AUTO_INCREMENT = 1
  14.   DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
复制代码
运行乐成后你的数据库活出多一张uodo_log的表。

至此为止,微服务整合的工作就完成了。
2.2.4.业务测试

上面回滚失败的业务:

  • 进入购物车页面
  • 然结算下单,进入订单结算页面:
  • 将购物车中某个商品的库存修改为0
  • 提交订单,终极因库存不敷导致下单失败
  • 去查察购物车列表,发现购物车数据依然被清空了,并未回滚
我们在订单服务中,用户点击结算提交订单的业务方法上加上@GlobalTransactional注解,
当库存再次不敷时,业务会举行回滚,购物车就不会被错误的清空。

@GlobalTransactional注解就是在标志事件的出发点,将来TM就会基于这个方法判定全局事件范围,初始化全局事件。
至此,分布式事件seata框架的先容竣事!
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表