面试:Redis

目录

一、缓存穿透

1、解决方案一:

2、解决方案二:

二、缓存击穿

1、解决方案一:

2、解决方案二:

三、缓存雪崩

1、解决方案一:

2、解决方案二:

3、解决方案三:

4、解决方案四:

四、双写一致

1、解决方案一:(强一致)

2、解决方案二:(强一致)

3、解决方案三:(允许短暂的不一致)

4、面试模拟

五、Redis的持久化

1、RDB

(1)介绍:

(2)执行原理:

2、AOF

(1)介绍:

(2)缺点:

3、两者对比

4、面试模拟

六、Redis的过期策略

1、惰性删除

(1)介绍:

(2)优点:

(3)缺点:

2、定期删除

(1)介绍:

(2)两种模式:

(3)优点:

(4)缺点:

七、Redis的数据淘汰策略

1、Redis支持8种不同策略来选择要删除的key:

2、数据淘汰策略-使用建议

3、面试可能会问到的问题

八、Redis的分布式锁

1、介绍

2、redisson-执行流程(每隔一段时间给锁续期)

3、redisson-可重入

4、主从一致性

5、面试模拟:

九、Redis的集群方案

1、主从复制(解决高并发)

(1)主从同步原理

(2)增量同步(slave重启或后期数据变化)

2、哨兵(解决高可用)

(1)服务状态监控

(2)哨兵选主规则

(3)脑裂

3、分片集群结构(海量数据存储问题、高并发写的问题)

(1)数据读写

4、面试模拟:(主从复制、哨兵模式、分片集群结构)


一、缓存穿透

查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库,会导致数据库宕机。

1、解决方案一:

缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存

优点:

实现简单

缺点:

消耗内存,可能会发生不一致的问题

2、解决方案二:

布隆过滤器

优点:

占用内存小,没有多余的key。

缺点:

实现复杂,存在误判。


二、缓存击穿

给某一个key设置了过期时间,当key过期的时候 ,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮。

1、解决方案一:

互斥锁

优点:

强一致

缺点:

性能差

2、解决方案二:

逻辑过期


三、缓存雪崩

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

1、解决方案一:

给不同的Key的TTL添加随机值

2、解决方案二:

利用Redis集群提高服务的可用性(哨兵模式、集群模式)

3、解决方案三:

给缓存业务添加降级限流策略(ngxin或spring cloud gateway)

4、解决方案四:

给业务添加多级缓存(Guava或Caffeine)


四、双写一致

双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致

读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间

写操作:延迟双删

问题一:先删除缓存,还是先修改数据库

先删除缓存和先删除数据库都可能出现脏读

问题二:为什么要删除两次缓存?

降低脏数据的出现

问题三:为什么要延时删除?

因为数据库一般是主从一致的,要等待主节点将数据发往从节点。但是延时的时间不好控制,也会有脏数据的风险。

1、解决方案一:(强一致)

加分布式锁可以杜绝脏数据的出现,但是性能较差

2、解决方案二:(强一致)

加上读写锁;

3、解决方案三:(允许短暂的不一致)

异步通知保证数据的最终一致性;

4、面试模拟


五、Redis的持久化

1、RDB

(1)介绍:

