SpringCloud

笔者的SpringCloud是跟着黑马的张虎翼老师学的,张老师绝对目前为止我见过课件ppt最好的老师。讲课真的很通透,Cloud的里面涉及到了很多新的名词,老师课件中也给出了,所以这篇文章很多都是截图。这篇文章记录了很多东西,一些名词,问题回答,还有我对一些知识的看法啥的,还是比较全的。由于时间关系,课程最后的面试篇我没有学,以后有时间再回来补。

文章目录

基础篇
课程概要

image-20240123082628509

image-20240123081006638


一些概念

image-20240124080404270

image-20240123082511639

常见组件

image-20240124080517947



微服务拆分时的几个原则

不同微服务,不要重复开发相同业务

微服务数据独立,不要访问其它微服务的数据库

微服务可以将自己的业务暴露为接口,供其它微服务调用



Eureka的作用

image-20240123095843789

image-20240123100103107



Ribbon

在微服务架构中,Ribbon(Netflix Ribbon)是一个用于实现客户端负载均衡的开源库。它主要用于在分布式系统中的服务调用中,帮助客户端应用程序选择可用的服务实例,并分配请求的负载,以提高系统的可用性和性能。
以下是 Ribbon 的主要特点和作用:

  1. 负载均衡: Ribbon 提供了多种负载均衡算法,包括轮询、随机、加权随机、加权轮询等。通过这些算法,Ribbon可以在多个服务实例之间分配请求,避免单一实例的过载,提高整体系统的稳定性和性能。
  2. 服务实例的动态发现: Ribbon 可以与服务注册中心(如Eureka、Consul等)集成,动态地获取可用的服务实例列表。这意味着当新的服务实例启动或旧的实例下线时,Ribbon能够自动感知并更新可用实例列表,确保负载均衡的准确性。
  3. 容错处理: Ribbon 具有容错机制,能够在某个服务实例不可用时,自动切换到其他可用实例,提高系统的健壮性。
  4. 自定义配置: 开发人员可以通过配置文件或编程方式进行定制化的配置,包括负载均衡算法、超时设置等,以适应不同场景和需求。
  5. 集成其他Netflix组件: Ribbon通常与其他Netflix组件如Eureka、Hystrix等一起使用,形成完整的微服务解决方案。例如,通过与Hystrix整合,可以实现对服务调用的熔断和降级。
    总体而言,Ribbon在微服务架构中扮演着重要的角色,帮助开发人员实现对服务调用的负载均衡和容错处理,从而提升整个微服务系统的可用性和性能。

image-20240123143101631

image-20240123143427897



另开一个实例-IDEA使用技巧

image-20240123145204647

一般端口会冲突,所以我们得在VM options 里面加个参数 如 -Dxxxx

image-20240123145252093



自定义负载均衡策略

image-20240123150423482



###### Nacos负载均衡

image-20240123171917452



###### Nacos环境隔离

image-20240123191554463



Nacos和Eureka对比

image-20240123193037771

image-20240123193050939



Nacos配置管理

image-20240123201837518

image-20240123211407959



ConfigurationProperties

@ConfigurationProperties 注解是 Spring 框架中用于将外部配置文件的属性映射到 Java 对象的注解。这个注解主要用于将配置文件中的属性值绑定到一个 JavaBean(POJO,普通的 Java 对象)上,方便在应用程序中使用这些配置属性。
以下是关于 @ConfigurationProperties 注解的一些关键信息:

  1. 用途: 主要用于将配置文件中的属性值映射到 JavaBean 中,使得可以通过对象的属性来访问配置。
  2. 配置类: 通常,使用 @ConfigurationProperties 注解的类被称为配置类,这个类中的属性对应了配置文件中的属性。
  3. 前缀匹配: 注解中可以指定一个前缀,用于匹配配置文件中的属性。只有以指定前缀开头的属性才会被映射到该类的属性上。
  4. 支持类型安全: 通过将配置属性映射到具体的 Java 类型,提供了类型安全的配置访问方式,避免了在代码中直接使用字符串来获取属性值。
    下面是一个简单的示例,演示如何使用 @ConfigurationProperties 注解:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
    private String appName;
    private int maxConnections;
    // Getters and setters
    // Other methods
}

在上述例子中,假设配置文件中有属性 myapp.appNamemyapp.maxConnections,使用 @ConfigurationProperties 注解的类 MyAppProperties 可以将这些属性映射到 appNamemaxConnections 属性上。
在 Spring Boot 应用程序中,通常还需要在主应用程序类上添加 @EnableConfigurationProperties(MyAppProperties.class) 注解,以启用对该配置类的支持。
使用 @ConfigurationProperties 注解有助于将配置信息从配置文件中解耦,使得配置更具有可维护性和可读性。



feign

image-20240124113141250



网关

image-20240124162442034



GatewayFilter

image-20240124194036503

image-20240124194013934



适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的对象进行合作**。这种模式允许一个类的接口变成客户端所期望的另一种接口,从而使原本由于接口不匹配而无法一起工作的类能够协同工作。**
具体解释:

  • 角色:
    • 目标接口(Target Interface): 客户端期望的接口,适配器模式通过适配器将其他接口转换成目标接口。
    • 适配器(Adapter): 实现目标接口,并持有一个被适配对象的引用。它将客户端的请求转换为对被适配对象的调用。
    • 被适配对象(Adaptee): 需要被适配的类或接口,其接口与目标接口不兼容。
    • 客户端(Client): 通过目标接口与适配器交互,无需知道适配器内部是如何实现的。
      应用场景:
  1. 接口不兼容: 当现有系统的接口与新的要求不兼容时,使用适配器模式可以让它们协同工作而无需修改原有代码。
  2. 封装已有功能: 如果已有的一些类的功能是我们需要的,但它们的接口不符合系统的需要,可以使用适配器模式进行封装,以便在系统中复用这些功能。
  3. 与第三方库协作: 在使用第三方库或模块时,为了适应自己的系统,可以使用适配器模式进行接口转换。
    示例:
    考虑一个简单的例子,有一个英国插头的电器,但在中国的插座上无法直接使用。这时可以引入一个适配器,将英国插头转换为中国插头,使电器能够在中国使用。
