redis面试题总结

redis做为缓存相关的问题

缓存预热

1.定期生成,不涉及"预热"

2.实时生成

问题:redis服务在刚启动的时候,初始没有数据,就会导致所有请求全部打到MySQL中。

解决办法:可以将定期生成和实时生成结合一下,通过离线的方式,统计一点热点数据,导入redis中,分担MySQL的压力。

缓存穿透

问题:对于查询某个redis中没有的key,mysql中也没有,那么这个key就不会被更新到缓存中,每次查询就会都直接打到mysql上,这样的数据如果过多,反复查询,就会给mysql带来很大的压力。

1.设计不合理,比如对参数校验不合理

2.不小心对数据库进行误删

3.黑客恶意攻击

解决办法:

1.如果发现某个key在redis和mysql上都不存在,仍然写入redis,value设成一个非法值(比如"")。

2.引入布隆过滤器在查询钱判断是否存在。

缓存雪崩

问题:由于短时间内,redis上大规模的key失效,导致缓存命中率陡然下降,并且mysql的压力迅速上升,甚至直接宕机。

1.redis直接挂了

2.同时设置了大量的key,并且设置了同一个过期时间

解决办法:

1.加强监控报警,加强redis集群的可用性的保证。

2.不给key设置过期时间或者在设置过期时间的时候加上一个随机因子(避免同一时间过期)。

缓存击穿

问题:相当于缓存雪崩的特殊情况下,针对于热点的key突然过期,导致大量请求直接打到数据库,甚至引起数据库宕机。

热点的key访问频率更高,影响更大

解决办法:

基于统计的方式发现热点的key,并设置永不过期。

进行必要的服务器降低,例如使用数据库的时候使用分布式锁,限制同时请求数据库的并发数。

redis和mysql如何保证双写一致性?

什么是双写一致性:用户修改数据的时候,需要对数据库进行修改,那么同时也需要修改缓存中的数据,但是如果直接写数据库和写redis的时候,有一方出现问题,就可能导致数据不一致的问题。

解决办法:

强一致性要求高的数据:

延迟双删:读的时候,如果没有数据就写入缓存,写的时候先删除缓存,再更新数据库,延迟一段时间后(数据库需要同步数据),再删除缓存。

这种办法也会存在数据不一致的问题,可以通过加读写锁的方式,来解决写的时候读的问题。

延迟一致性的数据:

异步通知保证数据的最终一致性,将要修改的数据发生到rabbitmq,异步实现数据的一致性。

或者是基于canal的异步通知,监听mysql的binlog。

redis作为缓存,数据的持久化是怎么做到?

reids持久化的方式:1.RDB 2.AOF

区别:

RDB:redis的数据快照,把内存中的所有数据都记录在磁盘中,如果redis发生故障重启后,从磁盘中读取快照文件,恢复数据。(数据安全性要求比较低)

AOF:redis处理的每一个命令都会记录在AOF文件中,可以看做是命令日志文件,通过把这个文件再执行一遍来恢复数据。(数据安全性要求比较高)

哪种恢复的比较快?

RDB因为是二进制文件,保存的时候体积比较小,恢复比较快,但是可能造成数据丢失,AOF虽然慢,但是风险比较小。

redis数据过期策略

惰性删除:访问一个key时发现已经过期再删除

定期删除:每隔一段时间进行一次扫描,删除掉已经过期的key

redis中同时使用了惰性过期和定期过期两种过期策略。

1.每隔100ms就随机抽取一定的key来检查和删除

2.在获取key的时候,也会进行检查是否过期,过期了就会删除

内存淘汰策略

FIFO先进先出

把缓存中存在时间最久的淘汰掉

LRU淘汰最久未使用的

记录每个key的最近访问时间,把最近访问时间最老的key淘汰掉

LFU淘汰访问次数最少的

记录每个key最近一段时间的访问次数,把访问次数最少的淘汰掉

Random随机淘汰

Redis的内存淘汰策略有哪些?

redis提供了很多种,默认是noeviction,不删除任何数据,内存不足直接报错。

可以在redis的配置文件中进行配置,有两个非常重要的概念是LRU和LFU

LRU的意思是最少最近使用,删除访问时间最老的key

LFU的意思是最少频率使用,删除使用频率最少的key

数据库中有1000万数据,redis只能缓存20w数据,如何保证redis中的数据都是热点数据?

可以使用allkeys-lru(挑选最近最少使用的数据淘汰)

redis内存用完了会发生什么?

redis默认的策略是noeviction,会直接报错

