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 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Explainfuture's Blog!