热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分布式事务框架seata介绍

分布式事务框架seata介绍

分布式事务框架seata介绍

一 、 事务特性(ACID)

1、原子性(A)
在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样。

2、一致性(C)
事务的执行必须保证系统的一致性

3、隔离性(I)
所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。

4、持久性(D)
所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。

这种特性简称刚性事物

二、事务隔离级别

1、脏读:事务T1读取到事务T2修改了但是还未提交的数据,之后事务T2又回滚其更新操作,导致事务T1读到的是脏数据。

2、不可重复读:事务T1读取某个数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。

3、幻影读:事务T1读取在读取某范围数据时,事务T2又插入一条数据,当事务T1再次数据这个范围数据时发现不一样了,出现了一些“幻影行”。

不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

幻读和不可重复读的异同:都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体。

三、分布式事务

1、概念

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

2、CPA理论

CAP由Eric Brewer在2000年PODC会议上提出[1][2],是Eric Brewer在Inktomi[3]期间研发搜索引擎、分布式web缓存时得出的关于数据一致性(consistency)、服务可用性(availability)、分区容错性(partition-tolerance)的猜想:

(1)数据一致性(consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(strong consistency) (又叫原子性 atomic、线性一致性 linearizable consistency)
(2)服务可用性(availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待
(3)分区容错性(partition-tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务、

3、Base理论

BASE理论是指,Basically Available(基本可用)、Soft-state( 软状态/柔性事务)、Eventual Consistency(最终一致性)。是基于CAP定理演化而来,是对CAP中一致性和可用性权衡的结果。核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。

1、基本可用:指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;网页访问过大时,部分用户提供降级服务,等。
2、软状态:软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。即允许系统在不同节点间副本同步的时候存在延时。
3、最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。BASE理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID是传统数据库常用的概念设计,追求强一致性模型

四、微服务中的分布式事务问题

让我们想象一下传统的单个应用程序。它的业务由3个模块组成。他们使用单个本地数据源。

自然,本地事务将保证数据的强一致性。
在这里插入图片描述
微服务架构已发生了变化。上面提到的3个模块被设计为在3种不同数据源之上的3种服务。本地事务已经无法保证模块之间调用数据的一致性。

在这里插入图片描述

五、seata介绍?

1、Seata是阿里开发的一个用于微服务架构的高性能易使用的分布式事务框架。分布式事务是由一批分支事务组成的全局事务,通常分支事务只是本地事务。

2、Seata有3个基本组成部分:

  • **事务协调器(TC):**维护全局事务和分支事务的状态,驱动全局提交或回滚。

  • **事务管理器(TM):**用于开启全局事务、提交或者回滚全局事务,是全局事务的开启者。

  • **资源管理器(RM):**用于分支事务上的资源管理,向TC注册分支事务,上报分支事务的状态,接受TC的命令来提交或者回滚分支事务。
    在这里插入图片描述
    3、Seata管理的分布式事务的典型生命周期:

(1)TM向TC请求发起一个全局事务,TC返回一个代表这个全局事务的XID。

(2)XID通过微服务的调用链传播。

(3)每个RM拿到XID后向TC发起一个分支事务,TC返回一个代表这个分支事务的XID。

(4)RM完成本地分支的业务,提交本地分支,并且报告给TC。

(5)全局事务调用链处理完毕,TM根据有无异常向TC发起全局事务的提交或者回滚。

(6)假设某个RM本地事务失败。该RM自身驱动本地事务回滚,并且报告给TC。

(7)TM检测到了某个分支事务失败,向TC发起全局事务回滚。

(8)TC给每一个RM发送消息,通知它们全部回滚。

(9)TC将全局事务回滚的结果发送给TM,全局事务结束。

六、demo简介

1.demo技术选型

  • 注册中心:eureka

  • 服务间调用:feign

  • 持久层:mybatis

  • 数据库:mysql 5.7.20

  • Springboot:2.1.7.RELEASE

  • Springcloud:Greenwich.SR2

  • jdk:1.8

  • seata:0.8

demo分为四个项目,单独启动。

  • eureka:作为注册中心
  • order:订单服务,用户下单后,会创建一个订单添加在order数据库,同时会扣减库存storage,扣减账户account;
  • storage:库存服务,用户扣减库存;
  • account:账户服务,用于扣减账户余额;

注:使用时版本需要相对应

order服务关键代码如下:

@Override
@GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class) //此注解开启全局事务
public void create(Order order) {
//本地方法 创建订单
orderDao.create(order);
//远程方法 扣减库存
storageApi.decrease(order.getProductId(),order.getCount());
//远程方法 扣减账户余额 可在accountServiceImpl中模拟异常
accountApi.decrease(order.getUserId(),order.getMoney());
}

2.使用步骤

  • (1).拉取本demo代码;
  • (2).拉取seata-server;
  • (3).执行每个项目下的建表语句,resource下xx.sql文件;
  • (4).seata相关建表语句见下文说明;

3.seata server端配置信息修改

seata-server中,/conf目录下,有两个配置文件,需要结合自己的情况来修改:
在这里插入图片描述

(1).file.conf

里面有事务组配置,锁配置,事务日志存储等相关配置信息,由于此demo使用db存储事务信息,我们这里要修改store中的配置:

## transaction log store
store {
## store mode: file、db
mode = "db" 修改这里,表明事务信息用db存储
## file store 当mode=db时,此部分配置就不生效了,这是mode=file的配置
file {
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
max-branch-session-size = 16384
# globe session size , if exceeded throws exceptions
max-global-session-size = 512
# file buffer size , if exceeded allocate new buffer
file-write-buffer-cache-size = 16384
# when recover batch read size
session.reload.read_size = 100
# async, sync
flush-disk-mode = async
}
## database store mode=db时,事务日志存储会存储在这个配置的数据库里
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "dbcp"
## mysql/oracle/h2/oceanbase etc.
db-type = "mysql"
driver-class-name = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://116.62.62.26/seat-server" 修改这里
user = "root" 修改这里
password = "root" 修改这里
min-conn = 1
max-conn = 3
global.table = "global_table"
branch.table = "branch_table"
lock-table = "lock_table"
query-limit = 100
}
}

由于此demo我们使用db模式存储事务日志,所以,我们要创建三张表:global_table,branch_table,lock_table,建表sql在上面下载的seata-server的/conf/db_store.sql中;

由于存储undo_log是在业务库中,所以在每个业务库中,还要创建undo_log表,建表sql在/conf/db_undo_log.sql中。

由于我自定义了事务组名称,所以这里也做了修改:

service {
#vgroup->rgroup
vgroup_mapping.fsp_tx_group = "default" 修改这里,fsp_tx_group这个事务组名称是我自定义的,一定要与client端的这个配置一致!否则会报错!
#only support single node
default.grouplist = "127.0.0.1:8091" 此配置作用参考:https://blog.csdn.net/weixin_39800144/article/details/100726116
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}

其他的可以先使用默认值。

(2).registry.conf

registry{}中是注册中心相关配置,config{}中是配置中心相关配置。seata中,注册中心和配置中心是分开实现的,是两个东西。

我们这里用eureka作注册中心,所以,只用修改registry{}中的:

registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "eureka" 修改这里,指明注册中心使用什么
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka" 修改这里
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}

