Skip to content

Redis 从零到精通验收清单

这页用来回答:Redis 文档是不是只讲了几个命令和八股题,还是能让零基础真正学会生产级 Redis?

学完 Redis 不能只会说“Redis 快、缓存穿透、分布式锁”。你要能解释 Redis 为什么快、为什么也会慢、命令执行全过程、数据结构适合什么场景、缓存和数据库为什么会不一致、哨兵和集群有什么区别、大 Key 和热 Key 为什么危险、线上 timeout 怎么按证据排查。

最终目标

学完 Redis 专栏后,你至少要能做到:

  1. 判断一个业务场景是否适合放 Redis。
  2. 根据访问模式选择 String、Hash、List、Set、ZSet、Bitmap、HyperLogLog。
  3. 解释 Redis 命令从网络事件到数据结构操作的全过程。
  4. 解释 Redis 为什么快,以及大 Key、热 Key、慢命令为什么会让它慢。
  5. 设计 Cache Aside,并处理穿透、击穿、雪崩和缓存一致性。
  6. 解释 TTL、惰性删除、定期删除、内存淘汰策略。
  7. 解释 RDB、AOF、主从复制、哨兵、Cluster 的原理和边界。
  8. 正确使用分布式锁,并知道 Redlock、Fencing Token 的适用边界。
  9. 排查 timeout、连接池耗尽、慢命令、大 Key、热 Key、主从延迟、Cluster 热点。
  10. 面试时能标准回答,追问时能跳回原理页讲流程和 Demo。

总路线

mermaid
flowchart TD
    A["阶段 1<br/>场景和数据结构"] --> B["阶段 2<br/>命令执行原理"]
    B --> C["阶段 3<br/>缓存模式和一致性"]
    C --> D["阶段 4<br/>过期删除和内存淘汰"]
    D --> E["阶段 5<br/>持久化和高可用"]
    E --> F["阶段 6<br/>高并发缓存问题"]
    F --> G["阶段 7<br/>分布式锁"]
    G --> H["阶段 8<br/>生产排查"]
    H --> I["阶段 9<br/>面试和商业落地"]

为什么要按这个顺序?

阶段原因如果跳过
先学场景Redis 不是 MySQL 替代品核心事实数据误放 Redis
再学数据结构结构决定命令复杂度和内存形成大 Key、慢命令
再学执行原理知道单线程为什么快也为什么会被阻塞只会背“内存快”
再学缓存一致性Redis 最常见用途是缓存旧数据、击穿、雪崩无法处理
再学过期淘汰缓存一定要面对内存和 TTL内存满、Key 不过期看不懂
再学高可用生产不能只部署单机主从、哨兵、Cluster 混淆
再学锁分布式锁容易误删和超时失效并发任务重复执行
最后排查生产问题是多机制叠加timeout 只会重启

阶段 1:场景和数据结构

Redis 适合保存高频访问、低延迟、临时性或可重建的数据。它通常不是权威事实源。

mermaid
flowchart TD
    A["业务数据"] --> B{"是否强一致且不可丢"}
    B -- "是" --> C["优先 MySQL / 关系库"]
    B -- "否" --> D{"是否高频访问或临时状态"}
    D -- "是" --> E["适合 Redis"]
    D -- "否" --> F["不一定需要 Redis"]

数据结构验收

数据结构适合场景不适合误用
String缓存、计数器、锁 token超大 JSON 对象
Hash对象字段、购物车field 数无限增长的大 Hash
List简单队列、时间线可靠消息队列主力
Set去重、标签、共同好友需要排序的排行榜
ZSet排行榜、延迟任务、TopN超大集合全量读取
Bitmap签到、是否存在、布尔统计稀疏且 ID 巨大的场景
HyperLogLogUV 估算需要精确去重明细

Demo:资产详情缓存

bash
set asset:detail:1001 '{"id":1001,"name":"CT-001","status":"USED"}' ex 1800
get asset:detail:1001
ttl asset:detail:1001

为什么要设置 TTL?

  1. 防止旧缓存永久存在。
  2. 释放长期不用的数据。
  3. 给缓存和数据库不一致提供兜底恢复。

如果是资产字段列表,不要把全医院所有字段塞进一个 Key。应该按表、模块、分页或业务维度拆分,避免大 Key。

