admin管理员组文章数量:1794759
SpringCloud高频重点面试题,看这一篇就够了。
文章目录
- Spring Cloud 相关组件
- 1. Eureka基础知识
- 1.1 什么是服务治理
- 1.2 什么是服务注册与发现
- 1.3 Eureka包含两个组件:Eureka Server 和 Eureka Client
- 1.4 单机Eureka构建步骤
- 1.4.1 服务端
- 1.4.2 客户端
- 1.4.3 将Eureka Client端中的服务消费端注册进Eureka Server称为Service Consumer
- 1.5 集群Eureka构建步骤
- 1.6 负载均衡
- 1.7 Eureka自我保护(CAP里面的AP分支)
- 1.7.1 产生原因
- 1.7.2 什么是自我保护模式?
- 1.7.3 怎么禁止自我保护
- 1.7.4 Eureka的三大角色
- 1.7.5 Eureka和zookeeper的对比
- 2. SpringBoot和SpringCloud的区别?
- 3. 微服务的优缺点
- 4.Ribbon
- 4.1是什么?
- 4.2 负载均衡算法?
- 5.feign
- 5.1 是什么?
- 5.2 能干什么?
- 6.hystrix
- 6.1 服务雪崩
- 6.1.1 雪崩效应
- 6.2 是什么?
- 6.3什么是服务熔断
- 6.3.1 熔断机制
- 6.4服务的降级
- 7.zuul路由网关
- 7.1 Gateway
- 7.1 Gateway特性
- 8.SpringCloud config
- 8.1分布式的配置问题
- 8.2是什么? 怎么用?
- 9.nacos
- 1. nacos是什么?
- 2.命名空间,分组和DataID三者关系,如何分类配置?
- 2.1DataID配置
- 2.2 新建组 TEST_GROUP
- 2.3 新建命名空间
- 3. Nacos集群搭建
- 4. 各种注册中心比较
- 10.sentinel
- 10.1 sentinel是什么?
- 10.2 为什么要用?
- 10.3 Sentinel 分为两个部分
- 10.4 流量控制
- 10.4.1 流控模式之直接失败
- 10.4.2 流控模式之关联
- 10.4.3 流控模式之链路
- 10.4.4 Warm up 预热
- 10.4.5 排队等待
- 10.5 降级规则
- 10.5.1 RT
- 10.5.2 异常比例
- 10.5.3 异常数
- 10.6 热点Key限流
- 10.7 系统规则
- 10.8 sentinelResource
- 10.8.1 按URL访问 rateLimit/byUrl
- 10.8.2 存在问题:代码耦合
- 10.8.3 解决方法
- 10.8.4 实现原理
- 10.9 熔断
- 10.9.1 服务熔断无配置
- 10.9.2 只配置fallback
- 10.9.2 只配置blockHandler
- 10.9.3 fallback和blockHandler都配置
- 10.9.4 异常忽略
- 10.9.5 熔断框架比较
- 10.9.6 限流配置规则持久化
- 11.seata
- 11.1 分布式事务的由来
- 11.2 是什么?
- 11.3 Seata术语
- 11.4 使用
- 11.5 处理过程
- 11.6 如何使用
- 11.7 原理讲解
- 11.7.1 整体机制
- 11.7.2 写隔离
- 11.7.3 读隔离
- 11.7.4 工作机制
- 11.7.4.1 一阶段
- 11.7.4.2 二阶段-回滚
- 11.7.4.3 二阶段-提交
- 11.7.4.4 TCC模式
- 11.7.45 Saga 模式
- 12.消总线
- 12.1 是什么?
- 12.2 能干嘛?
- 12.3 什么是总线?
SpringCloud封装了Netflix公司开发的Eureka模块来实现服务治理
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂。因为管理比较复杂,所以需要使用服务治理,来管理服务与服务之间依赖关系,这样就可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
1.2 什么是服务注册与发现Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心。 而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持 心跳链接 。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信(比如:服务地址、通讯地址等)以别名方式注册到注册中心中。
另一方(消费者/服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用。
RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心(存放服务地址相关信(接口地址))
下左图是Eureka系统架构,右图是Dubbo系统架构
1.3 Eureka包含两个组件:Eureka Server 和 Eureka Client各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将存储所有可用服务节点的信,服务节点的信可以在界面中直观看到。
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中表把这个服务节点移除(默认90秒)
1.4 单机Eureka构建步骤 1.4.1 服务端引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>启动类上加注解:@EnableEurekaServer
/** * @author LongXi * @create 2021-04-29 22:21 */ @SpringBootApplication @EnableEurekaServer public class EurekaMain7001 { public static void main(String[] args) { SpringApplication.run(EurekaMain7001.class,args); } }写配置文件
server: port: 7001 eureka: instance: hostname: localhost client: register-with-eureka: false fetch-registry: false service-url: defaultZone: ${eureka.instance.hostname}:{server.port}/eureka/ 1.4.2 客户端将Eureka Client端中的服务提供端注册进Eureka Server作为Service Provider
引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>配置文件
server: port: 8001 spring: application: name: cloud-payment-service # 入驻Eureka服务注册中心的服务名称 datasource: type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包 url: jdbc:mysql://localhost:3306/cloud20?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root eureka: client: #表示是否将自己注册进EurekaServer默认为true。 register-with-eureka: true #是否从EurekaServer抓取已有的注册信,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 fetchRegistry: true service-url: #单机版 defaultZone: localhost:7001/eureka # 入驻的服务注册中心地址 mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: cn.sher6j.springcloud.entities # 所有Entity别名类所在包启动类加注解:@EnableEurekaClient
/** * @author LongXi * @create 2021-04-25 22:02 */ @SpringBootApplication @EnableEurekaClient public class PaymentMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentMain8001.class, args); } } 1.4.3 将Eureka Client端中的服务消费端注册进Eureka Server称为Service Consumer配置文件
server: port: 80 spring: application: name: cloud-order-service eureka: client: #表示是否将自己注册进EurekaServer默认为true。 register-with-eureka: false #是否从EurekaServer抓取已有的注册信,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 fetchRegistry: true service-url: #单机 defaultZone: localhost:7001/eureka启动类
package cn.sher6j.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloudflix.eureka.EnableEurekaClient; /** * @author sher6j */ @SpringBootApplication @EnableEurekaClient public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class); } }此时,再回看最开始的Eureka系统架构,在服务注册中心和服务提供者没有集群的情况下,7001端口的微服务就对应了服务注册中心,而该服务不需要向服务注册中心注册自己,8001端口的微服务作为服务提供方入住到服务注册中心,8002端口的微服务作为服务消费方也同样注册到服务注册中心
1.5 集群Eureka构建步骤- 服务注册过程将服务信注册进服务注册中心,
- 服务发现过程从服务注册中心上获取服务信,而这个过程的实质就是:将服务名作为key存储,然后根据value取得服务的调用地址。
整个Eureka的过程如果:
那么微服务RPC远程服务调用最核心的是什么呢???
高可用!!!,如果注册中心只有一个,而这个注册中心出现了故障,那么整个微服务就直接GG了,整个微服务环境就不可用了,所以应该搭建Eureka注册中心集群, 实现 负载均衡 + 故障容错
那怎么实现Eureka注册中心的集群呢? 用一句话总结就是——互相注册,相互守望,如下图所示: 服务注册中心实现相互注册,让彼此都知道对方的存在,也就是注册中心集群中的每一个注册中心都知道整个集群中的其他注册中心,比如如果有三个注册服务中心7001,7002,7003,那么就将7002和7003注册给7001, 将7002和7001注册给7003, 将7003和7001注册给7002, 以此类推,而这些个注册服务中心作为一个整体对外看做一个注册服务中心。
此时再回看最开始的Eureka微服务架构图,其集群架构图对应本实例应为:
1.6 负载均衡此时,我们使用80端口的服务消费方来访问 CLOUD-PAYMENT-SERVICE 服务,输入网址localhost/consumer/payment/get/1,但是我们每次得到的数据都是:
{ code: 200, message: "查询数据库成功, 端口号:8001", data: { id: 1, serial: "aaaa001" } }也就是说每次访问的具体微服务都是8001端口的CLOUD-PAYMENT-SERVICE服务,这明显是不符合业务逻辑的,原因就是在消费方代码中我们将服务访问地址写死了,没有实现负载均衡,这显然是不对的,所以我们应该让80访问服务名,而不是具体的服务,同时在配置文件中通过 @LoadBalanced 注解赋予RestTemplate负载均衡能力,该负载均衡默认为轮询方式,所以讲80服务的配置文件修改如下:
package cn.sher6j.springcloud.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /** * @author sher6j */ @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced//使用该注解赋予RestTemplate负载均衡的能力 public RestTemplate getRestTemplate() { return new RestTemplate(); } } //applicationContext.xml <bean id="" class="">然后重启80端口,发现每次访问 CLOUD-PAYMENT-SERVICE 服务时,具体的微服务在8001和8002之间进行轮询切换
1.7 Eureka自我保护(CAP里面的AP分支)保护模式主要用于一组客户端和EurekaServer之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信,不再删除服务注册表中的数据,也就是不会注销任何微服务。
如果在Eureka Server的首页看到以下提示,说明Eureka进入了保护模式(上面 单机Eureka构建步骤中提到过):
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
换句话说就是,某时刻某一个微服务不可用了,Eureka不会立刻清理,而是依旧会对该微服务的信进行保存。
1.7.1 产生原因Q:为什么会产生Eureka自我保护机制???
A:为了防止 EurekaClient可以正常运行,但是与EurekaServer网络不通 情况下,EurekaServer不会立刻将EurekaClient服务剔除。
1.7.2 什么是自我保护模式?默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之前无法正常通信,以上行为可能变得非常危险——因为微服务本身是健康的,只是由于网络问题链接不到EurekaServer,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障,网络延时),那么这个节点就会进入自我保护模式。
在自我保护模式中,EurekaServer会保护服务注册表中的信,不再注销任何服务实例,宁可保留错误的服务注册信,也不盲目注销任何可能健康的服务实例。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
1.7.3 怎么禁止自我保护- 在EurekaServer端修改配置文件即可设置关闭自我保护机制
- 在EurekaClient端修改配置文件
这样就会使EurekaClient客户端的微服务很快死亡。
1.7.4 Eureka的三大角色Zookeeper保证了CP(C:一致性,P:分区容错性),Eureka保证了AP(A:高可用,P:分区容错)
CAP理论:
- Consistency:指数据的强一致性。如果写入某个数据成功,之后读取,读到的都是新写入的数据;如果写入失败,读到的都不是写入失败的数据。
- Availability:指服务的可用性
- Partition-tolerance:指分区容错
SpringBoot专注于快速方便的开发单个个体微服务。
SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,
为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务
SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系
SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
3. 微服务的优缺点 4.Ribbon 4.1是什么?Ribbon是客户端负载均衡的工具。
Ribbon是本地负载均衡客户端 Nginx服务器负载均衡
客户端所有请求都会交给nginx,然后又nginx实现转发请求。
4.2 负载均衡算法?Feign是一个声明式WebService客户端,使用Feign能让编写Web Service客户端更加简单。 它的使用方法式定义一个接口,然后在上面添加注解。
5.2 能干什么?Feign旨在使编写Java Http客户端变得容易。 前面使用Ribbon+RestTemplate时 Feign,创建一个接口+注解 Feign也集成了Ribbon
6.hystrix 6.1 服务雪崩 6.1.1 雪崩效应整体资源快不够了,忍痛将某些服务先关掉,待度过难关,再开启回来。
7.zuul路由网关 7.1 Gateway是Spring Cloud生态系统中的网关,基于WebFlux实现的,而WebFlux框架底层使用的高性能Reactor模式通信框架Netty 在高并发和非阻塞式通信时非常有优势。
7.1 Gateway特性路由,断言,过滤
8.SpringCloud config 8.1分布式的配置问题 8.2是什么? 怎么用? 9.nacos 1. nacos是什么?nacos就是注册中心 + 配置中心的组合
可以替代Eureka做服务注册中心 可以替代Config做配置中心
但是Nacos也有自己的特性,结合【bootstrap.properties 】和【application.properties 】可以实现分区管理、
2.命名空间,分组和DataID三者关系,如何分类配置?多环境,多项目管理出现的问题 问题1:如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢? 问题2:怎么对微服务配置进行管理呢?
解决方案:
NameSpace主要区分部署环境,实现不同环境之间隔离。 Group可以把不通的微服务划分到同一个分组里面去。 Service就是微服务。
2.1DataID配置配置列表和dataID
bootstrap.properties 配置文件
spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.application.name=example【application.properties 】配置文件 略。。。下图有
在 Nacos Spring Cloud 中,dataId 的完整格式如下:
${prefix}-${spring.profiles.active}.${file-extension}通过 Spring Cloud 原生注解 @RefreshScope 实现配置自动更新:
@RestController @RequestMapping("/config") @RefreshScope public class ConfigController { @Value("${useLocalCache:false}") private boolean useLocalCache; @RequestMapping("/get") public boolean get() { return useLocalCache; } }总结如下:
2.2 新建组 TEST_GROUP在配置文件中指定group就可以了。
2.3 新建命名空间配置文件里加上命名空间就可以了
3. Nacos集群搭建
hostname -i 能识别的ip
cluster文件
编辑启动脚本,加入P参数
4. 各种注册中心比较
10.sentinel 10.1 sentinel是什么?
Sentinel: 分布式系统的流量防卫兵
10.2 为什么要用?随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
Sentinel 分为两个部分:
QPS,线程数
QPS:御敌于国门之外 线程数:关门打狗
QPS:会把请求挡在门外面 线程:会把请求放进来,处理不过来的时候才报错,模拟controller里睡0.8秒
开两个浏览器,相当于2个线程,第二个会出错
10.4.2 流控模式之关联我感冒你吃药
支付接口达到阈值以后,限制下订单的接口。
10.4.3 流控模式之链路NodeSelectorSlot 中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root 的虚拟节点,调用链的入口都是这个虚节点的子节点。
一棵典型的调用树如下图所示:
上图中来自入口 Entrance1 和 Entrance2 的请求都调用到了资源 NodeA,
Sentinel 允许只根据某个入口的统计信对资源限流。
比如我们可以设置 strategy 为 RuleConstant.STRATEGY_CHAIN,同时设置 refResource 为 Entrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而不关心经 Entrance2 到来的调用。
一句话:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,则进行限流),API级别的针对来源。
10.4.4 Warm up 预热Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。
通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
概述: 当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。
这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等。
它的实现是在 Guava 的算法的基础上实现的。然而,和 Guava 的场景不同,Guava 的场景主要用于调节请求的间隔,即 Leaky Bucket,而 Sentinel 则主要用于控制每秒的 QPS,即我们满足每秒通过的 QPS 即可,我们不需要关注每个请求的间隔,换言之,我们更像一个 Token Bucket。
我们用桶里剩余的令牌来量化系统的使用率。假设系统每秒的处理能力为 b,系统每处理一个请求,就从桶中取走一个令牌;每秒这个令牌桶会自动掉落b个令牌。令牌桶越满,则说明系统的利用率越低;当令牌桶里的令牌高于某个阈值之后,我们称之为令牌桶"饱和"。
当令牌桶饱和的时候,基于 Guava 的计算上,我们可以推出下面两个公式:
rate©=m*c+ coldrate 其中,rate 为当前请求和上一个请求的间隔时间,而 rate 是和令牌桶中的高于阈值的令牌数量成线形关系的。cold rate 则为当桶满的时候,请求和请求的最大间隔。通常是 coldFactor * rate(stable)。
默认 coldFactor 为 3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
10.4.5 排队等待
postMan模拟
10.5 降级规则
sentinel没有半开状态
10.5.1 RT解释:200毫秒内就的响应,在未来的一秒中,你搞不定,就得跳闸。
用postman测试
模拟
0.2秒就得响应,否则停一秒
10.5.2 异常比例在访问,就testC就挂了,服务降级了。
postman停了之后,不会走服务降级,直接报错
10.5.3 异常数
执行5次之后会报错,被降级
10.6 热点Key限流
删除试一下,blockHandler = “deal_testHotKey”)
所以一定要用第二种
平时qps一秒一次
特殊参数1=5的时候,每秒200
10.7 系统规则可以全局限制,整个系统
10.8 sentinelResource8401引入pom包
点击快了,会限流
关闭8401服务端
流控规则消失了,临时的
10.8.1 按URL访问 rateLimit/byUrl按资源配置异常处理,有就走自己配置,没有,就走系统自带的
10.8.2 存在问题:代码耦合 10.8.3 解决方法自定义 CutomerBlockHandler 方法为static
Handler Exception Block Exception
业务类,指定Class,指定blockHandler QPS超过1,做限流 详细关系
10.8.4 实现原理10.9 熔断 10.9.1 服务熔断无配置
没有配置,直接报出异常,对客户不友好
10.9.2 只配置fallback参数类型,一定要对上,否则兜不了底
10.9.2 只配置blockHandler配置异常数
缺了配置文件,sentinel控制台检测不到
只点一次,直接报error,点2次,被sentinel限流
10.9.3 fallback和blockHandler都配置限流QPS,一秒一个
一秒点一次,报java兜底异常,一秒2次以上,被sentinel限流,
10.9.4 异常忽略参数是4的话,不会被兜底
10.9.5 熔断框架比较 10.9.6 限流配置规则持久化引入依赖 添加配置
新建配置 DataId 就是上面配置的DataId
11.seataseata.io/zh-cn/
11.1 分布式事务的由来全局的事务一致性问题没办法保证。
一句话:一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题。
如何解决:Seata
11.2 是什么?Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。 Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
11.3 Seata术语TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器 定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:
SEATA 的分布式交易解决方案
11.6 如何使用
加全局事务注解 @GlobalTransactionsl
11.7 原理讲解 11.7.1 整体机制两阶段提交协议的演变:
一阶段:业务数据和回滚日志记录(undo_log)在同一个本地事务中提交,释放本地锁和连接资源。
二阶段:
提交异步化,非常快速地完成。 回滚通过一阶段的回滚日志进行反向补偿。以一个示例来说明:
两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。
tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。
tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的 全局锁 ,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待 全局锁 。
tx1 二阶段全局提交,释放 全局锁 。tx2 拿到 全局锁 提交本地事务。
如果 tx1 的二阶段全局回滚,则 tx1 需要重新获取该数据的本地锁,进行反向补偿的更新操作,实现分支的回滚。
此时,如果 tx2 仍在等待该数据的 全局锁,同时持有本地锁,则 tx1 的分支回滚会失败。分支的回滚会一直重试,直到 tx2 的 全局锁 等锁超时,放弃 全局锁 并回滚本地事务释放本地锁,tx1 的分支回滚最终成功。
因为整个过程 全局锁 在 tx1 结束前一直是被 tx1 持有的,所以不会发生 脏写 的问题。
11.7.3 读隔离在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted) 。
如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。
SELECT FOR UPDATE 语句的执行会申请 全局锁 ,如果 全局锁 被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。 这个过程中,查询是被 block 住的,直到 全局锁 拿到,即读取的相关数据是 已提交 的,才返回。
出于总体性能上的考虑,Seata 目前的方案并没有对所有 SELECT 语句都进行代理,仅针对 FOR UPDATE 的 SELECT 语句。
11.7.4 工作机制以一个示例来说明整个 AT 分支的工作过程。
业务表:product
id | bigint(20) | PRI |
name | varchar(100) | |
since | varchar(100) |
AT 分支事务的业务逻辑:
update product set name = 'GTS' where name = 'TXC'; 11.7.4.1 一阶段过程:
得到前镜像:
1 | TXC | 2014 |
得到后镜像:
1 | GTS | 2014 |
AT 模式(参考链接 TBD)基于 支持本地 ACID 事务 的 关系型数据库:
一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。 相应的,TCC 模式,不依赖于底层数据资源的事务支持:
一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。 二阶段 commit 行为:调用 自定义 的 commit 逻辑。 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。 所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。
11.7.45 Saga 模式Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。
适用场景
优势:
缺点:
- 不保证隔离性
配置的
12.2 能干嘛? 12.3 什么是总线?本文标签: 这一面试题重点就够了SpringCloud
版权声明:本文标题:SpringCloud高频重点面试题,看这一篇就够了。 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686858187a111080.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论