第38章:Redis 面试宝典与总复习
38.1 知识体系完整回顾
Redis 知识体系
├── 核心概念
│ ├── 内存数据库(快的原因:内存+单线程+IO多路复用)
│ └── KV 模型(Key→Value,8种数据类型)
├── 五大基本类型
│ ├── String(缓存/计数器/分布式锁)
│ ├── Hash(用户信息/购物车)
│ ├── List(消息队列/最新列表)
│ ├── Set(标签/共同好友/抽奖)
│ └── ZSet(排行榜/延时队列)
├── 高级类型
│ ├── Bitmap(签到)
│ ├── HyperLogLog(UV统计)
│ ├── Geo(附近的人)
│ └── Stream(可靠消息队列)
├── 持久化
│ ├── RDB(快照→恢复快)
│ ├── AOF(日志→数据安全)
│ └── 混合持久化(4.0+)
├── 高可用
│ ├── 主从(读写分离)
│ ├── Sentinel(自动故障转移)
│ └── Cluster(数据分片,16384槽)
├── 高级特性
│ ├── 事务(不支持回滚)
│ ├── Lua 脚本(原子性)
│ ├── Pipeline(减少RTT)
│ ├── Pub/Sub(不持久)
│ └── 过期+淘汰(惰性+定期+LRU/LFU)
└── 实践
├── go-redis 客户端
├── 缓存穿透/击穿/雪崩
├── 分布式锁(SET NX EX)
└── bigkey/热key处理38.2 高频面试题 40 题
基础概念
Q1:Redis 为什么快?
三点:①纯内存操作;②单线程避免锁竞争和上下文切换;③IO 多路复用。
Q2:Redis 单线程为什么还这么快?
瓶颈在网络 I/O 而不是 CPU。单线程省去了线程切换和锁的开销。Redis 6.0+ 把网络读写改成了多线程,但命令执行仍是单线程。
Q3:Redis 和 MySQL 的区别?
Redis 是内存数据库(快、容量小),MySQL 是磁盘数据库(慢、容量大)。Redis 适合缓存热数据,MySQL 存全量数据。
数据类型
Q4:五种基本类型及应用场景?
String=缓存/计数/锁,Hash=对象/购物车,List=消息队列,Set=标签/共同好友,ZSet=排行榜。
Q5:ZSet 底层是什么结构?
跳表(skiplist)+ 哈希表。跳表支持 O(logN) 范围查询和排名,哈希表支持 O(1) 查询分数。
Q6:ZSet 为什么用跳表而不用红黑树?
跳表实现简单(100行 vs 300行),天然支持范围查询,概率平衡无需旋转。
Q7:Hash 和 String(JSON) 存对象,该用哪个?
大部分场景用 Hash(更新单字段方便)。String(JSON) 适合:字段少、整体读写、需要缓存序列化对象。
Q8:Scan 为什么比 Keys 安全?
Keys 遍历所有 Key(O(N)),阻塞主线程。Scan 分批返回(O(1)每次),不阻塞。
持久化
Q9:RDB vs AOF 的优缺点?
RDB=快照(紧凑、恢复快、可能丢数据),AOF=日志(安全、文件大、恢复慢)。生产推荐两者同时开启。
Q10:AOF 什么时候重写?
AOF 文件大小超过上次重写后的指定百分比(auto-aof-rewrite-percentage 100)。
Q11:混合持久化是什么?
Redis 4.0+:AOF 文件前半部分是 RDB 格式的快照,后半部分是增量 AOF。兼顾恢复速度和数据安全。
高可用
Q12:Sentinel 工作原理?
监控 Master → 主观下线(SDOWN) → 客观下线(ODOWN,多数投票) → 选举 Leader Sentinel → 选最优 Slave 提升为 Master → 通知客户端。
Q13:Cluster 数据怎么分布的?
CRC16(key) % 16384 → 哈希槽 → 槽均匀分布到各节点。16384 个槽。
Q14:Cluster 中跨 Key 操作怎么处理?
用 Hash Tag
{user:1}:name让相关 Key 落在同一个槽。
缓存三大问题
Q15:缓存穿透是什么?怎么解决?
查一个不存在的数据,绕过缓存直击 DB。解决:①布隆过滤器;②缓存空值(短期)。
Q16:缓存击穿是什么?怎么解决?
一个热 Key 过期,大量请求同时打到 DB。解决:①互斥锁;②永不过期 + 异步更新。
Q17:缓存雪崩是什么?怎么解决?
大量 Key 同时过期,DB 瞬间被打爆。解决:①过期时间加随机值;②多级缓存;③限流降级。
分布式
Q18:分布式锁怎么实现?
SET lock:key unique_value NX EX 30。加锁用 SETNX,解锁用 Lua 判断 value 后 DEL(防误删)。
Q19:Redlock 算法是什么?
在 N 个独立的 Redis Master 上分别加锁,超过半数成功才算加锁成功。防止单点 Redis 故障导致锁失效。
Q20:如何保证 DB 和缓存一致性?
延迟双删:先删缓存 → 更新 DB → 延迟后再删缓存。或异步更新:先更新 DB → 通过 MQ/Canal 异步更新缓存。
优化
Q21:bigkey 怎么发现和处理?
redis-cli --bigkeys扫描。处理:拆分大 Key、UNLINK 异步删除。
Q22:热 key 怎么处理?
①客户端本地缓存;②多副本热 Key;③读写分离(读 Slave)。
Q23:内存淘汰策略有哪些?
noeviction(不淘汰)、allkeys-lru(LRU淘汰)、volatile-lru、allkeys-lfu、volatile-lfu、random 等。
场景设计
Q24:设计一个排行榜
ZSet:
ZADD rank 9500 张三+ZREVRANGE rank 0 9 WITHSCORES取 Top10。
Q25:设计一个计数器
INCR原子递增。高并发下批量合并:本地计数 + 定时刷到 Redis。
Q26:设计一个消息队列
简单用 List(BLPOP),可靠用 Stream(消费者组+ACK)。
38.3 进阶学习路线
- 阅读 Redis 源码(重点:dict、skiplist、ae 事件循环)
- 阅读《Redis 设计与实现》(黄健宏)
- 学习 Redis 协议(RESP)
- 参与 Redis 社区贡献
最后的话
你从零开始,走完了 38 章的 Redis 学习旅程。掌握了从基础命令到集群部署、从缓存策略到 Go 实战的全链路技能。
Redis 最强大的不是"快",而是它的数据结构和组合方式。学会用 Redis 的思维(KV + 数据结构)解决问题,你就是一个合格的 Redis 工程师。
祝你成为一名优秀的后端工程师!