目录

后端JAVA八股文笔记

系列 - 八股文

笔记基于 https://javaguide.cn/ 、以及黑马教程,重点归纳。

问题:你项目中什么场景使用了 Redis?

  • 回答 缓存:那就会接着问
    • 缓存三兄弟(穿透、击穿、雪崩)、双写一致、持久化、数据过期策略,数据淘汰策略
  • 回答 分布式锁
    • setnx、redisson
  • 回答 消息队列、延迟队列
    • 何种数据类型

发生了 缓存穿透、击穿、雪崩,该如何解决?

查询数据流程是:先查redis,没有就查数据库并且 缓存和返回 结果。

布隆过滤器:检索一个元素是否在集合中,我是用 redisson 实现的。 先创建一个很大的 bit数组,里面只存储0和1,当添加一个元素时会就行 三次哈希函数 计算,将对应数组下标设置为 1,表明 Key 的存在。 当然会存在一定误判,一般不超过5%,误判是必然存在的,增大数组长度解决,但会增加占用。

  • 缓存击穿

    • 当缓存过期的时候,恰好有大量的并发请求,这堆请求可能会瞬间把DB压垮
  • 解决办法

    • 互斥锁:强一致、性能差
      • 线程1:查询缓存发现过期,则添加 互斥锁,去查询数据库重建缓存,最后释放
      • 线程2:会一直等待、重试,直到 释放锁为止
    • 逻辑过期:高可用,性能优,不保证数据绝对一致
      • 线程1:先添加 互斥,然后开启一个新的线程2去重建缓存,自身直接返回 数据过期
      • 线程3:如果存在 ,则直接返回 数据过期
  • 缓存雪崩

    • 同一时间大量的缓存key失效,或者redis宕机,导致大量的请求抵达数据库。
  • 解决办法

    • key失效:TTL添加随机值
    • redis宕机:集群,哨兵模式、集群模式
    • 添加限流策略:nginx、spring gateway
    • 多级缓存:Guava、Caffeine

redis作为缓存,mysql数据库怎么与redis进行同步?(双写一致性)

一定要先介绍业务背景 例子1:我项目中是将文章热点数据写入缓存的,因此对实时性要求没这么高,所以采用异步的方案同步数据 例子2:我项目中是把商品库存写入缓存的,因此为了保证数据强一致,采用 redisson 的读写锁来同步数据。

  • 一致性要求高

    • 共享锁:读锁 readLock,其他线程只能读,不能写
    • 排他锁:独占锁 writeLock,其他线程不能读也不能写
  • 允许延迟一致(异步通知)

    • MQ:更新数据后通知缓存删除
    • canal:伪装成数据库slave,读取binlog数据更新缓存
  • 延迟双删

    • 先删除缓存、再修改数据库、最后延迟一段时间再删除缓存
      • 尽可能降低脏数据的风险

持久化

  • 持久化分为:RDB和AOF
  • 区别是什么:
    • RDB是一个快照文件,把内存数据写到硬盘,恢复直接从快照文件中恢复
    • AOF是追加文件,当操作写命令时,都会存储到该文件,恢复数据则重新执行一遍命令。
  • 那个恢复更快呢?
    • RDB因为是二进制文件所以更快,但可能会丢数据。我们项目中也是用AOF恢复数据,虽然慢一点,但丢数据的风险会小很多,刷盘策略我们是每秒批量写入命令。
RDBAOF
持久化方式定时对整个内存做快照记录每一次执行的命令
数据完整性不完整,两次备份之间会丢失相对完整,取决于刷盘策略
文件大小会有压缩,文件体积小记录命令,文件体积很大
宕机恢复速度很快
数据恢复优先级低,因为数据完整性不如AOF高,因为数据完整性更高
系统资源占用高,大量CPU和内存消耗低,主要是磁盘IO资源
但AOF重写时会占用大量CPU和内存资源
使用场景可以容忍数分钟的数据丢失,追求更快的启动速度对数据安全性要求较高常见

接下来是持久化命令的补充

  • RDB
    • 页表:记录虚拟地址与物理地址的映射关系
    • 主进程通过操作页表的 虚拟内存地址 去操作 物理内存数据
    • bgsave:复制页表到子进程,读取数据写入到RDB文件。