阶段 2:命令执行原理

Redis 快不是一句“内存数据库”就能解释清楚。

mermaid
flowchart TD
    A["客户端请求"] --> B["网络 IO 事件"]
    B --> C["解析 Redis 协议"]
    C --> D["命令排队"]
    D --> E["命令执行线程操作数据结构"]
    E --> F["生成响应"]
    F --> G["网络返回客户端"]

为什么快

原因解释
内存访问大多数操作不需要磁盘随机 IO
IO 多路复用少量线程管理大量连接事件
命令执行模型简单核心命令顺序执行,减少锁竞争
数据结构优化String、Hash、ZSet 等为场景优化
命令粒度小很多命令是 O(1) 或 O(logN)

为什么也会慢

慢的原因例子后果
大 KeyHGETALL 巨大 Hash主线程长时间处理,后续命令排队
热 Key某商品详情被大量访问单节点 CPU 或网络打满
慢命令KEYS *、大范围 ZRANGE阻塞其他请求
长 Lua脚本执行过久命令线程被占用
网络大包一次返回几十 MB带宽和客户端解析慢
持久化压力AOF rewrite、RDB fork延迟抖动

验收问题:

  1. Redis 单线程为什么还能高并发?
  2. Redis 6/7 的多线程主要优化什么?
  3. 为什么一个慢命令会影响其他请求?
  4. 为什么 KEYS * 线上危险?

详细看:命令执行与数据结构原理

阶段 3:缓存模式和一致性

最常见模式是 Cache Aside。

mermaid
flowchart TD
    A["读请求"] --> B["查 Redis"]
    B --> C{"命中"}
    C -- "是" --> D["返回缓存"]
    C -- "否" --> E["查数据库"]
    E --> F{"数据库是否有数据"}
    F -- "有" --> G["写缓存并设置 TTL"]
    F -- "无" --> H["缓存空值或直接返回"]
    G --> I["返回"]
    H --> I

写操作推荐链路

常见推荐是:先更新数据库,事务提交后删除缓存

mermaid
flowchart TD
    A["写请求"] --> B["开启数据库事务"]
    B --> C["更新 MySQL"]
    C --> D["提交事务"]
    D --> E["删除 Redis 缓存"]
    E --> F{"删除是否成功"}
    F -- "成功" --> G["结束"]
    F -- "失败" --> H["记录重试或发送补偿消息"]

为什么不是先删缓存?

  1. 先删缓存后,另一个读请求可能读旧数据库。
  2. 读请求把旧值重新写回 Redis。
  3. 写请求再更新数据库。
  4. 结果缓存长期是旧值。

为什么不是直接更新缓存?

  1. 缓存值可能是复杂聚合结果,更新成本高。
  2. 并发写入顺序很难保证。
  3. 删除缓存让下一次读取按数据库事实重建,更稳。

详细看:缓存一致性

阶段 4:过期删除和内存淘汰

TTL 不是到点立即删除所有 Key。Redis 主要靠惰性删除和定期删除配合。

mermaid
flowchart TD
    A["Key 设置 TTL"] --> B["到达过期时间"]
    B --> C{"是否被访问"}
    C -- "是" --> D["惰性删除"]
    C -- "否" --> E["等待定期抽样检查"]
    E --> F["发现过期后删除"]

内存满了怎么办

maxmemory 到达限制,Redis 会按淘汰策略处理。

策略含义适合场景
noeviction不淘汰,写入报错不允许丢缓存,需要应用兜底
allkeys-lru从所有 Key 中淘汰最近少用通用缓存
volatile-lru只淘汰设置 TTL 的 Key只让缓存 Key 参与淘汰
allkeys-lfu淘汰低频访问 Key热点明显场景
volatile-ttl优先淘汰快过期 KeyTTL 语义强的缓存

验收问题:

  1. Key 到期为什么不一定马上消失?
  2. 惰性删除和定期删除分别解决什么?
  3. 内存淘汰和过期删除有什么区别?
  4. 为什么生产 Key 最好设置 TTL?

详细看:过期删除与内存淘汰原理

阶段 5:持久化和高可用

Redis 高可用要分清:持久化、复制、故障转移、分片扩容

