Skip to content

Redis 速查卡

🎯 覆盖 32 题 | ⭐ 10 题 | 预计扫描 12 分钟 📌 先看⭐一句话答案 → 展开要点 → 自测清单检验


一、数据结构

知识地图:String(SDS) / Hash(listpack→hashtable) / List(quicklist) / Set(hashtable) / ZSet(skiplist+hashtable)

⭐ 五种数据类型 + 场景

类型底层典型场景
StringSDS缓存对象、计数器(INCR)、分布式锁(SETNX)、Session
Hashlistpack/hashtable对象属性(用户信息)、购物车
Listlistpack/quicklist消息队列(LPUSH+BRPOP)、Feed流
Setlistpack/hashtable去重(抽奖)、共同好友(SINTER)
ZSetlistpack/skiplist+hashtable排行榜(ZREVRANGE)、延迟队列(score=时间戳)

⭐ ZSet 底层 = 跳表 + 哈希表

一句话: ZSet 同时维护 skiplist(按 score 排序,支持范围查询 O(log N))和 hashtable(member→score 映射,O(1) 查分数),两者结合实现"既能排序又能快查"。

跳表核心: 多层链表 + 随机层高(P=0.25),查询 O(log N);比红黑树实现更简单、范围查询更自然、并发友好

为什么不用 B+ 树: Redis 数据在内存,B+ 树的磁盘页对齐优势无意义;跳表实现更简单


二、性能原理

⭐ Redis 为什么快

一句话: 六大原因——纯内存操作 + 命令执行单线程(无锁无切换) + IO 多路复用(epoll) + 高效数据结构 + 渐进式 rehash + RESP 协议简单。

⚠️ 易错:"单线程"指命令执行单线程;Redis 6.0+ 网络 IO 读写已经是多线程

↳ 追问:单线程但仍需分布式锁(SETNX/Lua),因为多个命令之间不是原子的(如先 GET 再 SET)


三、缓存问题

⭐ 穿透 / 击穿 / 雪崩

一句话: 穿透=查不存在的 key(恶意攻击),击穿=热点 key 突然过期,雪崩=大量 key 同时过期或 Redis 宕机。

问题原因解决方案
穿透查询不存在的数据,缓存和 DB 都没有① 缓存空值(短TTL) ② 布隆过滤器(推荐)
击穿热点 key 过期,大量请求打到 DB① 互斥锁重建 ② 逻辑过期(异步刷新,返回旧数据)
雪崩大量 key 同时过期 / Redis 宕机① TTL 加随机偏移 ② 集群高可用 ③ 多级缓存

布隆过滤器: m 位 bit 数组 + k 个哈希函数;"不存在"100%确定,"存在"有误判率

⚠️ 易错:三者不要混淆——穿透是数据根本不存在,击穿是热点 key 过期,雪崩是大面积过期/宕机


四、持久化与过期

⭐ 过期策略 + 淘汰策略

一句话: 过期用惰性删除(访问时检查)+定期删除(100ms抽样清理)双策略结合;内存满时触发淘汰策略,推荐 allkeys-lru

过期: 惰性删除(按需,CPU友好但可能积压) + 定期删除(抽样,兜底清理)

淘汰策略TOP3:

策略范围适用
allkeys-lru所有 key缓存场景(推荐)
allkeys-lfu所有 key访问频率差异大
volatile-lru有过期时间的 key混合场景(保护永久key)

RDB vs AOF: RDB=定时快照(文件小恢复快但可能丢分钟级数据);AOF=记录每条写命令(默认每秒fsync最多丢1s);推荐混合持久化(RDB+AOF增量)


五、分布式锁

⭐ Redis 分布式锁演进

一句话: 从 SETNX(不原子) → SET EX NX(原子加锁) → Lua 脚本释放(防误删) → Redisson(自动续期 Watch Dog + 可重入),生产用 Redisson。

四阶段演进:

① SETNX + DEL                      → 问题:SETNX和EXPIRE不原子,宕机死锁
② SET key uuid EX 30 NX             → 问题:业务超时锁自动过期,可能误删他人锁
③ Lua 脚本释放(检查uuid再DEL)        → 问题:业务超时仍可能导致锁过期
④ Redisson(Watch Dog每10s自动续期)    → 生产推荐,支持可重入/公平锁/读写锁

Redisson 加锁 Lua 核心: 锁用 Hash 结构(key=锁名, field=threadId, value=重入次数),不存在则 hset + pexpire;同线程则 hincrby 重入

Watch Dog: 默认锁 30s,每 10s 检查续期;线程正常释放则取消续期;JVM 宕机则 30s 后自动过期

⚠️ 易错:主从切换可能导致锁丢失(异步复制);Redlock 方案争议大,大多数场景单机 Redisson 够用;强一致用 ZooKeeper


六、一致性与集群

⭐ Redis 和 MySQL 数据一致性

一句话: 写操作先更新 DB 再删除 Cache(不是更新 Cache),用删除保证最终一致;强可靠用 Canal 监听 binlog + MQ 异步删除。

为什么是"删除"不是"更新": 更新需保证 DB+Cache 两步原子,复杂;删除后下次读自动重建,简单正确

为什么先更新 DB 再删 Cache(不反过来):

错误(先删Cache再更新DB):A删Cache → B读Cache miss读到旧DB写回Cache → A更新DB → 不一致!
正确(先更新DB再删Cache):微小窗口后Cache被删,下次读到新数据 → 最终一致

加强方案: 延迟双删(先删→更新DB→延迟500ms→再删)/ Canal 监听 binlog 异步删除


六B、集群架构(Sentinel / Cluster)