// 目标接口
interface ChineseSocket {
    void insertChinesePlug();
}
// 中国插座
class ChinaSocket implements ChineseSocket {
    public void insertChinesePlug() {
        System.out.println("插入中国插头");
    }
}
// 英国电器,拥有英国插头
class BritishDevice {
    void plugInBritishSocket() {
        System.out.println("插入英国插头");
    }
}
// 适配器,实现目标接口并持有英国电器的引用
class Adapter implements ChineseSocket {
    private BritishDevice britishDevice;
    Adapter(BritishDevice britishDevice) {
        this.britishDevice = britishDevice;
    }
    public void insertChinesePlug() {
        britishDevice.plugInBritishSocket();
    }
}
// 客户端
public class Client {
    public static void main(String[] args) {
        // 使用适配器将英国电器适配到中国插座
        BritishDevice britishDevice = new BritishDevice();
        Adapter adapter = new Adapter(britishDevice);
        adapter.insertChinesePlug();
    }
}

在这个例子中,BritishDevice代表英国电器,ChinaSocket代表中国插座,而Adapter充当适配器的角色,使得英国电器能够插入中国插座。这样,通过适配器模式,我们实现了不同接口之间的协同工作。



##### Docker

image-20240124195805895

Ubuntu和CentOS都是基于Linux内核,无非是系统应用不同,提供的函数库有差异

因为系统函数库被docker一起打包了,所以与系统软件无关了,仅依靠Linux内核!!

image-20240124195929382

image-20240124200207025



docker和虚拟机的区别

image-20240125084804789



镜像和容器

image-20240125085151985

需要啥就在自己那里复制一份(不会影响镜像)

image-20240125085240347



镜像常见命令

image-20240124211415606



容器常见命令

image-20240125090613527



为什么需要端口映射

我们知道运行的容器是隔离的,我们直接访问它的端口是得不到的,所以需要做一个映射

image-20240125092017999



数据卷

image-20240125101839097

image-20240125101859387



数据卷常用命令

image-20240125101955759

image-20240125103117443

image-20240125112357280



镜像的结构

image-20240125151220133



Dockerfile语法

image-20240125153002680

MQ
同步调用存在的问题

image-20240125173545731

异步通信

image-20240125174407303



RabbitMQ

image-20240125205332163

image-20240125205425060



常见消息模型

image-20240125210151485



@RunWith(SpringRunner.class)

在Spring框架中,@RunWith(SpringRunner.class)是一个JUnit运行器(Runner),用于在测试过程中启动Spring容器。这通常用于基于注解的测试类,以确保在测试执行期间能够正确加载和初始化Spring上下文
详细解释:

  • JUnit 4和JUnit 5: @RunWith注解是JUnit 4中的一项功能。在JUnit 5中,不再使用@RunWith,而是使用@ExtendWith(SpringExtension.class)
  • SpringRunner: SpringRunner是Spring提供的JUnit 4运行器,用于在测试时创建和管理Spring应用程序上下文。
  • 使用方式: 在JUnit测试类上使用@RunWith(SpringRunner.class)注解,或者在JUnit 5中使用@ExtendWith(SpringExtension.class)
@RunWith(SpringRunner.class)
@SpringBootTest
public class MySpringTest {
    // 测试代码
}
  • @SpringBootTest: @SpringBootTest注解用于指示该测试类是一个Spring Boot测试,会自动加载Spring Boot应用程序上下文。
    作用:
  1. 启动Spring容器: @RunWith(SpringRunner.class)确保在运行测试之前启动Spring容器,以便测试类中可以使用依赖注入和其他Spring功能。
  2. 自动配置: @SpringBootTest则会自动配置Spring Boot应用程序上下文,包括自动扫描和加载所有的Bean。
  3. 方便集成测试: 这样的配置使得编写集成测试变得更加方便,可以使用Spring的依赖注入、事务管理等功能进行测试。
    示例:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyIntegrationTest {
    @Autowired
    private MyService myService;
    @Test
    public void testServiceMethod() {
        // 测试代码,可以使用@Autowired注入的Bean
        myService.someMethod();
    }
}

在这个示例中,@RunWith(SpringRunner.class)确保在运行测试之前启动Spring容器,而@SpringBootTest自动配置了Spring Boot应用程序上下文,使得可以在测试中使用自动注入的MyService bean。



AMQP

image-20240125213712363



elasticseartch

image-20240126154827021

image-20240126154955271



B树

B树(B-tree)是一种自平衡的树状数据结构,通常应用于文件系统和数据库中的索引结构。它具有以下特点和操作:

结构特点:

  1. 节点结构: B树的节点包含多个键值和对应的子节点指针。

  2. 顺序性: 节点中的键值按照升序排列。

  3. 平衡性: B树保持平衡,确保所有叶子节点位于同一层,从而保持树的高度相对较低。

  4. 范围查询: B树支持范围查询,因为键值之间的顺序性有助于快速定位范围。

