推荐文章:【Redis】Redis的特性和应用场景 · 数据类型 · 持久化 · 数据淘汰 · 事务 · 多机部署-CSDN博客
一定要结合业务场景来回答问题!要是没有不要硬讲,除非面试官问;

接下来面试官将深入发问。
正常的场景是这样的:


缓存穿透:查询一个不存在的数据的时候,MySQL 查询不到数据也不会写入缓存,就会导致每次这样的查询请求都不会命中 Redis 的缓存,每次都穿过 Redis,查询 MySQL;
解决方案:
也就是查询出来的结果不存在,也将其缓存出来,例如:
{"id:1": null}
优点:简单直接有效;
缺点:消耗内存比较大,可能会出现双写不一致的问题,需要去维护双写一致性;

也就是通过布隆过滤器判断键值是否存在,再判断是否读缓存,再决定是否读 MySQL:
布隆过滤器的底层主要是一个比较大的数组,里面存放的是 0 / 1,在一开始的时候都是 0,当一个 key 来之后,经过 3 次 hash 计算,模上数组长度找到数据的下标,然后把数组中原来的 0 改为 1(1 则还是 1),这样的话,数组的三个位置就能标明一个 key 是否存在;
当然,这里很明显的问题就是可能会出现误判,并且避免不了,我们一般可以控制这个误判率,数组越大,误判率就越小,性能也越差,最好就是 0.03 - 0.05 了,性能还算好一点,误差也是在接受范围内的,在实际业务可以大大降低 key 不存在而查 MySQL 的次数;
优点:内存占用小,没有多余的 key,布隆过滤器一般不会设置过期时间;
缺点:实现复杂,存在误判,删除不是很好删,可能会影响其他的数据;
如果出现误判,那么岂不是还是会出现缓存穿透?
是的,我觉得两种方法可以结合起来使用!
- 布隆过滤器查询结果:缓存存在(假设为误判结果);
- 查询 Redis,不存在;
- 查询 MySQL,不存在;
- 在 Redis 中设置值为 null 的 key(在布隆过滤器表示存在的时候,再设置这个 key,而不是每次表示不存在都设置 null);
- 下一次同样的请求;
- 布隆过滤器查询结果:缓存存在(假设为误判结果);
- 查询 Redis,结果为 null,返回 null;
同理,其实业务中删除了 Redis 的某个键,也没必要在布隆过滤器中删除,把之后的每一次都视作“误判”;
回答:

缓存击穿:给某个 key 设置了过期时间,当 kye 过期的时候,恰好这个时间点对这个 key 有大量的并发请求过来,在 MySQL 读完并设置缓存这个间隙,MySQL 将瞬间收到大量的压力,甚至被搞垮;
解决方案:

回答:
缓存穿透与缓存击穿的字面理解:
这里的“洞”指的是,某个 key 无命中 Redis 的缓存,直接穿过 Redis 访问 MySQL;
缓存雪崩:在同一段时间内,大量的缓存 key 同时失效或者 Redis 服务宕机,导致大量的请求直接数据库,带来巨大压力;

解决方案:
一首打油诗,当作看了个乐就行🤣:

一定要先介绍自己的哪些业务背景维护了双写一致,或者可以去维护双写一致。

双写一致性:当修改了数据库的数据也要同时更新缓存的数据,保证缓存和数据库的数据要保持一致;
我们可能会想,更新的时候把缓存删了不就好了,那么我们是先更新后删除缓存,还是先删除缓存再更新数据库?

况且,对于 Redis 集群,主从库同步也需要时间,这个问题也会被扩大;
分为两个思路:
读数据操作:缓存命中则返回,缓存未命中则查询数据库,写入缓存,设定超时时间;
写数据操作:
- 期间是可能出现脏数据的;
延时多久不太好确定,延时删除可以通过定时器任务、消息中间件异步通知删除等方式去实现;
一般缓存的数据应该是**读多写少**,这样的数据才值得缓存,读多写少的场景下用读写锁可以尽可能的保持性能不会太差;
读写锁:
- 读锁:又称共享锁,别的线程读的话不阻塞,写的话则阻塞等待;
- 写锁:又称排他锁,别的线程读写都得阻塞等待;
用读写锁解决问题:

代码实例:
回答(示例):
RDB 全称 Redis Database Backup file(Redis 数据库备份文件,有压缩),也称为 Redis 数据快照。也就是把 Redis 内存中的所有数据都记录到磁盘中,当 Redis 实例故障重启,从磁盘中读取快照文件,恢复数据;

RDB 的执行原理:

AOF 全称 Append Only File(追加文件)。Redis 处理的每一个“写”命令都会记录在 AOF 文件,可以看做是命令日志/重做日志;

需要通过 redis.conf 来配置:

AOF 的执行频率策略:

因为是记录命令,没有压缩,AOF 文件会比 RDB 文件大很多,而且 AOF 会记录对同一个 key 的多次写操作,但是可能最后一次写操作有效,我们可以通过 bgrewriteaof 命令(bg rewrite aof),可以让 AOF 文件执行重写操作,减少最少命令达到相同效果;

可以通过 redis.conf 配置触发自动重写的阈值:


可能不会立即删除,要看 Redis 的数据过期策略;
Redis 对数据设置过期时间
set name macaku 10
数据过期之后,就需要将数据从内存中删除,可以按照不同的规则进行删除,这种删除规则就是 Redis 的数据过期策略;
有两种:
Redis 采用的是 惰性 + 定期;
惰性删除:设置该 key 过期时间后,我们不去管它,当需要该 key 时,我们检查是否过期,如果过期,我们就删掉;

优点: 对 CPU 友好,只会在使用该 key 的时候进行删除,对于很多用不到的 key 就不用浪费时间删除了;
缺点: 对内存不友好,如果一个 key 已经过期,长期不用,就滞留在内存里不会被释放了;
定时删除:每隔一段时间,我们就从 Redis 取出一定量的随机 key 进行检查,并删除其中过期的 key;
定期删除有两种模式:
每次的删除程度,例如:
- 从过期字典中随机取出20个键
- 删除这20个键中过期得键
- 如果过期键的比例超过25%,重复此过程
(由于有时间限制,所以不会循环太多次,可能最终没达到 25%,不过没啥大碍,交给下次咯)
可以自己去配;
优点: 可以通过限制删除操作执行的时长和频率来避免一次性删除/删除的数据量太大对 CPU 的影响,另外定期删除,也能有效释放过期键占用的内存,避免过期数据滞留在内存里;
缺点: 难以确定删除操作执行的时长和频率,“没有轮到删除”的过期数据可能被访问到;
所以混搭组合技才是王道,当访问到定时删除下还没删除的数据,判断其为过期数据则删除;
回答:
早期版本的Redis有以下六种内存淘汰策略:
在Redis 4.0版本中又新增了两种淘汰策略:
侧重点不同
Redis 的内存用完了会发生什么?
数据库有 1000w 数据,Redis 只能缓存 20w 数据,如何保证 Redis 中的数据都是热点数据?