Redis八股
面试问题
什么是缓存击穿、穿透、雪崩?区别是什么?如何解决?
- 穿透:请求永远不会命中缓存
- 请求的数据缓存中没有,数据库也没有,每次请求都会打到数据库
 - 查不存在的用户ID,如 ID=-1
 - ① 参数校验 ② 布隆过滤器 ③ 缓存空值
- 启动时将数据库中所有合法的 ID 加入布隆过滤器;
 - 每次查询前先判断:ID 是否在布隆过滤器中?
 - 如果不在 → 直接返回,不查缓存也不查库;
 
 
 
如果在 → 走正常的缓存查询流程。
- 击穿:缓存偶尔失效后瞬间打爆后端
- 某个热点数据突然过期,大量请求同时查询,穿透缓存打爆数据库
 - 秒杀商品库存刚好过期
 - ① 加互斥锁 ② 提前续期 ③ 永不过期+异步更新
 
 - 雪崩:大量缓存同时失效导致系统崩溃
- 大量缓存同一时间过期,所有请求打到数据库,系统瞬间崩溃
 - 定时批量缓存设置相同过期时间
 - ① 加随机过期时间 ② 热点预热 ③ 多级缓存
布隆过滤器是一种概率型数据结构,可以用来判断一个元素一定不存在/可能存在
 
 
Redis的过期删除策略?
- 惰性删除:访问key时,才检查他是否过期,如果过期就删除 | 但可能留下大量垃圾
 - 定期删除:每隔一段时间随机抽取部分 key 检查过期并删除(如每秒检查 20 个)
 - 主动淘汰:当内存不足时触发内存淘汰机制
 
什么是基于 Redis 构造分布式锁?
- 本质:利用 Redis 的 SET key value NX EX 原子命令,保证同一时刻只有一个线程/服务获取到锁,从而控制并发访问共享资源(如库存扣减、优惠券发放)。
 
1  | // 尝试加锁  | 
- NX:只在 key 不存在时设置(互斥)
 - EX 10:自动过期(防死锁)
 - my_value:用 UUID 表示“我是谁”,用于后续解锁校验
 
为什么用 Lua 脚本做分布式锁?
加锁与解锁需要“判断 + 删除”是一个原子操作。用普通 Redis 命令不能保证原子性(可能判断完刚要删,锁就被别人改了)。
Redis 支持执行一整段 Lua 脚本,这段脚本在 Redis 内部一次性、原子性执行,所以我们用它封装加锁或解锁逻辑,确保线程安全。
1  | if redis.call('get', KEYS[1]) == ARGV[1] then  | 
缓存一致性如何实现?
- 先更新库,再删除缓存,设置延迟双删。
 
持久化
- 虽然redis是内存数据库,但是提供了两种方式进行持久化,默认的是RDB,AOF需要自行设置配置开启;
 
AOF持久化
- AOF的步骤是,当一条
写命令成功执行后,把这条命令追加到一个文件里,然后重启redis的时候,redis先去这个文件里读取命令并执行,就相当于恢复了数据。- 避免额外检查开销
 - 不会阻塞当前写操作命令的执行:因为只有命令执行成功后才会被写入
 
 
AOF写回策略
- Always:执行完命令同步将AOF日志数据写回硬盘
 - Everysec:执行完命令后就将写操作写入到缓冲区,然后
每隔一秒将缓冲区的数据写入到硬盘 - No:转由操作系统写
 
AOF重写机制
- 随着数据库使用的越来越多,AOF文件的体积变大,就需要重写机制,只会保存最新的一条更新数据
 - 比如使用:set name lcc 然后再使用 set name lccc
 - 更新的时候只会记住后面的lccc,因为之前的命令已经没有意义了。
 
RDB持久化
- RDB是快照,每次执行快照,把
内存里的所有数据都记录到硬盘里,所以如果频繁执行快照,就会导致Redis的性能下降,如果设置时间过长,然后恰好宕机,就会丢失这一段时间里的所有数据 
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Explainfuture's Blog!