操作:

  1. 插入: 插入操作从根节点开始,按照键值大小逐级向下查找合适的叶子节点,然后在叶子节点中插入键值,并保持节点的平衡性。
  2. 删除: 删除操作也从根节点开始,定位到要删除的键值所在的叶子节点,进行删除操作,并根据需要进行节点的合并或者重新分配。
  3. 查找: 查找操作从根节点开始,按照键值大小逐级向下查找,直到找到对应的叶子节点,然后返回对应的数据。

优点:

  1. 平衡性: B树保持平衡,有助于维持较低的树高度,提高查找效率。
  2. 适用于外部存储: B树适用于大规模数据存储和索引,特别是对于需要磁盘访问的数据库和文件系统。
  3. 范围查询: 由于键值的顺序性,B树能够支持高效的范围查询操作。

适用场景:

  1. 数据库索引: B树常被用作数据库的索引结构,支持高效的查询操作。
  2. 文件系统: 文件系统中的索引结构也常使用B树,用于管理文件和目录的索引。
  3. 键值存储: 对于键值存储等需要快速查找和范围查询的场景,B树也是一种常见的选择。
    总体而言,B树作为一种自平衡的树状数据结构,在处理大规模数据和索引时具有广泛的应用。其平衡性和高效性使得它成为许多存储系统中的重要组成部分。


B+树

B+树是一种常见的树形数据结构,通常用于数据库和文件系统中的索引结构。它是B树的一种变体,在B树的基础上进行了一些优化,主要用于磁盘存储和索引查找操作
以下是关于B+树的详细解释:

结构特点:

  1. 节点结构: B+树的内部节点和叶子节点结构不同。
    • 内部节点: 内部节点仅包含键值和指向子节点的指针
    • 叶子节点: 叶子节点包含键值和对应数据的指针,叶子节点之间通过指针连接形成链表,便于范围查询。
  2. 顺序性: B+树中的节点按照键值顺序存储,使得范围查询更加高效。
  3. 平衡性: B+树保持平衡,确保树的高度相对较低,提高查找效率。
  4. 叶子节点指针: 所有叶子节点之间通过指针连接成链表,便于范围查询和顺序遍历。

操作:

  1. 插入: 插入操作从根节点开始,按照键值大小逐级向下查找合适的叶子节点,然后在叶子节点中插入键值,并保持节点的平衡性。
  2. 删除: 删除操作也从根节点开始,定位到要删除的键值所在的叶子节点,进行删除操作,并根据需要进行节点的合并或者重新分配。
  3. 查找: 查找操作从根节点开始,按照键值大小逐级向下查找,直到找到对应的叶子节点,然后返回对应的数据。

优点:

  1. 高效的范围查询: 叶子节点之间通过指针连接,使得范围查询更加高效。
  2. 高效的顺序遍历: 叶子节点之间按照键值顺序存储,可以方便地进行顺序遍历。
  3. 平衡性: B+树保持平衡,具有较低的高度,使得查找效率稳定。
  4. 适用于外部存储: B+树适用于大规模数据存储和索引,特别是对于需要磁盘访问的数据库和文件系统。

适用场景:

  1. 数据库索引: B+树常被用作数据库的索引结构,支持高效的查询和范围操作。
  2. 文件系统: 文件系统中的索引结构也常使用B+树,用于管理文件和目录的索引。
  3. 键值存储: 对于键值存储等需要快速查找和范围查询的场景,B+树也是一个合适的选择。
    总之,B+树作为一种经典的树形数据结构,在数据库和文件系统等领域有着广泛的应用,其平衡性和高效性使得它成为处理大规模数据和索引的重要工具之一。


B树和B+树的区别

B树和B+树是两种树形数据结构,它们在结构和应用方面存在一些关键区别。以下是它们之间的主要区别:

  1. 节点结构:
  • B树: B树的内部节点和叶子节点都存储键值对。每个内部节点包含一组键值,以及比键值多一个的子节点指针。在B树中,数据同时存储在叶子节点和内部节点。
  • B+树: B+树的内部节点只包含键值,不存储数据,而所有数据都存储在叶子节点中。叶子节点通过指针连接成链表,形成一个有序序列。
  1. 顺序性和范围查询:
  • B树: 由于B树的数据分布在内部节点和叶子节点,范围查询可能需要在不同层级的节点中进行查找,相对较慢。
  • B+树: B+树的所有数据都存储在叶子节点中,且叶子节点通过指针连接成链表,因此范围查询非常高效。顺序遍历也变得简单,只需遍历叶子节点链表即可。
  1. 叶子节点指针:
  • B树: B树的叶子节点并不一定通过指针连接成链表。
  • B+树: B+树的叶子节点必须通过指针连接成有序链表,方便范围查询和顺序遍历。
  1. 插入和删除操作:
  • B树: 插入和删除可能需要更新内部节点和叶子节点,操作相对复杂。
  • B+树: 插入和删除只涉及到叶子节点,内部节点仅用于导航,因此操作相对简单。
  1. 适用场景:
  • B树: 适用于需要频繁进行范围查询的场景,如数据库索引。
  • B+树: 更适用于文件系统和数据库索引,特别是对于范围查询和顺序遍历操作要求较高的场景。
    总体而言,B+树在范围查询和顺序遍历等操作上更有优势,而B树则可能在某些特定场景下有其应用价值。选择使用哪种树形数据结构通常取决于具体应用的需求。


相关概念

image-20240126161127478

image-20240126161053255

image-20240127144348055



ES和MySQL对比

image-20240126162433592

image-20240126162522998



Mapping属性

image-20240127152519085



@BeforeEach@AfterEach