能力解决什么不解决什么
RDB某个时间点快照两次快照之间可能丢数据
AOF追加命令日志,降低丢失窗口文件变大,需要 rewrite
主从复制读扩展和副本备份主库挂了不会自动切换
Sentinel监控主库并自动故障转移不做数据分片
Clusterslot 分片,扩容量和吞吐单 Key 热点仍在一个 slot

哨兵和 Cluster 区别

mermaid
flowchart TD
    A["Redis 高可用"] --> B["主从 + Sentinel"]
    A --> C["Redis Cluster"]
    B --> D["解决主节点故障自动切换"]
    B --> E["数据仍是一整份"]
    C --> F["按 slot 分片存储"]
    C --> G["解决容量和吞吐扩展"]
对比哨兵模式Cluster 模式
数据分片不分片,每组是一整份数据16384 slot 分布在多个主节点
主要目标自动故障转移分片扩容 + 故障转移
客户端行为连接主从,感知主从切换需要处理 MOVED、ASK
适合数据量不大但需要高可用数据量大、吞吐高、需要横向扩展
热 Key仍可能压垮主节点单 Key 仍只落一个 slot,仍可能热点

验收问题:

  1. RDB 和 AOF 各自丢数据窗口是什么?
  2. 主从复制全量和增量怎么理解?
  3. Sentinel 怎么判断主观下线和客观下线?
  4. Cluster 的 slot、MOVED、ASK 是什么?
  5. 为什么 Cluster 不能天然解决单个热 Key?

详细看:主从哨兵 Cluster 全过程原理

阶段 6:高并发缓存问题

穿透、击穿、雪崩

问题本质治理
穿透查询不存在数据,每次都打 DB参数校验、空值缓存、布隆过滤器
击穿热点 Key 失效瞬间打 DB互斥锁、逻辑过期、热点预热
雪崩大量 Key 同时失效或 Redis 故障TTL 随机、多级缓存、限流降级

布隆过滤器

mermaid
flowchart TD
    A["查询 assetId"] --> B["布隆过滤器判断"]
    B --> C{"一定不存在?"}
    C -- "是" --> D["直接返回空"]
    C -- "否,可能存在" --> E["查 Redis"]
    E --> F["未命中再查 MySQL"]

布隆过滤器特点:

  1. 判断不存在一定可信。
  2. 判断存在只是可能存在。
  3. 会误判,不会漏判。
  4. 删除困难,删除多时通常重建。

大 Key 和热 Key

问题本质治理
大 Key单个 value 太大或集合元素太多拆 Key、分页、限制大小、UNLINK
热 Key单个 Key 访问量极高本地缓存、拆 Key、限流、请求合并

大 Key 是“单次操作重”,热 Key 是“访问频率高”。一个 Key 可以同时又大又热。

详细看:大 Key 与热 Key 全过程治理高并发缓存治理

阶段 7:分布式锁

Redis 分布式锁的基础写法:

bash
set lock:order:1001 token-uuid nx ex 30

释放锁必须判断 token:

lua
if redis.call("get", KEYS[1]) == ARGV[1] then
  return redis.call("del", KEYS[1])
else
  return 0
end

为什么不能直接 del

mermaid
flowchart TD
    A["线程 A 获取锁,过期 30 秒"] --> B["线程 A 业务执行超过 30 秒"]
    B --> C["锁自动过期"]
    C --> D["线程 B 获取同一把锁"]
    D --> E["线程 A 执行 del"]
    E --> F["误删线程 B 的锁"]

所以锁 value 必须是唯一 token,释放时用 Lua 保证“判断和删除”原子执行。

Redlock 和 Fencing Token

Redlock 试图在多个独立 Redis 节点上获取多数派锁,但它仍然依赖时钟、网络和锁过期假设。对强一致要求极高的场景,不能只靠 Redlock,通常还要用数据库唯一约束、乐观锁、状态机或 Fencing Token。

Fencing Token 是递增令牌。即使旧客户端锁过期后又继续执行,下游也可以根据更小的 token 拒绝旧请求。

详细看:分布式锁红锁 Redlock锁扩展点

阶段 8:生产排查

Redis timeout 排查流程