$ save   # 由Redis主进程来执行RDB,会阻塞所有命令
ok
$ bgsave   # 开启子进程执行RDB,避免主进程受到影响
Background saving started

刷盘策略,打开 redis.conf

# 900秒内,如果至少有1个key被修改,则执行bgsave
save 900 1 
save 300 10 
save 60 10000
  • AOF
# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"

# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

# AOF文件比上次文件 增长超过多少百分比则触发重写  
auto-aof-rewrite-percentage 100  
# AOF文件体积最小多大以上才触发重写  
auto-aof-rewrite-min-size 64mb

redis的key过期以后,会立即删除吗?

  • 数据过期策略
  • 惰性删除
    • 访问 key 的时候判断是否过期,过期则删除。
    • 缺点是不访问就会一直存在内存在
  • 定期删除
    • 定期检查一定量的key是否过期,SLOW模式和FAST模式

缓存过多,内存被占满了怎么办?

  • 数据淘汰策略有八个
    • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。
    • volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
    • allkeys-random:对全体key ,随机进行淘汰。
    • volatile-random:对设置了TTL的key ,随机进行淘汰。
    • allkeys-lru: 对全体key,基于LRU算法进行淘汰
    • volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰
    • allkeys-lfu: 对全体key,基于LFU算法进行淘汰
    • volatile-lfu: 对设置了TTL的key,基于LFU算法进行淘汰
  • 使用建议:
    • allkeys-lru:将最常访问的保留在内存中
    • 如果所有数据访问频率差别不大,可以使用 allkeys-random ,全部全部随机
    • 有置顶要求可以使用 volatile-lru。(有一部分数据不需要被淘汰)
    • 短时间高频率可以使用 LFU 算法的 LRU:淘汰最近最少使用的,最后一次访问时间最早的 LFU:最少使用频率。

redis分布式锁,怎么实现?

使用 redisson 实现的分布式锁,底层是 SETNX 和 LUA 脚本(保证原子星)

redis分布式锁,如何控制锁的有效时长?

WarchDog 看门狗,当一个线程获取锁后,会持续给持有锁的线程 续期(默认是10秒续一次)

这个锁可以重入吗?

可以,通过判断是否是当前线程实现,使用 hash结构,存储线程信息和重入次数

这个锁能解决主从数据一直问题吗?

不能,虽然可以通过 红锁 解决,但是性能低。如果非要保持,建议使用 zookeeper 实现分布式锁。

Redis集群有哪些方案?

主从复制、哨兵模式、Redis分片集群

介绍一下主从同步

master负责写数据,slave负责读数据,master写入数据之后,需要把数据同步到slave中。

主从同步数据的流程

一般分为全量同步和增量同步

  • 全量同步

    • 第一步:slave请求master同步数据,其中slave会携带自己的 replication idoffset 偏移量
    • 第二步:master判断,replid不相同则代表第一次同步,master需要返回自己的replication id和offset偏移量。相同则不用动,代表不是第一次同步
    • 第三步:主执行 bgsave 生成并发送RDB文件,从去执行
    • 之后master会记录所有命令,记录到 repl_baklog ,发送他给slave。
  • 增量备份

    • 第一和第二步流程和上面一样
    • 第三步:master发送 repl_baklogoffset 之后的数据

怎么保证Redis的高并发高可用