在Java中,@BeforeEach@AfterEach 是JUnit 5测试框架中的注解,用于执行在每个测试方法运行之前和之后的操作。这些注解提供了更灵活的测试生命周期管理,相比于JUnit 4中的 @Before@After 更为强大。

  1. @BeforeEach 注解:
    • 用于标注在方法上,该方法将在每个测试方法执行之前运行。
    • 常见用途包括在测试之前进行一些初始化操作,确保测试执行的前提条件得到满足。
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    public class MyTest {
        @BeforeEach
        public void setUp() {
            // 执行测试前的初始化操作
        }
        @Test
        public void myTestMethod() {
            // 测试方法
        }
    }
    
  2. @AfterEach 注解:
    • 用于标注在方法上,该方法将在每个测试方法执行之后运行。
    • 常见用途包括在测试执行后进行一些清理或资源释放操作。
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.Test;
    public class MyTest {
        @Test
        public void myTestMethod() {
            // 测试方法
        }
        @AfterEach
        public void tearDown() {
            // 执行测试后的清理操作
        }
    

这些注解使得在测试方法级别更容易执行一些针对性的操作,而不仅仅是在整个测试类级别。它们是JUnit 5中引入的改进,提供了更清晰、灵活的测试生命周期管理方式。



把java对象转为Json

JSON.toJSONString(xxx);



DSL Query的分类

image-20240127213514379



DSL Query的基本语法

image-20240127213953842



RestClient查询的特性

image-20240129082939259

Java代码上的差异主要是request.source().query()中的参数了。同样是利用QueryBuilders提供的方法:

比如复合查询就是一个典型的例子

image-20240129083131677



复合查询

image-20240128094307380



请求参数

目前见到的请求参数的方式有四种

  1. header 参数,暂时没发现要写啥

  2. path 参数,也就是路径请求 如、aa/bb/{id} , 对应参数代码 :@PathVariable(“id”) Integer id

  3. body 参数,用 @RequestBody EmployeeDTO employeeDTO 只能拿对象或者string,Map接受

  4. query 参数 , page?page=1&pageSize=10 .直接拿对应的参数接收,不需要注解。



聚合

image-20240129090133376

image-20240128211222693



###### 分词器结构

image-20240205103243965

自定义分词器

image-20240205092722030



修改hotel结构

image-20240205111130591



completion类型

在Elasticsearch中,completion类型是一种专门用于自动补全建议的字段类型。它可以用于实现类似搜索引擎中的自动补全功能。

image-20240206082231440

suggest

这段DSL是用于执行一个Elasticsearch的搜索请求,具体解析如下:

GET /hotel/_search
{
  "suggest": {
    "suggetions": {
      "text": "h",
      "completion": {
        "field": "suggestion",
        "skip_duplicates": "true",
        "size": 10
      }
    }
  }
}
  • GET /hotel/_search:这是一个HTTP GET请求,用于搜索名为"hotel"的索引中的文档。_search表示执行搜索操作。
  • "suggest":这是一个搜索建议(suggestion)的部分,用于在搜索过程中提供自动补全的建议。
  • "suggetions":这是一个自定义的建议名称,可以根据自己的需求进行命名。
  • "text": "h":这是要进行自动补全的文本内容,这里设置为"h"。
  • "completion":这是一个自动补全建议类型,用于在搜索过程中提供自动补全的建议。
  • "field": "suggestion":这是指定自动补全建议的字段名,这里设置为"suggestion"。这个字段应该是一个已经配置了自动补全功能的字段。
  • "skip_duplicates": "true":这是一个可选的参数,用于指定是否跳过重复的建议。这里设置为"true"表示跳过重复的建议。
  • "size": 10:这是指定返回的建议数量,这里设置为10,表示返回最多10个建议。
    通过执行这个DSL,你可以在名为"hotel"的索引中搜索以"h"开头的文本,并获取最多10个自动补全的建议。建议结果将返回在响应中。请注意,这只是一个简化的示例,实际使用中可能需要根据具体的索引和需求进行适当的调整。


new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false)

这段代码是一个Java方法,用于创建一个TopicExchange对象并返回。在MQ(消息队列)中,TopicExchange是一种通过主题(Topic)进行消息路由的交换机类型。
具体解释如下:

  • public TopicExchange topicExchange():这是一个公共方法,返回一个TopicExchange对象。
  • new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false):这是创建TopicExchange对象的语法,其中包含以下参数:
    • MqConstants.HOTEL_EXCHANGE:这是一个常量,表示TopicExchange的名称。根据代码中的命名约定,它可能是一个名为"HOTEL_EXCHANGE"的常量,用于指定特定的交换机名称。
    • true:这是一个布尔值,表示是否持久化(durable)该交换机。如果设置为true,则表示在服务器重启后仍然存在。
    • false:这是一个布尔值,表示是否自动删除(auto-delete)该交换机。如果设置为false,则表示交换机不会在至少一个绑定到它的队列解除绑定后自动删除。
      通过调用这个方法,可以创建一个具有指定名称、持久化设置和自动删除设置的TopicExchange对象。该对象可以用于在MQ中进行消息的发布和订阅,使用主题进行消息的路由和过滤。
      请注意,代码中可能还有其他相关的类和方法,这段代码只是其中的一部分。要完全理解这段代码的含义,可能需要查看其他相关的代码和上下文。


集群相关概念

image-20240206080646274



高级篇
解决雪崩问题的4种方法

image-20240206084123695

image-20240206084329842

image-20240207094455005



服务技术对比

image-20240206085307296



修改sentinel的参数

image-20240206085826683



netstat -tulnp

输出所有端口

sentinel控制台

sentinel-限流的神器!

image-20240206100635646



