SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务

事务ACID原则

原子性:事务中的所有操作,要么全部成功,要么全部失败

一致性:要保证数据库内部完整性约束、声明性约束

隔离性:对同一资源操作的事务不能同时发生

持久性:对数据库做的一切修改将永久保存,不管是否出现故障

一、理论基础
1)CAP理论

1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标:

Consistency(一致性)

Availability(可用性)

Partition tolerance (分区容错性)

Eric Brewer 说,分布式系统无法同时满足这三个指标。 这个结论就叫做 CAP 定理。

CAP定理- Consistency

Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致

CAP定理- Availability

Availability (可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝

CAP定理-Partition tolerance

Partition(分区):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。

Tolerance(容错):在集群出现分区时,整个系统也要持续对外提供服务

2)BASE理论

BASE理论是对CAP的一种解决思路,包含三个思想:

Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。

Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。

Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。

而分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论:

AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。

CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态

二、分布式事务Seata
1)初识seata

Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。

致力于提供高性能和简单易用的分布式事务服务,为用户打造一站式的分布式解决方案。

官网地址:http://seata.io/,其中的文档中提供了大量的使用说明、源码分析。

2)Seata架构

Seata事务管理中有三个重要的角色:

TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。

TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

Seata提供了四种不同的分布式事务解决方案:

XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入

TCC模式:最终一致的分阶段事务模式,有业务侵入

AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式

SAGA模式:长事务模式,有业务侵入

SeaTa AT模式实战
Seata AT模式实现原理
  1. 解析业务SQL,更新业务数据,保存更新前后镜像到undo_log。在业务操作数据库流程中,Seata会基于数据源代理(0.9以后支持自动代理)对原执行SQL进行解析。之后通过本地事务的ACID特性,将这两步操作(保存业务数据前后镜像到undo_log, 更新业务数据)在本地事务中进行提交

  1. TC服务接收到事务分支的事务状态汇报之后,决定对全局事务进行提交或者回滚,这就是第二阶段。

具体的流程为:

(1) 分支事务收到TC的提交请求之后放入异步队列中,马上返回提交成功的结果;这里不需要同步返回的原因是:TC不需要知道分支事务的结果,因为仅仅只是一步删除UNDO_LOG记录的操作,即使不成功也不会结果造成影响,所以采用异步是有效的方式

(2) 从异步队列中执行分支提交请求,清理undo_log日志,这里并不需要分支事务的提交了,因为第一阶段中已经提交过了

理解起来就是:AT模式下的全局事务的提交只需要清理UNDO_LOG记录就行,不需要管分支(本地)事务的提交结果!

下载地址:https://github.com/seata/seata/releases

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第1张图片

修改seata1.6.1/seata/conf/application.yml内容,由于使用nacos作为注册中心主要seata的config、registry、store

#  Copyright 1999-2019 Seata.io Group.
#
#  Licensed 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.

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    username: seata
    password: seata

seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace:
      group: DEFAULT_GROUP
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
      data-id: seataServer.properties
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      namespace:
      group: DEFAULT_GROUP
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
  store:
    # support: file 、 db 、 redis
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: root
      password: feng02140.0
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 1000
      max-wait: 5000

  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第2张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第3张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第4张图片

根据seata1.6.1/seata/script/server/db/mysql.sql建数据库表seata

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第5张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第6张图片

在nacos中新增配置seataServer.properties

# 数据存储方式,db代表数据库
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true&serverTimezone=GMT
 
store.db.user=root
store.db.password=feng02140.0
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
# 事务、日志等配置
server.recovery.committingRetryPeriod=3000
server.recovery.asynCommittingRetryPeriod=3000
server.recovery.rollbackingRetryPeriod=3000
server.recovery.timeoutRetryPeriod=3000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
 
# 客户端与服务端传输方式
transport.serialization=seata
transport.compressor=none
# 关闭metrics功能,提高性能
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898


Nacos中新建service.vgroupMapping.order-service

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第7张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第8张图片

启动seata

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第9张图片

访问后台http://127.0.0.1:7091/#/login

账号:seata 密码:seata

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第10张图片

父POM引入

 
                io.seata
                seata-all
                ${seata.version}
            

order以及store服务引入


        
            io.seata
            seata-spring-boot-starter
            ${seata.version}
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-seata
            
                
                    io.seata
                    seata-all
                
                
                    seata-spring-boot-starter
                    io.seata
                
            
        

order服务中配置

seata:
  application-id: order-service
  tx-service-group: order-service
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      group: DEFAULT_GROUP
      namespace:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      group: DEFAULT_GROUP
      namespace:
  service:
    vgroupMapping:
      order-service: default

store服务中配置

seata:
  application-id : store-service
  tx-service-group: order-service
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      group: DEFAULT_GROUP
      namespace:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      group: DEFAULT_GROUP
      namespace:
  service:
    vgroupMapping:
      order-service: default

service.vgroupMapping 后的order-service为事务组名称,对应Nacos的配置service.vgroupMapping.order-service中的order-service

对应tx-service-group 后的value

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第11张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第12张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第13张图片

两个服务需要配置同一个事务组

在order服务接口上添加@GlobalTransactional(name = "order",rollbackFor = Exception.class)

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第14张图片

使用postman访问,模拟库存不足的情况,库存不足将抛出RunTimeException.修改库存为0

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第15张图片
SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第16张图片

order存在两个订单

发送请求

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第17张图片

发现库存不足,订单创建失败,事务被回滚.查看数据库

因库存不足order并未被创建

SpringCloud AliBaBa(五)-Nacos集成seata实现分布式事务_第18张图片

[遇到的小问题]:store服务在接口层面不能直接catch异常,不然会无法回滚.

你可能感兴趣的:(SpringCloud,AliBaBa,spring,cloud,分布式,数据库)