Redis 高频面试题
本节汇总了中高级职位的 Redis 高频面试题,涵盖从基础架构到生产问题的深度解析。
基础与核心原理
Q1: Redis 为什么这么快?
- 纯内存操作:所有读写均在内存完成。
- 单线程模型:避免了多线程上下文切换和锁争用开销。
- 高效数据结构:Skiplist、Listpack(旧版本 Ziplist)、IntSet 等均为内存极致优化。
- I/O 多路复用:基于
epoll的非阻塞 I/O。 - Redis 6+ 多线程 I/O:主线程执行逻辑,多线程处理网络读写。
Q2: 单线程 Redis 能利用多核吗?
- 核心逻辑由主线程单核跑完。
- Redis 6.0 后支持
io-threads解决网络 I/O 瓶颈。 - 其他工作如 AOF 后台刷盘、UNLINK 删除、BGSAVE 均由子线程或子进程执行。
持久化与一致性
Q3: RDB 与 AOF 的抉择?
- RDB (快照):文件积压、恢复快。缺点:易丢数据(看快照频率)。
- AOF (日志):数据更安全、记录命令。缺点:文件大、恢复慢。
- 混合持久化 (Redis 4.0+):开启
aof-use-rdb-preamble。结合 RDB 的快与 AOF 的稳,是目前生产环境的标配。
Q4: AOF 重写 (Rewrite) 的原理?
- Fork 出子进程。
- 遍历内存数据,生成新的 AOF 文件(只记录当前最新状态,合并冗余命令)。
- Redis 7.0 (Multi-part AOF):不再需要临时文件切换,减少了内存管理压力。
高可用与集群
Q5: 哨兵 (Sentinel) 与 集群 (Cluster) 如何选择?
- Sentinel:适用于读多写少、单机能扛住写压力的场景,主打自动故障切换。
- Cluster:适用于海量数据且写并发极高的场景,实现真正的分布式水平扩展。
Q6: 为什么 Cluster 槽数是 16384 (16k)?
- 节点心跳包(Cluster Bus)会包含槽位位图(Bitmap)。
- 如果槽位太多(如 65536),位图将占据 8KB 左右,导致心跳包网络负担过重。
- 16k 已经足够分片需求,通常节点数在 1000 以内是最佳规模。
缓存生产故障
Q7: 缓存崩了该怎么办? (雪崩、击穿、穿透)
参考 Redis 最佳实践 中关于这三者的详细应对。
Q8: 如何保持数据库与缓存的双写一致性?
- 方案:先更新数据库,再删除缓存。
- 延时双删:写完数据库后,过几百毫秒再删一次缓存,缓解极短时间内请求读旧数据并重填缓存的问题。
- Binlog 订阅:通过 Canal/MySQL Binlog 异步删除缓存,将逻辑解耦,保证最终一致性。
开发与运维进阶
Q9: 什么是 Big Key?如何处理?
- 定义:String > 10KB, List/Hash 成员数 > 5000。
- 风险:阻塞网卡、删除耗时高导致主线程卡顿。
- 方法:
- 发现:
redis-cli --bigkeys或MEMORY USAGE。 - 处理:UNLINK 异步删除(非 DEL 阻塞销毁),或将大 Key 拆分为多个小 Key。
- 发现:
Q10: Redis 7.4 的 Hash 字段过期解决了什么问题?
- 以前只能整个 Hash 过期。要实现字段过期通常采用:
- 字段名带时间戳:
hset user:1 age:20241010 25。 - 设置额外过期 Key 集。
- 字段名带时间戳:
- Redis 7.4 的
HEXPIRE命令直接由内核支持,减少了业务逻辑维护复杂性。
持续更新中,建议结合实践不断提升。