mermaid
flowchart TD
    A["应用 Redis timeout"] --> B{"是单接口还是全站"}
    B -- "单接口" --> C["查该接口 Key 和命令"]
    B -- "全站" --> D["查 Redis 实例和网络"]
    C --> E["SLOWLOG / bigkeys / hotkeys"]
    D --> F["INFO CPU / memory / clients / persistence"]
    E --> G{"是否大 Key 或慢命令"}
    G -- "是" --> H["拆 Key、分页、禁用危险命令"]
    G -- "否" --> I["查连接池、网络、下游阻塞"]
    F --> J{"是否内存、持久化、主从异常"}
    J -- "是" --> K["扩容、调参、故障转移"]
    J -- "否" --> I

证据清单

证据看什么
应用日志timeout 是读、写、锁还是批量命令
连接池指标活跃连接、等待连接、最大连接
SLOWLOG是否有慢命令
INFO commandstats哪类命令调用多、耗时高
MEMORY USAGE某个 Key 是否过大
--bigkeys大 Key 分布
--hotkeys热 Key 候选
INFO memoryused_memory、碎片率、淘汰
INFO persistenceRDB/AOF 是否造成抖动
INFO replication主从延迟、复制状态
Cluster 指标slot 分布、单节点热点、MOVED/ASK

不能做什么

错误操作后果
线上 KEYS *阻塞 Redis 主线程
对大集合 HGETALL网络和主线程压力巨大
直接 DEL 大 Key同步释放内存阻塞
timeout 就加连接池可能放大 Redis 压力
Redis 挂了全部打 DB数据库雪崩
分布式锁无 token可能误删别人的锁

阶段 9:商业场景验收

资产详情缓存

必须做到:

  1. Key 命名清晰,例如 asset:detail:{assetId}
  2. 设置 TTL,并根据业务加随机抖动。
  3. 更新数据库后删除缓存。
  4. 删除失败进入重试或 CDC 补偿。
  5. 查询不存在资产时缓存短 TTL 空值或用布隆过滤器。

热点字典配置

必须做到:

  1. Redis 缓存全局字典。
  2. 应用本地缓存短 TTL,降低 Redis 热点。
  3. 配置变更后发送失效通知。
  4. 权限、金额、库存这类强一致数据不能照搬本地缓存策略。

分布式任务防重复

必须做到:

  1. SET NX EX 获取锁。
  2. value 使用唯一 token。
  3. Lua 判断 token 后释放。
  4. 任务耗时超过锁时间要考虑续期或改用调度框架。
  5. 数据库层仍用唯一约束或状态机兜底。

面试闭环

高频问题标准回答深入原理
Redis 为什么快Redis 面试命令执行与数据结构原理
单线程为什么高并发Redis 面试高并发缓存治理
穿透击穿雪崩Redis 面试缓存问题
布隆过滤器Redis 面试布隆过滤器原理
大 Key 热 KeyRedis 面试大 Key 与热 Key 治理
缓存一致性Redis 面试缓存一致性
哨兵和集群区别Redis 面试主从哨兵 Cluster 全过程原理
分布式锁Redis 面试分布式锁
Redis容器化怎么保证内存和数据安全Redis 面试配置、ACL、RDB/AOF、内存与高可用

最终验收题

问题合格标准
Redis 是否适合某场景能说清事实源、缓存、临时状态边界
数据结构怎么选能按访问模式和复杂度选择
Redis 为什么快能说内存、IO 多路复用、命令模型和数据结构
Redis 为什么慢能说大 Key、热 Key、慢命令、持久化、网络
缓存一致性能画出先写库后删缓存和失败补偿
穿透击穿雪崩能说本质、流程和治理
布隆过滤器能说位数组、多哈希、误判、不漏判
哨兵和 Cluster能说高可用和分片扩容区别
分布式锁能写 SET NX EX、Lua 释放,并说风险
生产 timeout能按应用、连接池、slowlog、bigkeys、info 排查
Redis容器化能解释ACL Secret、/data Volume、RDB/AOF、fork/COW、maxmemory与cgroup余量,以及单容器和高可用的边界

本章小结

真正学会 Redis,不是会背命令,而是能把业务场景、数据结构、命令执行、缓存一致性、过期淘汰、持久化、高可用、大 Key、热 Key、分布式锁、生产排查串成闭环。

如果某个问题讲不清,就回到对应知识点页重新看流程图、Demo 和商业场景。Redis 的问题往往不是单点知识不会,而是把缓存、数据库、线程池、网络、持久化、集群和业务一致性割裂开看。