后端JAVA八股文笔记
笔记基于 https://javaguide.cn/ 、以及黑马教程,重点归纳。
1 Redis
问题:你项目中什么场景使用了 Redis?
- 回答
缓存:那就会接着问- 缓存三兄弟(穿透、击穿、雪崩)、双写一致、持久化、数据过期策略,数据淘汰策略
- 回答
分布式锁- setnx、redisson
- 回答
消息队列、延迟队列- 何种数据类型
发生了 缓存穿透、击穿、雪崩,该如何解决?
- 缓存穿透
- 查询一个 不存在 的数据,mysql查不到数据就无法写入缓存,从而导致每次请求都查询数据库。
- 缓存穿透解决办法
- 布隆过滤器(一般用布隆过滤器解决)
查询数据流程是:先查redis,没有就查数据库并且 缓存和返回 结果。
布隆过滤器:检索一个元素是否在集合中,我是用 redisson 实现的。
先创建一个很大的 bit数组,里面只存储0和1,当添加一个元素时会就行 三次哈希函数 计算,将对应数组下标设置为 1,表明 Key 的存在。
当然会存在一定误判,一般不超过5%,误判是必然存在的,增大数组长度解决,但会增加占用。

缓存击穿
- 当缓存过期的时候,恰好有大量的并发请求,这堆请求可能会瞬间把DB压垮
解决办法
- 互斥锁:强一致、性能差
- 线程1:查询缓存发现过期,则添加
互斥锁,去查询数据库重建缓存,最后释放锁。 - 线程2:会一直等待、重试,直到
释放锁为止。
- 线程1:查询缓存发现过期,则添加
- 逻辑过期:高可用,性能优,不保证数据绝对一致
- 线程1:先添加
互斥,然后开启一个新的线程2去重建缓存,自身直接返回数据过期。 - 线程3:如果存在
锁,则直接返回数据过期。
- 线程1:先添加
- 互斥锁:强一致、性能差
缓存雪崩
- 同一时间大量的缓存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恢复数据,虽然慢一点,但丢数据的风险会小很多,刷盘策略我们是每秒批量写入命令。
| RDB | AOF | |
|---|---|---|
| 持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
| 数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
| 文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
| 宕机恢复速度 | 很快 | 慢 |
| 数据恢复优先级 | 低,因为数据完整性不如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 64mbredis的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 id和offset偏移量 - 第二步:master判断,replid不相同则代表
是第一次同步,master需要返回自己的replication id和offset偏移量。相同则不用动,代表不是第一次同步 - 第三步:主执行
bgsave生成并发送RDB文件,从去执行 - 之后master会记录所有命令,记录到
repl_baklog,发送他给slave。
- 第一步:slave请求master同步数据,其中slave会携带自己的
增量备份
- 第一和第二步流程和上面一样
- 第三步:master发送
repl_baklog中offset之后的数据
怎么保证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、单线程就避免不必要的上下文切换和竞争条件。
例如:BGSAVE和BGREWRITEAOF都是在后台执行操作,不影响主线程的正常使用,不会产生阻塞。
能解释一下I/O多路复用模型
指利用单个线程来同时监听多个Socket,采用的epoll模式实现,当Socket就绪时,epoll会通知用户进程写入Socket到用户空间,则不需要挨个遍历询问。
2 Mysql数据库
如何定位慢查询?
我当初是用了 Skywalking 可以检测哪个接口慢,如果是mysql的问题,我会开启 慢日志查询,我当初是设置2秒,超过这个数就会记录到日志中。
# 开启MySQL慢日志查询开关
slow_query_log=1
# 设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志
long_query_time=2那这个SQL语句执行很慢,如何分析呢?
- 我是用MYSQL自带的分析工具
explain查看执行情况 - 通过
key和key_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 id,name from tb_user where name = ‘Arm’
-- 非覆盖索引, 需要回表查询
select id,name,gender 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 JOIN或RIGHT 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 log和read view。隐藏字段包括trx_id和roll_pointer。undo log记录了不同版本的数据,通过roll_pointer形成版本链。read view定义了不同隔离级别下的快照读,决定了事务访问哪个版本的数据。
MySQL主从同步原理是什么?
利用二进制文件 binlog
- 主库事务提交是会保存变更记录到 Binlog
- 从库去读取 Binlog,并写到从库中继文件 Relay log
- 从库执行 Relay log 中的事件,将改变反应到自己数据中。
你们项目用过MySQL的分库分表吗?
某个表数据量超过1000万,单库优化后性能仍然很慢,因此采用了水平分库。我们首先部署了3台服务器和3个数据库,使用mycat进行数据分片。旧数据也按照ID取模规则迁移到了各个数据库中,这样各个数据库可以分摊存储和读取压力,解决了性能问题。
- 垂直分库:按业务进行充分
- 垂直分表:冷热数据分离
3 Spring
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对象HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServletDispatcherServlet将ModelAndView传给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容器中。
- 内部就是读取了该项目和该项目引用的 Jar包的 classpath 路径下
- 条件判断会有像
@ConditionalOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的 Bean 放入 spring 容器中使用。
Spring 的常见注解有哪些?
- 声明Bean的注解:@Component、@Service、@Repository、@Controller。
- 依赖注入相关注解:@Autowired、@Qualifier、@Resource。
- 设置作用域的注解:@Scope。
- 配置相关注解:@Configuration、@ComponentScan、@Bean。
- 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执行流程?
- 读取MyBatis配置文件
mybatis-config.xml。 - 构造会话工厂
SqlSessionFactory去创建SqlSession对象。(包含了执行SQL语句的所有方法) Executor执行器去执行方法中的MappedStatement参数,封装了映射信息。- 输入参数映射。
- 输出结果映射。
Mybatis是否支持延迟加载?
MyBatis支持延迟加载,即在需要用到数据时才加载。可以通过配置文件中的lazyLoadingEnabled配置启用或禁用延迟加载。
延迟加载的底层原理知道吗?
延迟加载的底层原理主要使用CGLIB动态代理实现:
- 使用
CGLIB创建目标对象的代理对象。 - 调用目标方法时,如果发现是null值,则执行SQL查询。
- 获取数据后,设置属性值并继续查询目标方法。
Mybatis的一级、二级缓存用过吗?
MyBatis的一级缓存是基于 PerpetualCache 的HashMap本地缓存,作用域为Session,默认开启。
二级缓存需要单独开启,作用域为 Namespace 或 mapper ,默认也是采用PerpetualCache,HashMap存储。
Mybatis的二级缓存什么时候会清理缓存中的数据?
当作用域(一级缓存Session/二级缓存Namespaces)进行了新增、修改、删除操作后,默认该作用域下所有select中的缓存将被清空。
4 微服务
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:区域感知的负载均衡,优先选择同一区域中可用的服务器。
如果想自定义负载均衡策略如何实现?
- 创建一个类实现
IRule接口,这将定义全局的负载均衡策略。 - 在客户端配置文件中指定特定服务调用的负载均衡策略,这将仅对该服务生效。
什么是服务雪崩,怎么解决这个问题?
服务雪崩是指一个服务的失败导致整个链路的服务相继失败
- 服务降级:在请求量突增时,主动降低服务的级别,确保核心服务可用。
- 服务熔断:当服务调用失败率达到一定阈值时,熔断机制会启动,防止系统过载。