族点链路

image-20240207094643174

image-20240206101007656



三种流控模式

image-20240206113946117



标记其他方法成为资源

image-20240206143225201



流控效果

image-20240206153025935

image-20240206154344905



热点参数限流

image-20240206155847570


小细节

image-20240206155918595

所以我们得在controller方法上加上@SentinelResource注解



复习 – feign

远程调用的前提是他们已经加入到注册中心了

之前我们用nacos + RestTemplate的代码是这样子的

image-20240206165243873

不够简洁

我们使用Feign ,编写一个userClient的客户端

里面有对应的封装方法,调用对应方法就相当于发送了一个远程请求

image-20240206165644761

image-20240206165329207



image-20240206165312898



@Lazy注解

@Lazy注解是Spring框架中的一个注解,用于延迟加载(懒加载)Bean的初始化。当一个Bean被标记为@Lazy时,它将在首次使用时才会被实例化,而不是在应用程序启动时立即进行实例化
使用@Lazy注解可以提高应用程序的性能,特别是在存在大量Bean的情况下。通过延迟加载,可以减少启动时间和内存消耗,只有在需要使用该Bean时才会进行实例化。
以下是@Lazy注解的使用示例:

@Lazy
@Component
public class MyBean {
    // Bean的定义
}

在上述示例中,MyBean被标记为@Lazy注解,表示它是一个延迟加载的Bean。当容器加载时,MyBean不会立即被实例化,只有在其他组件中引用到MyBean时才会被实例化。
需要注意的是,@Lazy注解只能用于单例作用域的Bean,因为原型(prototype)作用域的Bean在每次请求时都会创建一个新实例,不存在延迟加载的概念。
另外,@Lazy注解也可以应用于@Configuration注解标记的配置类或@Bean注解标记的方法,以实现延迟加载配置类或Bean方法。
希望这个解释能够帮助到你。如果你还有其他问题,请随时提问。



高扇出

在软件开发中,“高扇出”(High Fan-Out)是一个描述代码或系统设计的概念。
扇出"指的是一个组件或模块对其他组件或模块的直接依赖数量。当一个组件对许多其他组件具有直接依赖关系时,我们称之为"高扇出”。
高扇出可能导致以下问题:

  1. 耦合度增加:高扇出会增加组件之间的耦合度,使得系统更难以理解和维护。当一个组件发生变化时,它可能会影响到许多其他组件,导致代码修改的范围扩大。
  2. 依赖关系复杂:高扇出会导致复杂的依赖关系网络,使得系统的设计和架构更加复杂。这可能增加代码的理解难度,并导致困难的调试和排错。
  3. 可测试性下降:高扇出会增加代码的复杂性,使得单元测试和集成测试变得更加困难。当一个组件变化时,需要测试和验证的范围也会增加。
    为了避免高扇出,可以采取以下措施:
  4. 单一责任原则:确保每个组件或模块只负责一个明确的任务或功能。这样可以将代码分解为独立且低耦合的组件,减少直接依赖的数量。
  5. 抽象和接口:使用抽象和接口来定义组件之间的协议和通信方式。这样可以降低具体实现之间的直接依赖,提高代码的可扩展性和可替换性。
  6. 依赖注入:使用依赖注入框架来管理组件之间的依赖关系,减少手动处理依赖的代码。通过依赖注入,可以将依赖关系外部化,并将其交由框架来处理。
    总之,高扇出是指一个组件对其他组件的直接依赖数量较多。


线程隔离

image-20240206201456437



熔断降级

image-20240206202745285



java里面try-catch异常和直接向外抛异常有什么区别

在Java中,异常处理的方式有两种:try-catch块和向外抛出异常(throws)。

  1. try-catch块:
    使用try-catch块可以捕获并处理异常。在try块中,我们编写可能会抛出异常的代码。如果在try块中抛出了异常,异常会被catch块捕获,然后可以在catch块中对异常进行处理。这样可以防止异常的传播,程序可以继续执行后续的代码。
    例如:
    try {
        // 可能会抛出异常的代码
    } catch (ExceptionType e) {
        // 异常处理代码
    }
    
    try-catch块的优点是能够捕获并处理异常,使程序能够继续执行。它适用于我们可以解决或处理异常的情况。
  2. 向外抛出异常(throws):
    当我们无法处理异常或者希望将异常传递给上层调用者来处理时,我们可以使用throws关键字将异常向外抛出。这样做会将异常传递给调用者,调用者可以选择捕获异常或继续向上抛出。
    例如:
    public void method() throws ExceptionType {
        // 可能会抛出异常的代码
    }
    
    向外抛出异常的优点是能够将异常的处理责任交给调用者,使得代码更加灵活。它适用于我们无法解决或处理异常的情况,或者希望将异常传递给上层调用者来处理。
    总结:
  • 使用try-catch块可以捕获并处理异常,使程序能够继续执行。


那为什么有时候我们会在还catch 中 new RuntimeException呢?
  • throw exception直接终止方法,或者退出循环。

  • try catch还要继续处理方法余下的逻辑,或者不结束循环

  • 还可以自定义异常信息

  • image-20240206210420090

    image-20240206210019463

try catch 还能输出1 ,要是直接throw 抛出异常就输出不了 1 了



授权规则

为什么需要授权规则?

当我们的微服务地址没有限定内网范围,不法分子直接绕过我们的网关直接来访问我们,这时候我们就需要授权规则了

image-20240207100401032

image-20240207100252217



常见的异常类

image-20240207105502041



为什么有了网关还要设置授权规则