⭐ Sentinel 哨兵模式

一句话: 三大功能——监控主从节点健康 + 自动故障转移(选新主) + 通知客户端新主地址;至少 3 个 Sentinel 奇数部署。

下线判断: SDOWN(主观,单个哨兵超时) → ODOWN(客观,quorum 个哨兵共识) → 触发故障转移

选新主顺序: 过滤不健康 → slave-priority 小的优先 → 复制偏移量大的优先(数据最新) → runId 最小

⚠️ 局限:写仍集中在单主,无法水平扩展写能力和存储容量


⭐ Redis Cluster 架构

一句话: 去中心化 P2P 架构,16384 个 hash slot 分片到多主节点,CRC16(key) % 16384 决定路由;每主配从实现高可用。

核心要点:

slot 数量 = 16384(心跳 bitmap 仅 2KB,工程平衡点)
路由:CRC16(key) % 16384 → slot → node
Hash Tag:{user:1001}:info 强制相关 key 落同一 slot
Gossip 通信:MEET/PING/PONG/FAIL,节点间交换状态,最终一致

故障转移: PFAIL(单节点超时) → 半数主节点确认 → FAIL → 从节点选举(偏移量最大优先) → 接管 slot

扩缩容: 添加节点 → resharding(slot 迁移,IMPORTING+MIGRATING+MIGRATE 逐 key 搬) → 迁移中 ASK 临时重定向

MOVED vs ASK: MOVED = slot 永久迁完,更新客户端映射表;ASK = slot 正在迁移,仅本次临时重定向


⭐ 三种部署模式对比

模式高可用数据分片写扩展适用
单机不支持不支持开发测试
哨兵自动切换不支持(全量在主)不支持(单主)读多写少,数据量可单机承载
Cluster自动切换16384 slot多主并行写大数据量、高并发、水平扩展

选型: 数据量单机装得下 → 哨兵(1主2从3哨兵);装不下或写QPS高 → Cluster(≥3主3从)


补充速览

关键词核心答案
SDSO(1)获取长度 + 空间预分配 + 惰性释放 + 二进制安全
渐进式 rehash扩容时不一次性迁移,每次操作顺带迁移一个桶;查询先查 ht[0] 再查 ht[1]
Bitmap底层是 String(SDS),按 bit 位操作;最大 512MB = 42.9 亿 bit;用于签到/UV统计
热 key本地缓存(Caffeine) + 分散 key(热key复制多份随机读)
大 key拆分 + UNLINK 异步删除 + HSCAN 分批读
逻辑过期key 永不过期,value 存过期时间;过期后互斥锁异步重建 + 返回旧数据
主从复制全量(RDB+buffer) → 增量(repl_backlog) → 命令传播(异步)
本地缓存一致性短 TTL(5s) + Redis Pub/Sub 广播失效;多实例各自有 Caffeine 需通知清除
限流固定窗口(INCR,有边界问题) → 滑动窗口(ZSet,精确) → 令牌桶(允许突发)
Redlock5个独立实例,过半加锁成功;争议大,强一致用 ZK/etcd
Redis vs ZK 锁Redis: AP/高性能/TTL释放;ZK: CP/强一致/临时节点自动释放
Sentinel 故障转移SDOWN→ODOWN→Raft选Leader→选新主(偏移量最大)→SLAVEOF NO ONE
16384 slotCRC16(key)%16384;bitmap仅2KB;hash tag {}强制同slot
Gossip 协议MEET/PING/PONG/FAIL四种消息,节点间随机交换,最终一致
Cluster 故障转移PFAIL→半数主节点确认FAIL→从节点选举→接管slot→广播PONG
Slot 迁移IMPORTING+MIGRATING+MIGRATE逐key搬;迁移中ASK临时重定向

🧠 助记汇总

口诀含义
穿不存,击过期,崩大面积穿透=数据不存在;击穿=热key过期;雪崩=大面积过期/宕机
先DB后删Cache缓存一致性写操作顺序
内单路结渐简Redis快的六原因:内存/单线程/多路复用/数据结构/渐进rehash/协议简单
跳哈双结构ZSet = 跳表(有序) + 哈希表(O(1)查分数)
NX→EX NX→Lua→Redisson分布式锁四阶段演进
主客观,选最新Sentinel:SDOWN→ODOWN→选偏移量最大的从节点
一万六千三百八十四16384 个 hash slot,CRC16 取模路由
MOVED 永久,ASK 临时客户端路由重定向的两种类型

✅ 自测清单

#问题你能说出...
1五种数据类型底层结构 + 各自典型场景
2ZSet 底层skiplist+hashtable 双结构 + 为什么不用B+树
3Redis 为什么快六大原因 + "单线程"具体指什么
4穿透/击穿/雪崩三者区别 + 各自解决方案
5分布式锁四阶段演进 + Redisson Watch Dog 原理
6缓存一致性先更新DB再删Cache + 为什么是删除不是更新
7过期+淘汰双删除策略 + 推荐淘汰策略
8RDB vs AOF各自优缺点 + 推荐混合
9Sentinel 哨兵SDOWN/ODOWN区别 + 选新主规则 + 局限性
10Cluster 架构16384 slot + CRC16路由 + hash tag
11Cluster 故障转移PFAIL→FAIL + 从节点选举 + slot接管
12MOVED vs ASK永久重定向 vs 临时重定向 + 客户端行为区别
13三种部署模式单机/哨兵/Cluster 适用场景 + 选型决策

💡 首次全部过一遍 → 第2天只过答不上来的 → 第4天再复习 → 面试前一天最后扫一遍