可以使用哨兵模式

  • 哨兵模式
    • 监控:检查主slave状态
    • 自动故障恢复:如果master宕机,将一个 slave 提升为 `master
    • 通知:发生故障转移以后,将 新master 的信息发送给Redis客户端

你的redis是单点还是集群?

1主1从+哨兵就可以了

redis 集群脑裂解决方案

  • 出现原因:
    • 由于 master 与 slave 处于不同的网络分区,导致哨兵没法使用心跳感知到master,通过选举方式提升了一个 slave 为 master,这也就存在两个 master。
  • 影响
    • 主程序继续向 老master 写入数据,网络恢复以后 老master 被强制降为 slave,导致数据丢失。
  • 解决:修改redis配置,设置最少从节点数量和缩短主从数据同步延迟。
min-replicas-to-write 1   表示最少的salve节点为1个
min-replicas-max-lag 5  表示数据复制和同步的延迟不能超过5秒

Redis的分片集群有什么作用?

有多个 master,每个master都可以保存不同数据 每个master自带多个slave 可以互相监控彼此状态 客户端可以访问集群任意节点,最终会转发到正确节点

Redis分片集群中数据是怎么存储和读取的?

有 16384 个哈希槽,集群中每个主节点绑定了一定范围的哈希槽范围,key通过CRC16校验后对16384取模来决定放置哪个槽,通过槽找到对应的节点进行存储。

Redis是单线程的,但是为什么还那么快?

基于内存、C语言、多路I/O复用模型,非阻塞IO、单线程就避免不必要的上下文切换和竞争条件。 例如:BGSAVEBGREWRITEAOF都是在后台执行操作,不影响主线程的正常使用,不会产生阻塞。

能解释一下I/O多路复用模型

指利用单个线程来同时监听多个Socket,采用的epoll模式实现,当Socket就绪时,epoll会通知用户进程写入Socket到用户空间,则不需要挨个遍历询问。

如何定位慢查询?

我当初是用了 Skywalking 可以检测哪个接口慢,如果是mysql的问题,我会开启 慢日志查询,我当初是设置2秒,超过这个数就会记录到日志中。

# 开启MySQL慢日志查询开关  
slow_query_log=1  
# 设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志  
long_query_time=2

那这个SQL语句执行很慢,如何分析呢?

  • 我是用MYSQL自带的分析工具 explain 查看执行情况
  • 通过 keykey_len 判断是否命中索引
  • 再通过 type 判断是否存在全索引扫描或全盘扫描
    • type的指:性能由好到差为NULL、system、const、eq_ref、ref、range、 index、all
  • 最后通过 extra 判断是否出现了回表,可以通过添加索引或修改返回字段解决

了解过索引吗?(什么是索引)

通过索引列对数据进行排序,有序,提高查询效率,降低数据库 IO 成本

索引的底层数据结构了解过吗?

MySQL的InnoDB引擎采用的B+树的数据结构来存储索引 特点:非叶子节点只存储指针,只有叶子节点才存储数据,便于扫库和区间查询,叶子节点是一个双向链表。

而B树:他是叶子也非叶子节点都存储数据

什么是聚簇索引什么是非聚簇索引

也可以称之为 聚集索引,例如给ID添加索引,叶子节点存储一整行数据 row,由主键组成。只能有一个

name 字段添加索引(称之为二级索引),那就是 非聚簇索引,数据和索引会分开存储(叶子节点存储的是主键值)。可以有多个

知道什么是回表查询吗?

通过二级索引找到对应的主键值,然后再通过主键值查询聚簇索引中对应的整行数据的过程。

知道什么叫覆盖索引吗?

在SELECT查询中,返回的列全部能在索引中找到,避免了回表查询

-- 覆盖索引
select * from tb_user where id = 1
-- 覆盖索引
select idname from tb_user where name = Arm
-- 非覆盖索引, 需要回表查询
select idnamegender from tb_user where name = Arm

MySQL超大分页怎么处理?

在数据量比较大时,limit分页查询,需要对数据进行排序,效率低 解决方案:覆盖索引+子查询

-- 需要 11 秒
select * from tb_sku limit 9000000,10

-- 只需要 7 秒
select *  
from tb_sku t,  
     (select id from tb_sku order by id limit 9000000,10) a  
where t.id = a.id;

索引创建原则有哪些?

  • 什么情况下会添加索引呢?
    • 数据量大,10W条数据
    • 为经常用于 where、order by、group by 的字段创建索引
    • 使用复合索引
    • 控制索引数量

什么情况下索引会失效?

  • 违反最左匹配原则。
    • 例如联合索引是 name、status、address
    • 如果我 where 条件只查询了 name,那么是可以匹配索引的
    • 但是如果是 name address,跳过了 status 那就无法匹配了
    • 不能跳过中间某一列
  • 在索引字段上进行了运算或类型转换。
    • 类型转换:字符串没加单引号
  • 模糊查询且%号在前面

SQL的优化经验有哪些?

  • 建表的时候尽量选择合适的类型,比如状态可以用 tinyint
  • SQL语句避免造成索引失效的写法
  • 避免使用 SELECT *
  • 尽量用 union all 代替 union
    • union 会多一次过滤操作
  • 使用LEFT JOINRIGHT JOIN时,确保小表作为驱动表。
  • 采用主从复制和读写分离提高性能
  • 在数据量大时考虑分库分表

事务的特性是什么?

事务的特性是ACID,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability) 要么都成功、要么都失败

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

并发事务带来哪些问题?

问题:

  • 脏读
    • 一个事务读到了另一个事务未提交的“脏数据”
  • 不可重复读
    • 一个事务内多次读取同一数据,由于其他事务的修改导致数据不一致
  • 幻读
    • 一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了”幻影”

怎么解决这些问题呢?MySQL的默认隔离级别是?

  • 未提交读(READ UNCOMMITTED):解决不了所有问题。
  • 读已提交(READ COMMITTED):能解决脏读,但不能解决不可重复读和幻读。
  • 可重复读(REPEATABLE READ):能解决脏读和不可重复读,但不能解决幻读,这也是MySQL的默认隔离级别。
  • 串行化(SERIALIZABLE):可以解决所有问题,但性能较低。

undo log和redo log的区别是什么?

  • redo log:记录的是数据页的物理变化,用于服务宕机后的恢复,保证事务的持久性。
  • undo log:记录的是逻辑日志,用于事务回滚时恢复原始数据,保证事务的原子性和一致性。

事务的隔离性如何保证?解释下MVCC

事务的隔离性通过锁和多版本并发控制(MVCC)来保证。MVCC通过维护数据的多个版本来避免读写冲突。底层实现包括隐藏字段、undo logread view。隐藏字段包括trx_idroll_pointerundo log记录了不同版本的数据,通过roll_pointer形成版本链。read view定义了不同隔离级别下的快照读,决定了事务访问哪个版本的数据。

MySQL主从同步原理是什么?

利用二进制文件 binlog

  • 主库事务提交是会保存变更记录到 Binlog
  • 从库去读取 Binlog,并写到从库中继文件 Relay log
  • 从库执行 Relay log 中的事件,将改变反应到自己数据中。

你们项目用过MySQL的分库分表吗?

某个表数据量超过1000万,单库优化后性能仍然很慢,因此采用了水平分库。我们首先部署了3台服务器和3个数据库,使用mycat进行数据分片。旧数据也按照ID取模规则迁移到了各个数据库中,这样各个数据库可以分摊存储和读取压力,解决了性能问题。

  • 垂直分库:按业务进行充分
  • 垂直分表:冷热数据分离

Spring框架中的单例bean是线程安全的吗?

不是线程安全(没有线程安全这个问题) Spring框架中有一个 @Scope 注解,默认的值就是 singleton,单例的。 因为一般在 spring 的 bean 的中都是注入无状态的对象,没有线程安全问题,如果在 bean 中定义了可修改的成员变量,是要考虑线程安全问题的,可以使用多例或者加锁来解决

什么是AOP?

面向切面编程,将公共行为封装成,降低耦合

你们项目中有没有使用到AOP

在记录操作日志的时候用过,核心是使用AOP的环绕通知+切点表达式,通过环绕通知的参数获取请求方法的参数

Spring的事务是如何实现的

通过AOP功能,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

Spring中事务失效的场景有哪些

  • 方法内部自己捕获和处理了异常,会导致事务失效
  • 默认不会回滚 检查型异常,需要有在@Transactional注解上配置rollbackFor属性为Exception
    • throws FileNotFoundException 就是检查型异常
  • 如果事务注解的方法不是公开(public)修饰的,也可能导致事务失效
@Transactional
public void update(Integer from, Integer to, Double money) throws FileNotFoundException {
        //读取文件
    new FileInputStream("dddd");
    }
}

Spring的bean的生命周期?

  • 通过 BeanDefinition 获取 bean 的定义信息
  • 调用构造函数实例化 bean
  • Bean 的依赖注入
  • 处理 Aware 接口(BeanNameAware、BeanFactoryAware、ApplicationContextAware)
  • Bean的前置处理器 BeanPostProcessor-before
  • 初始化方法(InitializingBean、init-method)
  • Bean的后置处理器 BeanPostProcessor-after
  • 销毁bean

Spring中的循环引用?

bean对象互相引用,导致形成闭环。Spring框架是使用三级缓存解决了大部分循环依赖。

  • 一级缓存:单例池,缓存已完成初始化的bean对象。
  • 二级缓存:缓存尚未完成生命周期的早期bean对象。
  • 三级缓存:缓存ObjectFactory,用于创建bean对象。

那具体解决流程清楚吗?

  • 实例化A对象,并创建ObjectFactory存入三级缓存。
  • A在初始化时需要B对象,开始B的创建逻辑。
  • B实例化完成,也创建ObjectFactory存入三级缓存。
  • B需要注入A,通过三级缓存获取ObjectFactory生成A对象,存入二级缓存。
  • B通过二级缓存获得A对象后,B创建成功,存入一级缓存。
  • A对象初始化时,由于B已创建完成,可以直接注入B,A创建成功存入一级缓存。
  • 清除二级缓存中的临时对象A。

构造方法出现了循环依赖怎么解决?

使用@Lazy懒加载注解

public A(@Lazy B b){
    System.out.println("A的构造方法执行了...");
    this.b = b ;
}

SpringMVC的执行流程?JSP版本

  • 用户发送出请求到 前端控制器DispatcherServlet
  • DispatcherServlet 收到请求调用 HandlerMapping(处理器映射器)
  • HandlerMapping 找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给 DispatcherServlet
  • DispatcherServlet 调用 HandlerAdapter(处理器适配器)
  • HandlerAdapter 具体的处理器(Handler/Controller
  • Controller 执行完成返回 ModelAndView 对象
  • HandlerAdapterController 执行结果 ModelAndView 返回给 DispatcherServlet
  • DispatcherServletModelAndView 传给 ViewReslover (视图解析器)
  • ViewReslover 解析后返回具体 View(视图)
  • DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)
  • DispatcherServlet 响应用户

SpringMVC的执行流程?接口开发、异步请求

  • 用户发送出请求到 前端控制器DispatcherServlet
  • DispatcherServlet 收到请求调用 HandlerMapping(处理器映射器)
  • HandlerMapping 找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给 DispatcherServlet
  • DispatcherServlet 调用 HandlerAdapter(处理器适配器)
  • HandlerAdapter 具体的处理器(Handler/Controller
  • 方法上添加了@ResponseBody
  • 通过HttpMessageConverter来返回结果转换为JSON并响应

Springboot自动配置原理?

  • 在Spring Boot项目中的引导类上有一个注解 @SpringBootApplication,这个注解是对三个注解进行了封装,分别是:
    • @SpringBootConfiguration
    • @EnableAutoConfiguration
    • @ComponentScan
  • 其中 @EnableAutoConfiguration 是实现自动化配置的核心注解。 该注解通过@Import 注解导入对应的配置选择器。
    • 内部就是读取了该项目和该项目引用的 Jar包的 classpath 路径下 META-INF/spring.factories 文件中的所配置的类的全类名。
    • 在这些配置类中所定义的Bean会根据条件注解 所指定的条件来决定 是否需要将其导入到Spring容器中。
  • 条件判断会有像 @ConditionalOnClass 这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的 Bean 放入 spring 容器中使用。

Spring 的常见注解有哪些?

  1. 声明Bean的注解:@Component、@Service、@Repository、@Controller。
  2. 依赖注入相关注解:@Autowired、@Qualifier、@Resource。
  3. 设置作用域的注解:@Scope。
  4. 配置相关注解:@Configuration、@ComponentScan、@Bean。
  5. AOP相关注解:@Aspect、@Before、@After、@Around、@Pointcut。

SpringMVC常见的注解有哪些?

  • @RequestMapping:映射请求路径。
  • @RequestBody:接收HTTP请求的JSON数据。
  • @RequestParam:指定请求参数名称。
  • @RequestHeader:获取请求头数据。
  • @ResponseBody:将Controller方法返回的对象转化为JSON。
  • @PathVariable:从请求路径中获取参数。
  • @PostMapping、@GetMapping等。

Springboot常见注解有哪些?

  • @SpringBootApplication
  • 其他注解如@RestController、@GetMapping、@PostMapping等,用于简化Spring MVC的配置。

MyBatis执行流程?

  1. 读取MyBatis配置文件 mybatis-config.xml
  2. 构造会话工厂 SqlSessionFactory 去创建 SqlSession 对象。(包含了执行SQL语句的所有方法)
  3. Executor 执行器去执行方法中的 MappedStatement 参数,封装了映射信息。
  4. 输入参数映射。
  5. 输出结果映射。

Mybatis是否支持延迟加载?

MyBatis支持延迟加载,即在需要用到数据时才加载。可以通过配置文件中的lazyLoadingEnabled配置启用或禁用延迟加载。

延迟加载的底层原理知道吗?

延迟加载的底层原理主要使用CGLIB动态代理实现:

  1. 使用 CGLIB 创建目标对象的代理对象。
  2. 调用目标方法时,如果发现是null值,则执行SQL查询。
  3. 获取数据后,设置属性值并继续查询目标方法。

Mybatis的一级、二级缓存用过吗?

MyBatis的一级缓存是基于 PerpetualCache 的HashMap本地缓存,作用域为Session,默认开启。 二级缓存需要单独开启,作用域为 Namespacemapper ,默认也是采用PerpetualCache,HashMap存储。

Mybatis的二级缓存什么时候会清理缓存中的数据?

当作用域(一级缓存Session/二级缓存Namespaces)进行了新增、修改、删除操作后,默认该作用域下所有select中的缓存将被清空。

Spring Cloud 5大组件有哪些?

Spring Cloud Alibaba 的组件

  • 服务注册与配置中心:Nacos。
  • 负载均衡:Ribbon。
  • 服务调用:Feign。
  • 服务保护:Sentinel。
  • API网关:Gateway。

服务注册和发现是什么意思?

  • 服务注册与发现主要包含三个核心功能:服务注册、服务发现和服务状态监控。
    • 服务注册:服务提供者将自己的信息(如服务名称、IP、端口等)注册到Eureka。
    • 服务发现:消费者从Eureka获取服务列表信息,并利用负载均衡算法选择一个服务进行调用。
    • 服务监控:服务提供者定期向Eureka发送心跳以报告健康状态;如果Eureka在一定时间内未接收到心跳,将服务实例从注册中心剔除。

我看你之前也用过nacos,你能说下nacos与eureka的区别?

  • 共同点:两者都支持服务注册与发现,以及心跳检测作为健康检查机制。
  • 区别:
    • Nacos支持服务端主动检测服务提供者状态,而Eureka依赖客户端心跳。
    • Nacos区分临时实例和非临时实例,采用不同的健康检查策略。
    • Nacos支持服务列表变更的消息推送,使服务更新更及时。
    • Nacos集群默认采用AP模式,但在存在非临时实例时,会采用CP模式;而Eureka始终采用AP模式。 Nacos还支持了配置中心,eureka则只有注册中心,也是选择使用nacos的一个重要原因

你们项目负载均衡如何实现的?

Ribbon首先从注册中心获取服务地址列表,然后根据预设的路由策略选择一个服务实例进行调用,常用的策略是轮询。

Ribbon负载均衡策略有哪些?

  • RoundRobinRule:简单的轮询策略。
  • WeightedResponseTimeRule:根据响应时间加权选择服务器。
  • RandomRule:随机选择服务器。
  • ZoneAvoidanceRule:区域感知的负载均衡,优先选择同一区域中可用的服务器。

如果想自定义负载均衡策略如何实现?

  1. 创建一个类实现 IRule 接口,这将定义全局的负载均衡策略。
  2. 在客户端配置文件中指定特定服务调用的负载均衡策略,这将仅对该服务生效。

什么是服务雪崩,怎么解决这个问题?

服务雪崩是指一个服务的失败导致整个链路的服务相继失败

  • 服务降级:在请求量突增时,主动降低服务的级别,确保核心服务可用。
  • 服务熔断:当服务调用失败率达到一定阈值时,熔断机制会启动,防止系统过载。