我是这样认为的
我觉得限制内网访问和设置授权规则是对网关的进一步完善。打个比喻,网关就是服务的大门,但是不法分子不走大门,专门翻墙进去,设置内网访问就是把墙加高了(不给他们翻墙的机会),而设置授权规则就是派人去墙内蹲着,看到有人翻墙进来了,就把他们请出去

sentinel配置持久化

image-20240207115424816

image-20240207115435897



如何改源码

大致流程就是解压源码

在IDE里面打开,修改里面的代码

然后打包,生成jar包

运行jar包

主要是体会这个流程

image-20240207121459531


分布式事务
概念

image-20240208093520152

image-20240208093604431



CAP定理

image-20240208095304140

image-20240208100122434



BASE理论

image-20240208101943121



事务协调者

image-20240208102123744



解决分布式事务的思想

image-20240208102408384



Seata

image-20240208102635446



Seata架构

image-20240208103346686



Seata配置对应关系

image-20240208161007728

image-20240208162004675

XA模式

image-20240208195541981

image-20240208183228497

image-20240208183305580
AT模式

用的最多

image-20240208195935761

image-20240208200127691



AT模式和XA模式的区别

image-20240208200445980



AT的脏写问题

image-20240208201721077





使用全局锁

seata管理的事务在对同一份资源进行操作时,需要获得全局锁

image-20240208201659329



那非seata管理的事务对资源进行操作呢 – 不需要获取全局锁

保存两次快照,

before-image 用来为了数据回滚的

after-image 用来判断当前的信息和 after-image里面的信息是否一致(类似查看版本号吧 – 乐观锁),不一致说明数据还被其他人操作过了,就不能正常的回滚,此时就需要人工介入

image-20240208202345481

image-20240208203649700

乐观锁和悲观锁

乐观锁(Optimistic Locking)和悲观锁(Pessimistic Locking)是在并发编程中使用的两种不同的锁策略,用于处理多线程或多个事务同时访问共享资源的情况。它们的主要区别在于对资源访问的态度和处理方式。

  1. 乐观锁(Optimistic Locking):
    • 乐观锁认为并发访问的冲突是不常见的。因此,它在读取数据时不立即加锁,而是在更新数据时进行冲突检测。
    • 当要更新数据时,乐观锁会比较此前读取的数据版本与当前实际数据版本是否一致。如果一致,表示没有其他线程修改过数据,可以进行更新;如果不一致,表示有其他线程修改过数据,更新操作可能会失败。
    • 乐观锁通常使用版本号或时间戳等方式来标识数据版本。
    • 如果更新操作失败,乐观锁可能选择重试操作或者向用户报告冲突。
  2. 悲观锁(Pessimistic Locking):
    • 悲观锁认为并发访问的冲突是常见的。因此,它在读取数据时会立即加锁,以防止其他线程修改数据
    • 当线程获得了锁之后,其他线程需要等待锁的释放才能访问资源。
    • 悲观锁通常使用互斥锁(Mutex)或读写锁(ReadWrite Lock)等机制来实现。
    • 悲观锁可以确保数据的一致性,但会导致并发性能下降。
      总体来说,乐观锁适用于并发冲突较少的情况,它通过延迟锁的应用来提高并发性能。而悲观锁适用于并发冲突较多的情况,它通过立即加锁来确保数据的一致性。
      在实际应用中,选择乐观锁还是悲观锁取决于具体的业务需求、数据访问模式以及对数据一致性和并发性能的考量。
      希望能够帮助你理解乐观锁和悲观锁的区别。如果有任何进一步的问题,请随时提问。


TCC模式

image-20240208212250891

image-20240208212328607

image-20240208212607192

空回滚和业务悬挂是什么意思

image-20240208213401368



saga模式

用的很少

image-20240208224211821



四种模式总结

image-20240208224650026

弱一致其实就是最终一致

总结:解决事务问题无非就是加锁,或者补偿,上面4种模式无非是的锁不同,补偿方式的不同



非关系型数据库(NoSQL)

非关系型数据库(NoSQL)是一种与传统关系型数据库不同的数据库类型。与关系型数据库使用表和固定的模式来存储数据不同,非关系型数据库采用了更灵活的数据模型来存储和检索数据。
非关系型数据库的特点包括:

  1. 无固定的模式:非关系型数据库不需要预先定义表结构、字段和关系,可以根据需要动态地存储和检索数据。这使得非关系型数据库适用于需要频繁更改数据模型或存储半结构化/非结构化数据的场景。
  2. 可扩展性:非关系型数据库通常采用分布式架构,可以轻松地扩展到多个节点,以适应大规模的数据和高并发访问需求
  3. 高性能:由于非关系型数据库通常采用了更简单的数据模型和存储结构,以及更高效的查询和索引机制,因此在某些情况下可以提供更高的性能和吞吐量。
  4. 多样化的数据模型:非关系型数据库提供了多种数据模型,如键值存储、文档数据库、列族数据库、图形数据库等。每种数据模型都专注于不同类型的数据和查询需求,使得非关系型数据库在不同场景下具有更好的灵活性和效率。
    非关系型数据库的一些常见实现包括MongoDB、Cassandra、Redis、Elasticsearch等。
    需要注意的是,非关系型数据库并不是对关系型数据库的替代,而是在特定的应用场景下提供了更好的选择。根据具体的业务需求和数据特点,选择适合的数据库类型是非常重要的。



为什么说Elasticsearch是非关系型数据库