RDB全称Redis Database Backup file (Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据.

·主动创建备份,推荐使用bgsave

· Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:

(2)执行原理:

bgsave开始时会fork主进程得到子进程子进程共享主进程的内存数据 。完成fork后读取内存数据并写入RDB文件。使用页表进行虚拟内存和物理内存的映射

fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

2、AOF

(1)介绍:
  • AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:
  • AOF的命令记录的频率也可以通过redis.conf文件来配:
  • 差别:
(2)缺点:
  • 因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义 。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。
  • Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

3、两者对比

4、面试模拟


六、Redis的过期策略

Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。

1、惰性删除

(1)介绍:

设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key

(2)优点:

对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查

(3)缺点:

对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放

2、定期删除

(1)介绍:

每隔一段时间 ,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。

(2)两种模式:
  • SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf的hz选项来调整这个次数
  • FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms
(3)优点:

可以通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。另外定期删除,也能有效释放过期键占用的内存。

(4)缺点:

难以确定删除操作执行的时长和频率。


七、Redis的数据淘汰策略

当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

1、Redis支持8种不同策略来选择要删除的key:

  • noeviction:不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略
  • volatile-ttl:对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
  • allkeys-random:对全体key,随机进行淘汰。
  • volatile-random:对设置了TTL的key,随机进行淘汰。
  • allkeys-lru:对全体key,基于LRU算法进行淘汰
  • allkeys-Iru: 对全体key,基于LRU算法进行淘汰
  • volatile-Iru:对设置了TTL的key,基于LRU算法进行淘汰
  • allkeys-lfu:对全体key,基于LFU算法进行淘汰
  • volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰

2、数据淘汰策略-使用建议

  1. 优先使用alkeys-lru 策略。充分利用LRU算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显的冷热数据区分,建议使用
  2. 如果业务中数据访问频率差别不大,没有明显冷热数据区分 ,建议使用allkeys-random,随机选择淘汰。
  3. 如果业务中有置顶的需求 ,可以使用volatile-lru 策略,同时置顶数据不设置过期时间,这些数据就一直不被删除,会淘汰其他设置过期时间的数据。
  4. 如果业务中有短时高频访问的数据 ,可以使用allkeys-lfu或volatile-lfu策略。

3、面试可能会问到的问题

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

使用allkeys-lru(挑选最近最少使用的数据淘汰)淘汰策略,留下来的都是经常访问的热点数据

2. Redis的内存用完了会发生什么?

主要看数据淘汰策略是什么?如果是默认的配置( noeviction ),会直接报错。

3、数据库有1000万数据,我不用Redis,如何缓存100w热点数据?(美团真题)

  1. 定义缓存数据结构 :首先,你需要定义一个数据结构来存储缓存数据。这个数据结构可以是一个哈希表 ,其中键是数据的唯一标识符,值是数据本身。除了哈希表,你还可以使用其他数据结构,比如LRU(最近最少使用)缓存

  2. 确定热点数据:通过对数据库进行分析或者根据应用程序的访问模式,确定哪些数据是热点数据,即经常被访问的数据。

  3. 缓存策略:选择合适的缓存策略来缓存热点数据。常见的缓存策略包括:

    • 基于时间的过期策略TTL:设置缓存数据的过期时间,当缓存数据过期时,需要重新从数据库中加载。
    • 基于请求频率的淘汰策略LFU:根据数据的访问频率来淘汰不常用的数据,保留常用的数据。

八、Redis的分布式锁

1、介绍

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则SET)的简写。

2、redisson-执行流程(每隔一段时间给锁续期)

3、redisson-可重入

可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁.

4、主从一致性

RedLock(红锁): 不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁(n/ 2+1),避免在一个redis实例上加锁。

5、面试模拟:


九、Redis的集群方案

1、主从复制(解决高并发)

单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。

(1)主从同步原理
  • Replication ld:

简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid

  • offset:

偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset.如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

  • 全量同步:
(2)增量同步(slave重启或后期数据变化)

2、哨兵(解决高可用)

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

  • **监控:**Sentinel 会不断检查您的master和slave是否按预期工作.
  • **自动故障恢复:**如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主.
  • **通知:**Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端.
(1)服务状态监控

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令;

  • 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。
(2)哨兵选主规则
  1. 首先判断主与从节点断开时间长短,如超过指定值就排该从节点
  2. 然后判断从节点的slave-priority值,越小优先级越高
  3. 如果slave-prority一样,则判断slave节点的offset值,越大优先级越高
  4. 最后是判断slave节点的运行id大小,越小优先级越高。
(3)脑裂

由于网络原因产生了两个主节点
解决方式:设置redis的配置参数

3、分片集群结构(海量数据存储问题、高并发写的问题)

使用分片集群可以解决上述问题,分片集群特征:

  1. 集群中有多个master,每个master保存不同数据
  2. 每个master都可以有多个slave节点
  3. master之间通过ping监测彼此健康状态
  4. 客户端请求可以访问集群任意节点,最终都会被转发到正确节点
(1)数据读写

4、面试模拟:(主从复制、哨兵模式、分片集群结构)

相关推荐
柯南二号7 小时前
MacOS 用brew 安装、配置、启动Redis
redis
星星点点洲9 小时前
【Redis】RedLock实现原理
redis·缓存
我来整一篇9 小时前
用Redis的List实现消息队列
数据库·redis·list
加什么瓦10 小时前
Redis——数据结构
数据库·redis·缓存
lybugproducer11 小时前
浅谈 Redis 数据类型
java·数据库·redis·后端·链表·缓存
青山是哪个青山11 小时前
Redis 常见数据类型
数据库·redis·bootstrap
杨不易呀11 小时前
Java面试全记录:Spring Cloud+Kafka+Redis实战解析
redis·spring cloud·微服务·kafka·高并发·java面试·面试技巧
morris13112 小时前
【redis】CacheAside的数据不一致性问题
redis·缓存策略·cache aside·数据不一致性
wjcurry12 小时前
我的实习日报
java·redis·mysql