redis作为分布式锁

1.如何实现的

使用redisson实现分布式锁,底层是setnx和lua脚本保证原子性

2.如何合理控制锁的有效时长

使用WatchDog(看门狗),一个线程获取锁成功之后,WatchDog会给持有锁的线程续期

3.redisson这个锁可重入吗?

可重入,redis记录了获取锁的线程信息和重入的次数

4.redisson锁能解决主从数据一致性的问题吗?

不能解决,但是可以使用redisson提供的红锁(多个redis共同进行加锁),但是性能比较差,建议使用zookeeper实现。

redis的集群方案

主从复制

主节点主要负责写操作,从节点负责读操作,主节点写操作之后,要把数据同步给从节点。

介绍一下redis的主从同步?

单节点redis的并发能力是有上限的,需进一步提高redis的并发能力,就需要搭建主从集群,实现读写分离。一般都是一主多从,主节点负责写数据,从节点负责读数据。

能说一下,主从同步数据的流程吗?

全量同步

1.从节点请求主节点同步数据(replication id 、offset)

2.主节点判断是否是第一次请求,是第一次就与从节点同步版本信息(replication id和offset)

3.主节点执行bgsave,生成rdb文件后,发送给从节点去执行。

4.在rdb生成执行期间,主节点会以命令的方式记录到缓存区(一个日志文件)

5.把生成之后的命令日志文件发送给从节点进行同步。

增量同步:

1.从节点请求主节点同步数据,主节点判断是不是第一次请求,不是第一次就获取从节点的offset的值。

2.主节点从命令日志中获取offset值之后的数据,发送给从节点进行数据同步。

哨兵的作用

redis提供了哨兵(sentinel)机制来实现主从集群的自动故障恢复。

怎么保证redis的高并发高可用?

使用哨兵模式:实现主从集群的自动故障恢复(监控、自动故障恢复、通知)

你们使用redis是单点还是集群,哪重集群?

主从(1主1从)+哨兵就可以了

redis集群脑裂,该怎么解决?

集群脑裂:由于主节点和从节点和哨兵处于不同的网络分区,如果哨兵没有能够感知到主节点的心跳,就会通过选举的方式提供了一个从节点为主,这样就存在了两个master,就像大脑分裂了一样,这样就会导致客户端还在老的主节点那里写入数据,新节点无法同步数据,当网络恢复后,哨兵会将主节点降为从节点,再从从节点那里同步数据,就会导致数据丢失。

解决:可以修改redis的配置,可以设置最少的从节点数量以及缩短主从数据同步的延迟时间,达不到要求就拒绝请求,避免数据的丢失。

分片集群结构

引入多个主节点解决内存不够的问题

redis的分片集群有什么作用

集群中有多个master,每个matser保存不同的数据

每个master都可以有多个slave节点

master之间通过ping监测彼此之间的健康状态

客户端请求可以访问集群任意节点,最终都会被正确的转发到正确的节点。

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

redis分片集群引入了哈希槽的概念,redis集群中有16384个哈希槽。

将16384个插槽分配到不同的实例

读写数据:根据key的有效部分计算哈希值,对16384取余,余数作为插槽,寻找对应的实例。

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

redis是纯内存操作,执行速度非常快。

采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题。

使用IO多路复用模型,非阻塞IO

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

是指利用单个线程来同时监听多个socket,并在某个socket可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。reids采用epoll实现,他会通知用户进程socket就绪的同时,把已就绪的socket写入用户空间,不需要遍历socket判断是否就绪,提高了性能。

相关推荐
为美好的生活献上中指2 小时前
*Java 沉淀重走长征路*之——《Linux 从入门到企业实战:一套六步法,带你打通运维与开发的任督二脉》
java·linux·运维·开发语言·阿里云·华为云·linux命令
wuqingshun3141592 小时前
依赖注入的方式有几种,各是什么?
java·开发语言
冬夜戏雪2 小时前
实习面经(十二)
java
未秃头的程序猿2 小时前
Redis也能做消息队列!Spring Boot实战:从List到Stream的优雅实现
redis·后端
编码忘我2 小时前
JVM 运行时数据区详解
java·后端·程序员
阿唯不困2 小时前
AI智能应用开发(Java)从起点到终点-面向对象
java·后端
m0_726965982 小时前
面面面(2)
java·开发语言
05大叔2 小时前
RAG开发
java·服务器·前端
迷藏4942 小时前
# 发散创新:用 Rust实现高性能测试框架的底层逻辑与实战演练
java·开发语言·后端·python·rust