SPRINGCLOUD
分布式
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组服务,服务之间互相协调、互相配合、为用户提供最终价值。每个服务运行在其独立的服务中,服务于服务之间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、根据对其进行构建。
分布式架构:服务注册与发现、服务调用、服务熔断、负载均衡、服务降级、服务消息队列、配置中心管理、服务网关、服务监控、全链路追踪、自动化构建部署、服务定时任务。
微服务RPC远程调用最核心的是高可用。
CAP原则:CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。CAP理论关注粒度是数据,而不是整体系统的设计的策略。
Windows下的host文件地址; C:\Windows\System32\drivers\etc。
Application.yml和bootstrap.yml的区别:
Application.yml是用户级的资源配置项
bootstrap.yml是系统级的,优先级更高,比Application.ym先加载。
Springcloud
分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的几何体,俗称微服务全家桶。
RestTemplate提供了多种便捷访问远程Http服务的方法。是一种简单便捷的restful服务模板类,是spring提供的用于访问rest服务的客户端模板工具类。
RestTemplate的方法中的object和entity的区别:object返回对象为响应体中数据转化成的对象,基本可以理解为json。Entity返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等。Entity().getbody()。
注册中心
Eureka
在eureka模块启动类是标注注解@EnableEurekaServer 声明eureka注册中心,访问localhost://端口,则可打开eureka注册中心。
往服务模块pom中添加eureka依赖,服务模块配置文件添加eureka相关配置,模块启动类添加@EnableEurekaClient注解,将服务注册进eureka注册中心。
客户端需要添加resttemllate配置类。
原理:将服务信息注册进注册中心,从注册中心上获取服务信息。
实质:存key服务命令,取value调用地址。
底层是利用httpclient技术实现远程调用。
和zookeeper的区别:当zookeeper的leader出现问题时,会进行自救,救不活,选出新的leader,选举成功才可以访问这个集群。Eureka每个server的内容都是完整的,就算只剩一个eureka可用,整个集群可是可用的。
Eureka通过resttemplate进行远程调用,通过注解@LoadBalanced 开启resttemplate的负载能力。
Actuator 监控和管理Spring Boot应用的工具
http://localhost:8001/actuator/health 查看服务状态 应用健康指标
自我保护机制:基于一组客户端和eureka server之间存在的分区场景下的保护。一旦进入保护状态,eureka server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
某时刻某一个微服务不可用了,eureka不会立即清理,依旧会对该微服务地信息进行保存。
为什么:防止client可以正常运行,但是server网络不通情况下,server不会立刻从client服务剔除。
什么是:默认情况下,eurekaserver在一定时间内没有接受到某个微服务实例的心跳,server将会注销该实例(90秒)。但是当网络分区故障发生时,微服务与server无法正常通信时,就不能被注销。Eureka通过自我保护机制来解决这个问题。当eureka节点在短时间内丢失过多客户端时,那么这个节点就会进入自我保护模式。宁可保留错误的注册信息,也不盲目注销任何可能健康的服务实例。
关闭自我保护机制:修改server端:eureka.server. enable-self-preservation: false
eureka.server. eviction-interval-timer-in-ms: 3000 #发送心跳间隔时间
client端:eureka.instance.lease-renewal-interval-in-seconds: #客户端向服务端发送心跳间隔的时间,默认30秒
eureka.instance.lease-expiration-duration-in-seconds: #客户端收到最后一次心跳后等待时间上限,默认90秒,超时剔除
discovery 服务发现
discovery:服务发现,发现注册经eureka里面的微服务信息。
利用DiscoveryClient获得服务详细信息。
模块启动类添加@EnableDiscoveryClient 用于向注册中心注册服务。
Zookeeper注册中心
添加zookeeper依赖,启动类上加@EnableDiscoveryClient。yml文件添加zookeeper地址:Spring.cloud.zookeeper.connect-string: ip地址:端口2181。
服务注册创建的结点是临时性的。
Consul注册中心
分布式服务发现和配置管理系统。
进入consul.exe目录,
三个注册中心异同
负载均衡
负载均衡分为集中式和进程内 load Balanced
Ribbon
ribbon属于进程内LB。
ribbon是一个软负载均衡的客户端组件。他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。
Ribbon在工作时分为两步,优先选择在同一个区域内负载较少的server。第二部根据用户指定的策略,在server取到的服务注册列表中选择一个地址。其中ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。
更改负载均衡策略需在启动类包外进行修改实现。Ribbon负载均衡策略接口IRule
在启动类上添加@RibbonClient(name="消费服务名",configuration = 修改负载均衡策略类.class)
服务调用
OpenFeign
声明式WebService客户端,让编写Web服务变得非常容易,只需创建一个接口并在接口上添加注解即可。
Feign集成了ribbon,并且通过轮询实现了客户端的负载均衡。而与ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
在消费端使用。 @FeignClient(value = “指定消费服务名”)
Feign自带负载均衡配置项。
feign超时控制
Feign默认一秒钟拿到结果。超时报错。
超时控制配置:
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
feign日志打印
日志级别:
1、NONE:默认的,不显示任何日志。
2、BASIC:仅记录请求方法、URL、响应状态及执行时间。
3、HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息。
4、FULL:除了HEADERS中定义的信息之外,还有请求和响应的中文及元数据。
添加配置:
logging:
level:
#feign日志以什么级别监控哪个接口
com.jayus.service.OrderFeignService: debug
服务降级
Hystrix断路器
处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务崩溃,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控,向调方返回一个符合预期的、可处理的备选响应(fallback),而不是长时间的等待或者抛出异常方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
消费侧、服务侧都可以使用。
作用:服务降级、服务熔断、接近实时的监控。
重要概念:服务降级:当服务器无法响应时,返回一个符合预期可处理的备选响应。兜底的解决方案。程序运行异常、服务熔断触发服务降级、线程池/信号量打满都会导致服务降级。
服务熔断:系统达到最大访问量时,直接拒绝访问,然后调用服务降级的方法并返回友好提示。 不能用->限制访问->恢复。
服务限流:高并发操作,严禁一窝蜂的过来拥挤,排队有序进行。
服务降级
概念:当服务器不能及时对请求作出响应时,返回友好信息。
缺点:代码膨胀,耦合度高。
降级配置:服务提供方在需要做处理的方法添加@HystrixCommand(fallbackMethod = “降低处理方法,兜底方法”,commandProperties = {
@HystrixProperty(name = “execution.isolation.thread.timeoutInMilliseconds”,value = “3000”)})
启动类添加注解@EnableCircuitBreaker
服务消费方:配置文件添加feign.hystrix.enabled: true #开启支持hystrix。在启动类上添加@EnableHystrix。
Class文件解决服务降级处理方法过多的方法:在需要用到服务降级的类上添加@DefaultProperties(defaultFallback = “降级处理方法”),此方法用作默认服务降级处理。在需要使用的类上添加@HystrixCommand,则会使用默认的服务降级处理。需要使用特地用的服务降级的方法自行配置@HystrixCommand注解里面的值。
feign消费者解决服务提供者宕机的方法service接口层:在@FeignClient(value = “调用注册中心服务名”,fallback = 当前接口实现类.class),当有方法调用不通时,会去子类找对应的降级方法,降级方法就是当前调用不通方法的重写方法。
服务熔断
熔断机制是应对雪崩效应的一种微服务链路保护机制。当链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务地调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。通过hystrix实现。
在需要配置熔断服务的类上添加@HystrixCommand(fallbackMethod = “paymentCircuitBreaker_fallback”,commandProperties = {
@HystrixProperty(name = “circuitBreaker.enabled”,value = “true”), //是否开启断路器
@HystrixProperty(name = “circuitBreaker.requestVolumeThreshold”,value = “10”),//请求次数
@HystrixProperty(name = “circuitBreaker.sleepWindowInMilliseconds”,value = “10000”),//时间窗口期 时间范围
@HystrixProperty(name = “circuitBreaker.errorThresholdPercentage”,value = “60”)// 失败率达到多少后跳闸 10秒内10次访问 60%的访问失败 则跳闸 })
当访问多次此服务失败后,此服务会停止被访问。过一段时间后,服务慢慢恢复。
熔断类型
熔断打开:请求不再调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态。
熔断关闭:熔断关闭不会对服务进行熔断。
熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断。
Hystrix dashboard hystrix可视化监控
所有服务提供方添加依赖 actuator 监控信息完善。被监控方。
访问项目的hystrix.stream路径。
服务网关gateway
Gateway
Gateway是在spring生态系统上构建的API网关服务,基于spring5、spring boot 2和project reactor等技术。
旨在提高一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。
Spring gateway是基于webflux框架实现的,而webflux框架底层则使用了高性能的reactor模式通信框架netty。
基于异步非阻塞模型进行开发的。
特性:1、基于spring5、spring boot 2和project reactor构建。
2、动态路由。
3、可以对路由指定Predicate(断言)和Filter(过滤器)
4、集成hystrix的断路器功能
5、集成spring cloud服务发现功能
6、易于编写的predicate(断言)和filter(过滤器)
7、请求限流功能。8、支持路径重写。
三大概念:1、route(路由):构建网关的基本模块,由id,目标url,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
2、predicate(断言):匹配http请求中的所有内容,如果请求与断言相匹配则进行路由。
3、filter(过滤):spring框架的gatewayfilter实例,使用过滤器,可以在请求被路由前或之后对请求进行修改。
核心逻辑:路由转发和执行过滤器链。
配置:添加gateway和eureka依赖,删除web和actuator依赖。将项目注册进注册中心,配置路由详情。则可通过当前项目端口访问路由项目端口。
网关配置两种方法:1、yml文件中配置。
2、代码注入RouteLocator的Bean。需配置多个路由则添加多个方法。
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builer){
RouteLocatorBuilder.Builder routes = builer.routes();
//路由的id 访问 localhost:9527/guonei 会进入https://www.bilibili.com/
routes.route(“path-route2”,
r->r.path("/guonei").uri(“https://www.bilibili.com/”)).build();
return routes.build();}}
根据服务名实现动态路由
cloud: gateway: discovery: locator: enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由。修改路由地址:将uri改为服务名
gateway常用的predicate
可以在yml文件的predicates中配置来限制访问.
Predicate是为了实现一组匹配规则,让请求过来找对应的route进行处理。
Gateway的filter
创建类继承GlobalFilter和Ordered接口,重写filter和getOrder()方法,getorder()设置过滤器优先级,filter进行拦截。
Springcloud config 分布式服务配置中心
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度都相对较小,因此系统中会出现大量的微服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中动态的配置管理设施是必不可少的。
Springcloud提供了configserver来解决这个问题。
Springcloud config分为服务端和客户端两部分。
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来配置服务器并未客户端提供获取配置信息,加密/解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便地管理和访问配置内容。
服务端配置:添加config-server依赖,yml配置文件添加gitbug项目路径:spring☁️config:
server: git: #uri: git@github.com:jayusHZK/springcloud-config.git #github上面的git仓库名 uri: https://github.com/jayusHZK/springcloud-config.git
search-paths:
- springcloud-config #搜索目录
label: master # 读取分支
客户端配置:添加starter-config依赖,将配置文件名改为bootstrap.yml,优先加载。添加配置:cloud: config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上述三个综合:master分支上的config-dev.yml的配置文件被读取 3344
uri: http://localhost:3344
服务中心客户端不及时响应
重启服务中心客户端。
添加actuator监控依赖,配置文件暴露端口:#暴露监控端点
management:
endpoint:
web:
exposure:
include: “*”
业务类添加@RefreshScope注解,刷新。然后发送一个post请求刷新服务客户端。Http://xxxx:8080/actuator/refresh
消息总线
实现分布式自动刷新配置功能。Springcloud bus配合springcloud config 使用可以实现配置的动态刷新。
Bus
支持两种消息代理,RabbitMQ和Kafka。 RabbitMQ默认账号密码:guest
管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、时间推送等,也可以当作微服务间的通信通道。
为什么被称为总线:微服务架构中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所以微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和浪费,所以称它为消息总线。在总线的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
设计思想:1、利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置
2、利用消息总线触发一个服务端configserver的/bus/refresh端点,而刷新所有客户端的配置。
缺点:方式1违背了微服务地单一性,因为微服务本身就是业务模块,它不应该承担配置刷新的职责。破坏了微服务各节点的对等性。局限性,如果想做到自动刷新,会要做更多修改。
配置:1、服务中心服务端添加bus-amqp依赖,配置文件添加RabbitMQ配置:rabbitmq:
host: localhost 和暴露bus刷新配置的端点: management:
port: 5672 endpoints: #配置bus刷新配置的端点
username: guest web: exposure:
password: guest include: ‘bus-refresh’
2、客户端配置:添加bus-amqp依赖,配置文件添加RabbitMQ配置用户名等信息。
这时候不能做到自动刷新,只是发送一次post请求Http://服务端地址:端口/actuator/bus_refresh,刷新全部服务端。
定点更新
指定某一个客户端配置修改生效,发送post请求:Http://服务端地址:端口/actuator/bus_refresh/spring服务名:端口
Springcloud stream
构建消息微服务的框架。屏蔽底层消息中间件的差异,降低切换成本,同一消息的编程模型。
应用程序通过inputs(消费者)和outputs(生产者)来与springcloud stream中binder对象交互。
通过我们配置来binding(绑定),而springcloud stream的binder对象负责与消息中间件交互。
所以,我们只需要搞清楚如何来与springcloud stream交互就可以方便使用消息驱动的方式。
通过使用spring integration来连接消息代理中间件以实现消息时间驱动。
为供应商的消息中间件产品提供了个性化的自动化配置实现,。引用了发布-订阅、消费组、分区的三个核心概念。
仅支持rabbitmq和kafka。
设计理念:标准MQ,消息必须走消息通道,消息通信方式遵循发布-订阅模式。
Source是生产者,sink是消费者。
配置
生产者项目添加stream-rabbit依赖,rabbit为使用的消息队列工具。Yml文件添加配置:参考项目cloud-stream-provider8801,output配置。通过@EnableBinding(Source.class)定义消息的发送管道,通过MessageChannel对象构建消息。
消费者项目添加stream-rabbit依赖,yml文件添加input配置,参考cloud-stream-consumer8002,
解决消息被重复消费
使用stream的消息分组解决。Stream处于同一个组时竞争关系,能够保证消息只能其中一个服务消费一次。不同组可以重复消费。
在yml文件的消息绑定中添加group: 组名,即可对服务消费者进行分组。同组成员消费服务类似负载均衡。
消息持久化
生产者往消息容器中发生了消息,消费者服务器后启动,消费者能不能接受到消息。
Stream不会保留默认的消息分组,只保留自定义的消息分组。
分布式请求链路跟踪器springcloudsleuth
在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点调用来协同产生最后的请求结果,每一个前端请求都会形成一个复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起这个请求最后的失败。
Springcloudsleuth提供了一套完整的服务跟踪的解决方案,在分布式系统中提供追踪解决方案并且兼容支持了zipkin。Sleuth监控,zipkin展现。 Kafka+elk
下载zipkin.jar包并用java -jar运行。访问http://localhost:9411/zipkin/
名词解释:Trace:类似于树结构的span集合,表示一条调用链路,存在唯一表示
Span:表示调用链路来源,通俗的理解span就是一次请求信息。
配置
在需要监控的项目添加zipkin依赖,添加配置:
Cloud alibaba
服务限流降级、服务注册发现、分布式配置管理、消息驱动能力、阿里云对象存储、分布式任务调度。
添加spring-cloud-alibaba-dependencies依赖。
Nacos服务注册和配置中心
下载地址:https://github.com/alibaba/nacos/releases
进入下载文件解压bin目录,稠密,cmd运行starter.cmd.
访问http://localhost:8848/nacos/#/login 账号密码 nacos
Naming Configuration Service
更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 =eureka+config+bus.
配置
生产者添加alibaba-nacos-discovery依赖,yml文件添加cloud: nacos: discovery: server-addr: localhost:8848 # nacos地址和监控,启动类添加@EnableDiscoveryClient。
消费者添加alibaba-nacos-discovery依赖,yml文件添加cloud: nacos: discovery: server-addr: localhost:8848 # nacos地址和监控,启动类添加@EnableDiscoveryClient。添加resttemplate模板配置类
Nacos自带负载均衡功能。
Nacos同时支持AP和CP,不支持CAP。支持AP和CP的切换。C是所以节点在同一时间看到的数据是一致的,A的定义是所有的请求都会有回应。
AP为了服务的可能性而减弱了一致性,一次AP模式只支持注册临时实例
CP模式则支持注册持久化实例,此时是以raft协议为集群运行模式,该模式下注册实例必须先注册服务,如果服务不存在,则会返回错误。
切换命令:curl -X PUT “$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverModel&value=CP?AP”
配置中心
项目添加alibaba-nacos-discovery和alibaba-nacos-config依赖,配置两个yml文件,application和bootstrap,bootstrap配置配置服务中心,读取文件名为
s
p
r
i
n
g
.
a
p
p
l
i
c
a
t
i
o
n
.
n
a
m
e
−
{spring.application.name}-
spring.application.name−{spring.profile.active}.${spring.cloud.nacos.config.file-extension}
Nacos命名空间
Namespace-group-dataID,例:public default nacos config client dev.yaml。
Namespace配置写id,group写自己配置的,dataid自写。
Nacos集群和持久化
将nacos数据库改为mysql数据库;执行nacos\conf下的nacos-mysql.sql文件,在nacos\conf下的application.properties添加数据库信息。
Linux集群搭建:用nginx+三台nacos集群+mysql数据库
Sentinel
下载地址:https://github.com/alibaba/sentinel/releases
实现熔断和限流。
Cmd运行下载jar文件,访问localhost:8080,账号密码为sentinel
Cloudalibaba-sentinel-service8401
配置
添加alibaba-nacos-discovery、sentinel-datasource-nocas、alibaba-sentinel、openfeign依赖,配置文件:
流控
QPS和线程数的区别:QPS请求被挡在外面,线程数是线程阻塞,在里面。
QPS(每秒的请求数量):当调用该api的QPS达到阈值时,进行限流。线程数:当调用该api的线程数达到阈值的时候,进行限流。
流控模式:1、直接:api达到限流条件时,直接限流
2、关联:关联的资源达到阈值时,限流自己。同一个controller下的服务,A满了,B限流。
3、链路:只记录指定链路上的流量(指定资源从入口资源尽量的流量,如果达到阈值,就进行限流)[api级别的针对来源]。
流控效果:1、warm up 预热形式,加载因子为3。
2、排队等待:请求排队处理,匀速排队。
服务降级:通过熔断进行服务降级。熔断没有半开状态。
1、RT:响应时间
2、异常比例:特定时间内异常次数占总次数比例。
3、异常数:特定时间内异常次数达到阈值。
流控和服务降级的区别:流控限制外部流量,服务降级处理内部异常。
热点key限流:根据请求带参限流。在接受请求方法上添加@SentinelResource(value = “hotkey”),value名称唯一。
Sentinel添加一个热点规则,资源名与@SentinelResource 的value一致。用到热点限流,需要配置兜底页面,错误显示在界面对用户不友好。自配置兜底方法需添加参数BlockException e
热点限流可配置例外项,当参数值为指定值时,可放大阈值。SentinelResource不管运行时异常。
配置自定义限流:@SentinelResource(value = “handlerException”,blockHandlerClass = CustomerBloockHandler.class
,blockHandler = “handlerException2”) //blockHandlerClass类 handlerException2方法名
服务熔断
Sentinel整合ribbon+openfeign+fallback。
@SentinelResource(value = “fallback”,blockHandler = “blockHandler”,fallback = “fallback”) blockHandler管理sentinel违规,fallback管理java异常。
@SentinelResource (exceptionsToIgnore={exception.class})对该类型异常不作fallback兜底。
Feign:一般用于消费测。引入依赖,添加feign的配置。
Feign服务熔断:@FeignClient(value = “nacos-provider-payment9003”,fallback = PaymentServiceImpl.class) fallback为当前接口实现类。
Sentinel规则持久化
Sentinel服务重启,规则需要重新配置。
解决:将配置规则持久化及nacos,只要刷新8401的某个rest地址,sentinel控制台就可以看到,只要nacos的配置不删除,针对8401上的sentinel上的流控规则则持续有效。
项目添加sentinel-datasource-nacos依赖,用作持久化,yml添加配置文件
Nacos添加服务名的配置dataid,添加如下内容
resource 资源名称
limitApp 来源应用
grade 阈值类型,0线程数,1 QPS
count 单机阈值
strategy 流控模式 0表示直接 1表示管理 2表示链路
controlBehavior 流控效果 0表示快速失败 1表示warm up 2表示排队等待
clusterMode 是否集群
Seata处理分布式事务
下载地址:https://github.com/seata/seata/releases。
单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的引用,分别使用三个独立的数据源。业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性有笨的事务来保证,但是全局的数据一致性没法保证。一次业务操作需要跨多个数据源或需要
多个系统进行远程调用,就会产生分布式事务问题。
分布式处理事务的一ID+三组件模块
一ID;Transation ID XID 全局唯一的事务ID。
三组件:Transaction Coordonator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
Transaction Manager™:控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
Resource Manager(RM):控制分支事务,负责分支注册、状态汇报,并接受事务协调器的指令,驱动分支(本地)事务的提交和回滚。
处理过程:1、TM向TC开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID。
2、XID在微服务调用链路的上下文传播。
3、RM向TC注册分支事务,将其纳入XID对应去啊女警事务的管辖。
4、TM向TC发起针对XID的全局提交或回滚决议。
5、TC调度XID下管辖的全部分支事务完成提交或回滚请求。
@globalTransactional
环境搭建
修改Seate目录的conf的file.conf文件,修改自定义事务组名称+事务日志存储模式为db+数据库连接信息。
修改store.mode为db,修改数据库连接信息。数据库新建seate库,建表语句在conf的db_store.sql。修改registry.conf,registry.type=”nacos”,指明连接nacos,修改nacos连接信息。在每个业务库中运行conf的db_undo_log.sql文件的建表语句,回滚日志表。
配置
com.alibaba.cloud
spring-cloud-starter-alibaba-seata
io.seata
seata-all
io.seata
seata-all
0.9.0
@GlobalTransacutional(name=””,rollback=Exception.class),name为唯一标识,bollback为遇到什么异常回滚。
Seata原理
TM事务发起方,RM事务参与方, seata通过XID协调。
分布式事务流程:
1、TM开启分布式事务(TM向TC注册全局事务记录)
2、按业务场景,编排数据库、服务等事务内资源(RM向TC汇报资源准备状态)
3、TM结束分布式事务,事务一阶段结束()TM通知TC提交/回滚分布式事务)
4、TC汇总事务信息,决定分布式事务是提交还是回滚
5、TC通知所有RM提交/回滚资源,事务二阶段结束。
一阶段找到业务sql要更新的数据,在数据更新前,保存前置镜像,更新后保存后置镜像,生成行锁。二阶段提交顺利,将一阶段保存的镜像数据和行锁删掉,完成数据清理。提交失败,回滚,用前置镜像还原业务数据,还原前校验脏写,对比当前数据库数据和后置镜像,如果完全一致,可以还原,不一致说明有脏写需转人工处理。还原后镜像和行锁。
seata数据库保留库信息,undo_log保存镜像信息。
雪花算法 Snowslafe
生成ID能够按照时间有序生成。按时间趋势递增。
算法生成的id的结果是一个64bit大小的整数,为一个Long型(转换成字符串后长度最多19)。
分布式系统内不会产生ID碰撞(由datacenter和workerld作区分)并且效率较高。
优点:1、毫秒数在高位,自增序列在低位,整个id都是趋势递增。2、不依赖数据库第三方系统,以服务的方式部署,稳定性更高,删除ID的性能也是非常高。3、可以根据自身业务特性分配bit位,非常灵活。
缺点:1、依赖时钟机器,如果时钟回拨,会导致重复id生成。2、在单机上是递增的,但是由于设计到分布式环境,每台机器不可能完全同步,有时候会出现不是全局递增的情况
其他补充:
Maven
dependencyManagement和Dependencies的区别:
dependencyManagement(pom中带有此标签就是父工程):提供一种管理依赖版本号的方式。能让所有在子项目中引用一个依赖而不用显式的列出版本号。让多个子项目都引用一个依赖,可以避免在每个使用的子项目里都声明一个版本号,这样想升级或切换版本只需该父工程的版本号。只声明依赖,不实现引入。子项目写了依赖,才会继承版本号,version和scope都读取自父pom。
Dependencies:自定义标签管理
replace into t_test(test) values(‘a’);
select LAST_INSERT_ID();