Elasticsearch被广泛认为是非关系型数据库,尽管它在某些方面与传统的关系型数据库有一些相似之处。以下是一些解释为什么Elasticsearch被归类为非关系型数据库的原因:

  1. 数据模型:Elasticsearch采用了文档型数据库的数据模型。它使用的是基于文档的存储方式,而不是传统关系型数据库中的表和行。每个文档是一个自包含的数据单元,可以是JSON或类似格式的结构化数据。这种灵活的数据模型允许在文档中存储和索引各种类型的数据,而无需预定义模式。
  2. 缺乏关系:与关系型数据库不同,Elasticsearch不支持表之间的关系。它没有内置的外键或表连接功能。相反,它专注于文档的全文搜索和分析,以及通过丰富的查询语法对文档进行灵活的检索和分析。
  3. 分布式架构:Elasticsearch是为大规模数据和高性能而设计的。它采用分布式架构,可以水平扩展到多个节点,以处理海量数据和高并发访问。这种分布式架构使得Elasticsearch在处理大型数据集和高负载环境下表现出色。
  4. 全文搜索和分析:Elasticsearch是一个强大的全文搜索引擎,具有高性能的全文搜索和复杂的文本分析功能。这使得它在处理结构化和非结构化数据的搜索和分析方面非常强大,特别适用于日志分析、数据挖掘和实时搜索等应用场景。
    尽管Elasticsearch在某些方面与关系型数据库有一些相似之处,例如数据持久性和数据一致性,但它的数据模型和功能集使其更适合于非关系型数据库的范畴。



查看mysql版本号

image-20240208105437368



更换java版本

我们下载然后安装jdk,系统会在环境变量里面为我们配置

image-20240208134834324

两个环境变量,系统会去寻找最上面的

image-20240208134933081

我把系统的删了,这样用户的就能生效

image-20240208135341908

如何切换jdk版本呢

电脑D盘里面我设置了两个文件夹(8 和 17),所以以后要更换java环境的时候去把JAVA_HOME里面的值改改就好了

image-20240208135529732

核心思想 本质 原理

原理上一台电脑是可以启动多个不同版本的jdk服务的,只不过我们只能在它对应的bin目录下执行相关操作,但是我们只要在环境变量里面配置了我们的bin目录的地址,那当我们在其他目录执行相关java命令时,系统在当前目录不能识别指令,就会去环境变量里面找。



redis高级篇

image-20240212084239794



RDB

image-20240212084718085

image-20240212091739792

image-20240212091950957



AOF

image-20240212092309253

RDB和AOF比较

image-20240212095110354

.



为什么要搭建redis主从架构

image-20240212095425266



数据同步原理

image-20240212110704811

image-20240212110728055

image-20240212111301757



关于增量同步

image-20240212112008616



优化方案

image-20240212112535240



小总结
image-20240212112657449
哨兵

image-20240212113343127

image-20240212202235527

高级篇一开始的sentinel和这里的sentinel 不一样,那个是sentinel控制台



分片集群

image-20240212211029567



集群监测原理

image-20240213085926022

哈希插槽

image-20240212213751840

多级缓存
关于缓存

image-20240213095423868

多级缓存

image-20240213151309622



caffeine

可以实现JVM的进程缓存

image-20240213095621194



Lua

image-20240213151441495

image-20240213151621452

image-20240213152248807



OpenResty

image-20240213153730384



缓存预热

image-20240213171704602



序列化

序列化是指将对象转换为可以存储或传输的格式的过程,通常是将对象转换为字节流或文本格式。这样做的目的是为了能够在不同的系统之间进行数据交换或持久化存储,而不受编程语言或硬件平台的限制。
在序列化过程中,对象的状态(即数据)被转换为字节流或文本,并在需要时可以通过反序列化操作重新构造成原始对象。序列化通常用于网络通信、数据持久化(如将对象保存到文件或数据库)、内存中对象的状态保存等场景。
在Java中,可以通过实现Serializable接口来指示一个类是可序列化的,然后使用Java的序列化机制将对象转换为字节流。其他编程语言也提供了类似的机制来进行对象的序列化和反序列化操作。
总的来说,序列化是一种重要的机制,它使得不同系统之间可以方便地交换数据,并且在许多应用程序中都有广泛的应用。



缓存同步策略

image-20240214155738366



Canal

image-20240214155940707

image-20240214160236195

image-20240214160324367



MySQL主从同步

MySQL的主从同步是指在MySQL数据库中,通过配置一个主服务器(Master)和一个或多个从服务器(Slave),使得主服务器上的数据变化能够自动同步到从服务器上,以实现数据的备份、负载均衡和容灾备份等目的。
主从同步的工作原理如下:

  1. 主服务器(Master):主服务器是数据库的主要操作节点,负责接收和处理客户端的写操作(INSERT、UPDATE、DELETE等)。主服务器上的数据变化会被记录到二进制日志(Binary Log)中。
  2. 从服务器(Slave):从服务器是主服务器的备份节点,它会连接到主服务器并请求复制主服务器上的数据变化。从服务器会先从主服务器上获取一份数据库的快照(Snapshot),然后根据主服务器的二进制日志进行增量同步,将主服务器上的数据变化应用到自己的数据库中,从而与主服务器保持同步。
    主从同步的配置步骤如下:
  3. 在主服务器上启用二进制日志(Binary Logging),以记录主服务器上的数据变化。
  4. 在主服务器上创建一个用于从服务器复制的专用用户,并授予复制权限。
  5. 在从服务器上设置主服务器的连接信息,并启动从服务器的复制进程。
  6. 在从服务器上配置需要复制的数据库或表。
    通过主从同步,可以实现以下功能和优势:
  • 数据备份和恢复:从服务器上的数据是主服务器的一个实时副本,可以用于灾难恢复和数据备份。
  • 负载均衡:可以将读操作分摊到从服务器上,减轻主服务器的负载,提高系统的并发处理能力。
  • 容灾备份:当主服务器发生故障时,可以快速切换到从服务器继续提供服务,保证系统的高可用性和容灾备份。
    需要注意的是,主从同步虽然可以提供数据的冗余备份和负载均衡,但并不适用于所有的应用场景,需要根据实际情况进行合理配置和使用。同时,在配置和维护主从同步时,也需要注意数据一致性、网络带宽、延迟和故障恢复等方面的问题。