其他的配置可以暂时使用默认值。

(3) 如果是在windows下启动seata-server,现在已经完成配置修改了,等eureka启动后,就可以启动seata-server了:执行/bin/seata-server.bat即可。
(4)用开发工具启动如下类就可以

在这里插入图片描述

4、client端相关配置

1.普通配置

client端的几个服务,都是普通的springboot整合了springCloud组件的正常服务,所以,你需要配置eureka,数据库,mapper扫描等,即使不使用seata,你也需要做,这里不做特殊说明,看代码就好。

2.特殊配置
1.application.yml

以order服务为例,除了常规配置外,这里还要配置下事务组信息:

spring:
application:
name: order-server
cloud:
alibaba:
seata:
tx-service-group: fsp_tx_group 这个fsp_tx_group自定义命名很重要,server,client都要保持一致

2.file.conf

自己新建的项目是没有这个配置文件的,copy过来,修改下面配置:

service {
#vgroup->rgroup
vgroup_mapping.fsp_tx_group = "default" 这个fsp_tx_group自定义命名很重要,server,client都要保持一致
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
disableGlobalTransaction = false
}

3.registry.conf

使用eureka做注册中心,仅需要修改eureka的配置即可:

registry {
# file 、nacos 、eureka、redis、zk
type = "eureka" 修改这里
nacos {
serverAddr = "localhost"
namespace = "public"
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka" 修改这里
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6381"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
file {
name = "file.conf"
}
}

其他的使用默认值就好。

3.数据源代理

这个是要特别注意的地方,seata对数据源做了代理和接管,在每个参与分布式事务的服务中,都要做如下配置:

/**
* 数据源代理
*/

@Configuration
public class DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Primary
@Bean("dataSource")
public DataSourceProxy dataSource(DataSource druidDataSource){
return new DataSourceProxy(druidDataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy)throws Exception{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSourceProxy);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath*:/mapper/*.xml"));
sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sqlSessionFactoryBean.getObject();
}
}

5.启动测试

  • (1).启动eureka;

  • (2).启动seata-server;

  • (3).启动order,storage,account服务;
    在这里插入图片描述
    DEFAULT为seata服务的默认名字,也可通过修改配置文件自定义名字

  • (5).访问:http://localhost:8080/order/create?userId=1&productId=1&count=10&mOney=100

然后可以模拟正常情况,异常情况,超时情况等,观察数据库即可,发现事务控制成功

6.模拟异常情况

  • (1)账户服务抛异常

/**
* 扣减账户余额
* @param userId 用户id
* @param money 金额
*/
@Override
public void decrease(Long userId, BigDecimal money) {

LOGGER.info("------->扣减账户开始account中");
accountDao.decrease(userId,money);
LOGGER.info("------->扣减账户结束account中");
throw new RuntimeException("发生错误");

}

(2)访问:http://localhost:8080/order/create?userId=1&productId=1&count=10&mOney=100,发现事务回滚
在这里插入图片描述


推荐阅读
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 解决Sharepoint 2013运行状况分析出现的“一个或多个服务器未响应”问题的方法
    本文介绍了解决Sharepoint 2013运行状况分析中出现的“一个或多个服务器未响应”问题的方法。对于有高要求的客户来说,系统检测问题的存在是不可接受的。文章详细描述了解决该问题的步骤,包括删除服务器、处理分布式缓存留下的记录以及使用代码等方法。同时还提供了相关关键词和错误提示信息,以帮助读者更好地理解和解决该问题。 ... [详细]
  • ElasticSerach初探第一篇认识ES+环境搭建+简单MySQL数据同步+SpringBoot整合ES
    一、认识ElasticSearch是一个基于Lucene的开源搜索引擎,通过简单的RESTfulAPI来隐藏Lucene的复杂性。全文搜索,分析系统&# ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
author-avatar
$Array$
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有