MQ常见问题

image-20240214165745251
.(img-qUVexc2D-1708078713999)]



序列化

序列化是指将对象转换为可以存储或传输的格式的过程,通常是将对象转换为字节流或文本格式。这样做的目的是为了能够在不同的系统之间进行数据交换或持久化存储,而不受编程语言或硬件平台的限制。
在序列化过程中,对象的状态(即数据)被转换为字节流或文本,并在需要时可以通过反序列化操作重新构造成原始对象。序列化通常用于网络通信、数据持久化(如将对象保存到文件或数据库)、内存中对象的状态保存等场景。
在Java中,可以通过实现Serializable接口来指示一个类是可序列化的,然后使用Java的序列化机制将对象转换为字节流。其他编程语言也提供了类似的机制来进行对象的序列化和反序列化操作。
总的来说,序列化是一种重要的机制,它使得不同系统之间可以方便地交换数据,并且在许多应用程序中都有广泛的应用。



缓存同步策略

[外链图片转存中…(img-3ic1KhN6-1708078713999)]

Canal

[外链图片转存中…(img-4kCQZEJ0-1708078713999)]

[外链图片转存中…(img-g95jmwyL-1708078714000)]

[外链图片转存中…(img-VSDBL0f7-1708078714000)]

MySQL主从同步

MySQL的主从同步是指在MySQL数据库中,通过配置一个主服务器(Master)和一个或多个从服务器(Slave),使得主服务器上的数据变化能够自动同步到从服务器上,以实现数据的备份、负载均衡和容灾备份等目的。
主从同步的工作原理如下:

  1. 主服务器(Master):主服务器是数据库的主要操作节点,负责接收和处理客户端的写操作(INSERT、UPDATE、DELETE等)。主服务器上的数据变化会被记录到二进制日志(Binary Log)中。
  2. 从服务器(Slave):从服务器是主服务器的备份节点,它会连接到主服务器并请求复制主服务器上的数据变化。从服务器会先从主服务器上获取一份数据库的快照(Snapshot),然后根据主服务器的二进制日志进行增量同步,将主服务器上的数据变化应用到自己的数据库中,从而与主服务器保持同步。
    主从同步的配置步骤如下:
  3. 在主服务器上启用二进制日志(Binary Logging),以记录主服务器上的数据变化。
  4. 在主服务器上创建一个用于从服务器复制的专用用户,并授予复制权限。
  5. 在从服务器上设置主服务器的连接信息,并启动从服务器的复制进程。
  6. 在从服务器上配置需要复制的数据库或表。
    通过主从同步,可以实现以下功能和优势:
  • 数据备份和恢复:从服务器上的数据是主服务器的一个实时副本,可以用于灾难恢复和数据备份。
  • 负载均衡:可以将读操作分摊到从服务器上,减轻主服务器的负载,提高系统的并发处理能力。
  • 容灾备份:当主服务器发生故障时,可以快速切换到从服务器继续提供服务,保证系统的高可用性和容灾备份。
    需要注意的是,主从同步虽然可以提供数据的冗余备份和负载均衡,但并不适用于所有的应用场景,需要根据实际情况进行合理配置和使用。同时,在配置和维护主从同步时,也需要注意数据一致性、网络带宽、延迟和故障恢复等方面的问题。
MQ常见问题

[外链图片转存中…(img-IndfXLlU-1708078714001)]





此文章用于笔者记录学习,也希望对你有帮助

  • 22
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Cloud是一个用于构建分布式系统的开发工具集合。它提供了一些常用的组件和框架,包括服务注册和发现、负载均衡、断路器、分布式配置等等。在使用Spring Cloud时,有一些常见的错误和注意事项需要注意。 首先,关于Spring Boot和Spring Cloud版本对应错误。在使用Spring Cloud时,需要确保Spring Boot和Spring Cloud的版本兼容。不同版本之间可能存在依赖冲突或不兼容的情况,因此需要根据官方文档或者相关文档来选择合适的版本。 另外,Spring Cloud Config是一个用于集中管理和动态获取配置的工具。它支持从Git、SVN或本地文件系统中获取配置文件,并提供了服务器和客户端支持。你可以通过官方使用说明文档了解更多关于Spring Cloud Config的详细信息。 此外,关于选择使用Nacos还是Eureka作为服务注册和发现组件的问题。Nacos是一个功能更强大的服务注册和发现组件,它整合了Spring Cloud Eureka、Spring Cloud Config和Spring Cloud Bus的功能。使用Nacos可以实现配置的中心动态刷新,而不需要为配置中心新增集群或使用消息队列。另一方面,Eureka是Spring Cloud原生全家桶的一部分,相对来说更加稳定一些。选择使用哪个组件需要根据具体的需求和项目特点来决定。 综上所述,Spring Cloud是一个用于构建分布式系统的开发工具集合,它提供了一些常用的组件和框架。在使用Spring Cloud时,需要注意Spring Boot和Spring Cloud版本的兼容性,并可以使用Spring Cloud Config来动态获取配置。同时,可以选择使用Nacos或Eureka作为服务注册和发现组件,具体选择需要根据项目需求来决定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值