学习地图
这门学科是干什么的
Redis 是一个基于内存的键值数据库,但如果只把它理解成"缓存工具"就太窄了。更准确地说,它是一个数据结构服务器 :你提交命令,它直接帮你在内存里维护 String、Hash、List、Set、ZSet 等结构,并提供过期、持久化、复制、高可用、分布式能力。
你学习 Redis 的本质,不是背命令,而是建立这条主线:
业务问题 -> 选合适的数据结构 -> 设计 Key -> 设置过期/持久化/一致性策略 -> 处理高并发与故障
这是后面所有实战和面试题的总框架,必须吃透。
它解决什么问题
Redis 最常解决的是下面几类问题:
- 加速读取
把热点数据放在内存里,减少对 MySQL 等磁盘数据库的访问。 - 承接高并发
比如秒杀、热点商品、排行榜、验证码、会话状态。 - 临时状态存储
比如登录状态、短信验证码、接口幂等标记、分布式锁。 - 数据结构型需求
比如计数器、队列、去重集合、排行榜。 - 高可用与扩展
通过主从复制、哨兵、集群支撑线上系统。
它和哪些相关技术有关系
| 相关技术 | 和 Redis 的关系 | 你要建立的联系 |
|---|---|---|
| MySQL / PostgreSQL | Redis 常作为前置缓存或辅助存储 | Redis 解决"快"和"并发",关系型数据库解决"持久"和"复杂查询" |
| Memcached | 都能做缓存 | Redis 不只是缓存,还支持数据结构、持久化、复制 |
| Kafka / RabbitMQ | 都可能出现在异步系统里 | Redis 可做轻量队列,但不是强消息中间件的完全替代 |
| Nginx / API 网关 | 网关扛流量,Redis 扛状态 | 常结合限流、验证码、登录态 |
| Java / Go / Node.js | 业务代码通过客户端操作 Redis | 学会"命令模型"和"客户端封装"同样重要 |
| Linux | Redis 常部署在 Linux | 基础运维、日志、端口、进程、内存排查都离不开 |
| 分布式系统 | Redis 常被用来做共享状态 | 要理解一致性、可用性、故障恢复、脑裂风险 |
学它之前需要哪些前置知识
必须具备
- 基本编程能力,知道变量、对象、数组、函数。
- 会使用命令行,至少能执行程序、看端口、看日志。
- 知道什么是客户端/服务端、TCP 连接、请求/响应。
- 知道数据库最基本概念:读、写、索引、事务、持久化。
有了会更顺
- Linux 基础。
- 一门后端语言的 Redis 客户端用法。
- 基本的数据结构知识:哈希表、链表、跳表、集合。
真正重要的 20% 核心内容是什么
下面这些内容,决定你是否真正掌握 Redis 的 80% 实战价值:
- Redis 的定位和边界
它适合什么,不适合什么。 - 五大核心数据类型
String、Hash、List、Set、ZSet的使用场景。 - 缓存设计
缓存命中、穿透、击穿、雪崩、一致性。 - 过期机制与淘汰策略
Key 为什么会过期、什么时候真正删除、内存满了怎么办。 - 持久化
RDB和AOF的区别、取舍、恢复过程。 - 高可用
主从复制、哨兵、集群的作用边界。 - 性能与排错
大 Key、热 Key、阻塞命令、慢查询、内存膨胀。
哪些内容是初学者容易陷入、但不值得一开始深挖的
先知道,后深入
- Redis 源码级对象系统细节。
- 每一种内部编码转换阈值。
- 集群槽位迁移细节和故障注入。
Lua、Function、Module的深层实现。HyperLogLog、Bitmap、GEO、Stream的边缘用法。- 内存分配器
jemalloc的源码细节。
初学者最容易学偏的地方
- 只背命令,不理解"为什么选这个数据结构"。
- 只会把 Redis 当缓存,不知道它还能承接状态和结构化场景。
- 只会
SET/GET,不会设计 Key、TTL、一致性策略。 - 只会用,不会解释为什么快、为什么会丢数据、为什么会出现缓存雪崩。
- 一上来就学集群搭建,却连单机行为都说不清。
学习顺序
推荐学习顺序
- 第一阶段:入门认知
先搞清 Redis 到底是什么、为什么快、为什么大家爱用它。 - 第二阶段:核心概念
把String/Hash/List/Set/ZSet的场景和命令吃透。 - 第三阶段:核心机制
过期、淘汰、事务、发布订阅、流水线。 - 第四阶段:底层原理
事件循环、I/O 多路复用、对象编码、持久化与复制主线。 - 第五阶段:工程实践
缓存设计、分布式锁、限流、排行榜、会话共享、高可用选型。 - 第六阶段:常见问题与排错
大 Key、热 Key、阻塞、慢日志、内存打满、复制延迟、连接异常。 - 第七阶段:面试与评估
用定义题、原理题、场景题、排错题建立稳定输出能力。 - 第八阶段:学习总结与知识闭环
把知识串成体系,形成"理解、上手、排错、面试"的闭环。
正确的学习方法论
- 先场景,后命令
先想"我要解决什么问题",再学 Redis 的命令。 - 先直觉,后定义,最后原理
否则会在术语里迷路。 - 先单机,后分布式
单机行为搞不懂,集群一定会学乱。 - 先主干,后枝叶
五大数据类型、缓存设计、持久化、高可用,这些必须先掌握。
企业里通常怎么用 Redis
- 热点数据缓存。
- 登录态、会话状态共享。
- 验证码、限流、幂等控制。
- 排行榜、计数器、点赞、关注关系。
- 分布式锁和轻量级队列。
面试官通常怎么问 Redis
- Redis 为什么快。
- Redis 和 MySQL / Memcached 的区别。
- 五种数据类型分别适合什么场景。
- 过期删除和内存淘汰策略。
- 缓存穿透、击穿、雪崩怎么处理。
- RDB 和 AOF 如何取舍。
- Redis 是单线程吗。
- 如何保证高可用。
必须掌握 vs 知道即可
| 层次 | 必须掌握 | 知道即可 |
|---|---|---|
| 入门 | Redis 定位、为什么快、基本命令 | 配置项全量细节 |
| 核心 | 5 大数据类型、TTL、持久化、高可用基本概念 | 冷门命令、边缘数据类型 |
| 实战 | 缓存设计、热点问题、锁、限流、排错 | 源码级内存结构 |
| 面试 | 原理解释能力、场景选型能力 | 特别深的源码优化细节 |
第一阶段:入门认知
1. 学什么
这一阶段我们先不追求"会很多命令",而是先建立 Redis 的正确直觉。
你要学会的内容有:
- Redis 到底是什么。
- 它为什么常被拿来做缓存。
- 它和 MySQL、Memcached 的本质区别。
- Redis 的基本工作方式:客户端发命令,服务端在内存中操作数据并返回结果。
- 最小命令集:
PING、SET、GET、DEL、EXPIRE、TTL。 - Redis 学习的设计哲学。
学习本质
Redis 入门最重要的不是记住多少命令,而是建立一句话认知:
Redis 是一个用内存换速度、用数据结构直接服务业务场景的系统。
这句话是 必须吃透 的,因为后面所有话题都会回到这里。
2. 为什么重要
如果你第一阶段就把定位搞错,后面会出现两类典型问题:
- 把 Redis 当成万能数据库
结果把本该放在 MySQL 的核心业务数据也塞进去,最后一致性和恢复都很痛苦。 - 把 Redis 当成只会缓存字符串的小工具
结果看不到它在排行榜、计数器、集合去重、会话共享中的价值。
这一阶段的重要性在于,它解决三个现实问题:
- 你能判断什么时候该用 Redis。
- 你能向别人解释 Redis 为什么快。
- 你能搭起一个最小可用环境并做基础操作。
3. 核心概念
3.1 用类比先理解
可以把 Redis 想成一个"超快的、住在内存里的、按命令办事的值班员":
- 你把钥匙牌
key交给它。 - 它帮你保管对应的内容
value。 - 你也可以告诉它"这份东西 60 秒后自动作废"。
- 它支持的不是单一盒子,而是很多数据结构盒子。
3.2 技术定义
Redis 是一个开源的、基于内存的、支持多种数据结构的键值数据库,提供高性能读写能力,并支持持久化、复制、过期、高可用等能力。
3.3 核心术语
| 术语 | 直觉理解 | 技术定义 | 先掌握到什么程度 |
|---|---|---|---|
| Key | 数据的名字 | Redis 中数据访问的唯一标识 | 必须掌握 |
| Value | 数据内容 | Key 对应的值,可是不同数据结构 | 必须掌握 |
| TTL | 剩余寿命 | Key 距离过期还有多少秒 | 必须掌握 |
| EXPIRE | 设置保质期 | 给 Key 设置过期时间 | 必须掌握 |
| In-memory | 数据放内存里 | 主要读写发生在内存,不靠磁盘直接查询 | 必须掌握 |
| Persistence | 落盘保存 | 把内存数据保存到磁盘,以便重启恢复 | 先知道,后深入 |
| RESP | 通信语言 | Redis 客户端与服务端交互协议 | 先知道,后深入 |
| Logical DB | 逻辑分库 | Redis 的编号数据库,如 0、1 |
知道即可 |
3.4 Redis、MySQL、Memcached 的区别
| 对比项 | Redis | MySQL | Memcached |
|---|---|---|---|
| 数据位置 | 内存为主 | 磁盘为主 | 内存 |
| 数据模型 | 键值 + 多种数据结构 | 关系型表 | 纯键值 |
| 查询方式 | 按 Key / 命令操作 | SQL | 按 Key |
| 持久化 | 支持 | 强项 | 通常不强调 |
| 常见角色 | 缓存、状态、计数、排行 | 核心业务数据 | 简单缓存 |
| 复杂查询 | 不擅长 | 擅长 | 不擅长 |
3.5 它解决什么实际问题
第一阶段你要能把 Redis 的价值压缩成 3 句话:
- 它让热点数据访问更快。
- 它让临时状态共享更容易。
- 它让一些常见业务结构不必自己在代码里重造轮子。
4. 原理解释
4.1 Redis 为什么快
先用直觉解释:
- 数据主要在内存
访问内存比访问磁盘快得多。 - 命令模型简单
大多数操作都是直接按 Key 找到值并处理。 - 核心执行路径短
请求进来,解析命令,操作内存,返回结果。 - 避免了很多关系型数据库的复杂开销
不需要 SQL 解析、复杂执行计划、磁盘页管理那一套重流程。
4.2 工作流程
一个最基础的 Redis 请求,通常会经历这些步骤:
- 客户端与 Redis 建立 TCP 连接。
- 客户端把命令按 RESP 协议发给 Redis。
- Redis 事件循环读取请求。
- Redis 解析命令并找到对应处理逻辑。
- Redis 在内存数据结构中执行操作。
- Redis 把结果返回给客户端。
- 如果配置了持久化或复制,后台还会继续做落盘或同步。
4.3 设计思想
必须吃透
- 用内存换时间
Redis 牺牲部分成本,换来极高吞吐和极低延迟。 - 用数据结构直接贴业务
排行榜就用有序集合,计数器就用字符串自增,而不是都塞成一坨文本。 - 核心简单,命令原子
单条命令的执行语义清晰,这让并发场景更容易控制。
4.4 关于"Redis 是单线程吗"
这是高频混淆点,第一阶段先建立正确说法:
- Redis 执行命令的主路径长期以单线程模型著称。
- 这不等于 Redis 整个进程完全只有一个线程。
- 现代 Redis 在网络 I/O、后台持久化等方面会使用额外线程。
你在面试里不要只背"Redis 是单线程",更准确的表达是:
Redis 的命令执行核心路径以单线程模型为主,但现代版本并不是整个系统只有一个线程。
5. 示例
5.1 最小可运行示例
如果你本机有 Docker,可以直接启动一个 Redis:
bash
docker run -d --name redis-demo -p 6379:6379 redis:7
进入客户端:
bash
redis-cli -h 127.0.0.1 -p 6379
然后执行最小命令集:
redis
PING
SET user:1 "Alice"
GET user:1
EXPIRE user:1 60
TTL user:1
DEL user:1
GET user:1
你应该看到类似结果:
text
PONG
OK
"Alice"
(integer) 1
(integer) 59
(integer) 1
(nil)
5.2 这个示例到底说明了什么
- Redis 不是"只能缓存页面",它本质上是在管理 Key 和 Value。
EXPIRE说明 Redis 天生支持"临时数据"。TTL让你观察 Key 的剩余生命周期。- 这已经足够模拟验证码、登录态、短期缓存等大量真实场景。
5.3 如果你更习惯代码
下面是一个 Node.js 示例,展示最基础的缓存读取流程:
ts
import Redis from "ioredis";
const redis = new Redis("redis://127.0.0.1:6379");
async function main() {
await redis.set("article:1", JSON.stringify({ id: 1, title: "Redis 入门" }), "EX", 60);
const value = await redis.get("article:1");
console.log(value);
console.log(await redis.ttl("article:1"));
await redis.quit();
}
main().catch(console.error);
6. 工程实践
6.1 真实工程场景
场景:电商商品详情页访问量很高,数据库压力过大。
目标:把商品详情缓存到 Redis,降低 MySQL 压力。
6.2 操作步骤
- 用户请求
/product/1001。 - 服务先查 Redis:
GET product:1001。 - 如果命中,直接返回。
- 如果没命中,查 MySQL。
- 查到后写回 Redis:
SET product:1001 <json> EX 300。 - 后续 5 分钟内的重复请求都直接走 Redis。
6.3 运行流程图
text
用户请求
-> 应用服务
-> 先查 Redis
-> 命中:直接返回
-> 未命中:查 MySQL -> 回写 Redis -> 返回结果
6.4 一个最小工程代码片段
ts
async function getProduct(id: number) {
const key = `product:${id}`;
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
const product = await db.product.findById(id);
if (!product) {
return null;
}
await redis.set(key, JSON.stringify(product), "EX", 300);
return product;
}
6.5 这一步解决了什么问题
- 数据库不必每次都抗同样的读请求。
- 热点数据能在更短时间内返回。
- 应用可以把"快读"与"准存"职责拆开。
6.6 企业里的真实用法提醒
企业里不会只写一个 GET/SET 就结束,通常还会考虑:
- Key 命名规范。
- TTL 多久合适。
- 数据更新后怎么删缓存或更新缓存。
- 热点数据失效时会不会把数据库打穿。
这些问题我们会在后续阶段系统展开。当前阶段先知道它们存在,不要一上来就钻太深。
7. 常见误区
| 误区 | 为什么错 | 正确认知 |
|---|---|---|
| Redis 就是缓存 | 过于狭隘 | Redis 还是状态存储和数据结构工具 |
| Redis 能替代 MySQL | 边界混乱 | Redis 更擅长快读和临时状态,不擅长复杂关系查询 |
| 设置了 EXPIRE 就会在那一秒立刻删掉 | 过于机械 | Redis 结合惰性删除和定期删除,不保证"秒级准点销毁" |
| Redis 是单线程,所以性能一般 | 因果倒置 | Redis 因为内存访问和简洁执行路径,反而非常快 |
| 有 Redis 就不会丢数据 | 忽略持久化配置 | 是否丢数据取决于持久化、复制和故障场景 |
| Key 随便命名就行 | 忽视工程规范 | Key 设计直接影响可维护性和排错效率 |
初学者最常踩的坑
- 不设置过期时间,临时数据越堆越多。
- 把大对象整块塞进去,后面很难更新和排查。
- 缓存命中后不理解数据来源,排错时找不到源头。
- 看到 Redis 很快,就想把什么都放进去。
8. 面试题
高频面试题 1
Redis 是什么?
回答骨架:
- Redis 是基于内存的键值数据库。
- 它支持多种数据结构,不只是简单字符串缓存。
- 常用于缓存、计数器、排行榜、会话共享、分布式锁等场景。
高频面试题 2
Redis 为什么快?
回答骨架:
- 数据主要存内存。
- 命令模型简单,执行路径短。
- 很多操作是 O(1) 或接近常数级。
- 避免了关系型数据库的复杂查询和磁盘 I/O 开销。
高频面试题 3
Redis 和 MySQL 的区别是什么?
回答骨架:
- Redis 更偏向高速访问和临时/热点数据。
- MySQL 更偏向持久化、事务、一致性和复杂查询。
- 两者通常不是替代关系,而是配合关系。
高频面试题 4
Redis 是单线程吗?
回答骨架:
- 核心命令执行路径以单线程模型为主。
- 但现代 Redis 的 I/O 和后台任务会使用多线程。
- 所以不能简单地说"Redis 整个系统只有一个线程"。
高频面试题 5
为什么 Redis 适合做缓存?
回答骨架:
- 访问快,延迟低。
- 支持 TTL,适合存放临时热点数据。
- 可以显著减轻后端数据库压力。
9. 自测题
概念自测
- 用你自己的话解释:Redis 为什么不是"只是缓存"。
- 为什么说 Redis 和 MySQL 不是替代关系,而是分工关系?
TTL和EXPIRE各自是干什么的?- 为什么"Redis 是单线程"这句话并不完整?
操作自测
- 启动一个 Redis 实例。
- 写入
name=redis。 - 给它设置 30 秒过期时间。
- 查看剩余生存时间。
- 删除这个 Key。
场景自测
判断下面场景是否适合 Redis,并说出原因:
- 首页热点商品缓存。
- 用户 5 分钟短信验证码。
- 核心订单明细长期唯一存储。
- 实时排行榜。
第一阶段练习题
练习 1:一分钟解释 Redis
请你尝试用 1 分钟回答下面这个问题:
"Redis 是什么,它解决什么问题,为什么快?"
要求:
- 不超过 150 字。
- 要同时提到"内存""数据结构""缓存/高并发"。
练习 2:命令实操
请你自己实际执行下面命令,并写出每一步的返回结果:
redis
SET login:code "842731"
EXPIRE login:code 120
TTL login:code
GET login:code
DEL login:code
GET login:code
练习 3:场景判断
下面 4 个场景,哪些优先考虑 Redis,哪些不要直接拿 Redis 当主存储?请说明理由。
- 热门文章阅读数。
- 用户登录会话。
- 财务流水主账本。
- 秒杀库存的高并发扣减辅助控制。
练习 4:对比题
请你自己填完这个表:
| 对比项 | Redis | MySQL |
|---|---|---|
| 存储位置 | ||
| 擅长场景 | ||
| 是否适合复杂查询 | ||
| 是否适合热点高并发读 |
练习 5:工程表达题
请你回答:
"如果商品详情页访问量很高,为什么要先查 Redis,再查 MySQL?"
要求:
- 从性能角度回答一次。
- 从系统分层角度再回答一次。
10. 学完标志
学完这一阶段后,你应该能做到:
- 用自己的话准确解释 Redis 是什么。
- 说清 Redis 解决的核心问题。
- 说出 Redis 为什么快,而不是只会背"单线程"。
- 搭建一个最小 Redis 环境并完成
SET/GET/EXPIRE/TTL/DEL操作。 - 判断一个场景是更适合 Redis,还是更适合 MySQL。
- 用"缓存商品详情"这个案例解释 Redis 在企业中的基本价值。
进入下一阶段前的达标标准
如果你已经能独立完成下面 3 件事,就可以进入下一阶段:
- 不看资料说清 Redis 的定位与边界。
- 实际执行基础命令并理解返回值。
- 说出至少 3 个 Redis 适合的业务场景。
下面直接进入第二阶段,并把整套 Redis 学习内容一次性闭环讲完。
第二阶段:核心概念
1. 学什么
这一阶段的核心任务只有一句话:
学会把业务需求翻译成 Redis 数据结构和命令。
你需要掌握的重点包括:
- 五大核心数据类型:
String、Hash、List、Set、ZSet。 - 每种类型最常见的命令。
- 每种类型最典型的业务场景。
- Key 设计方法。
- "业务问题 -> 数据结构选型 -> 命令设计"的思维方式。
2. 为什么重要
大部分 Redis 的使用成败,不取决于你会不会冷门命令,而取决于你会不会选类型。
它解决的现实问题是:
- 避免把所有数据都粗暴塞成字符串,导致更新困难、性能差、排错难。
- 让业务代码直接借力 Redis 的数据结构能力,而不是自己造轮子。
- 建立"数据建模"能力,这正是从初学者走向工程实践的关键一步。
如果这一阶段吃透了,你后面学缓存、锁、排行榜、限流时都会明显轻松。
3. 核心概念
3.1 五大数据类型总览
| 类型 | 直觉理解 | 常见命令 | 典型场景 | 选型关键词 |
|---|---|---|---|---|
| String | 一个值 | SET GET INCR |
缓存对象、计数器、验证码 | 单值、简单、通用 |
| Hash | 一个对象的多个字段 | HSET HGET HGETALL |
用户信息、商品字段 | 对象字段、局部更新 |
| List | 有顺序的列表 | LPUSH RPUSH LPOP RPOP |
简单队列、消息暂存 | 顺序、头尾操作 |
| Set | 无序且去重的集合 | SADD SREM SISMEMBER |
标签、去重、共同关注 | 去重、成员判断 |
| ZSet | 带分数的有序集合 | ZADD ZRANGE ZREVRANK |
排行榜、优先队列 | 排序、TopN、范围查询 |
3.2 一句话选型法
- 只需要存一个值,优先看
String。 - 需要存一个对象的多个字段,优先看
Hash。 - 需要按进入顺序处理,优先看
List。 - 需要去重、判断是否存在,优先看
Set。 - 需要排序、排名、按分值区间查,优先看
ZSet。
3.3 典型术语
| 术语 | 定义 | 为什么要懂 |
|---|---|---|
| Member | 集合或有序集合中的成员 | Set/ZSet 的核心元素 |
| Score | 有序集合成员的分值 | 决定排序 |
| Field | Hash 中的字段名 | 用于对象拆分 |
| Value | 字段值或 Key 对应值 | 实际数据内容 |
| Key Pattern | Key 命名模式 | 影响维护性和排错效率 |
3.4 Key 设计规范
Redis 不是只要能用就行,Key 设计本身就是工程能力。
推荐规则:
- 使用业务前缀:
user:、product:、order:。 - 使用层级分隔:
user:1001:profile。 - 保持语义一致:同类业务同类命名。
- 对临时数据尽量配 TTL。
- 不要把版本、环境、租户信息混乱塞在一起。
一个实用示例:
| 场景 | 推荐 Key |
|---|---|
| 用户基础信息 | user:1001:profile |
| 商品详情缓存 | product:2001:detail |
| 短信验证码 | sms:login:13800138000 |
| 榜单 | rank:game:s1 |
4. 原理解释
4.1 为什么 Redis 要提供多种数据结构
如果 Redis 只提供字符串,会发生三件麻烦事:
- 你要自己在应用层序列化和反序列化复杂结构。
- 一个字段变更也要重写整个对象。
- 排行、去重、队列这些场景都要自己实现,复杂度高。
Redis 的设计思路是:
把业务里高频出现的数据组织方式直接做成原生命令。
这就是它叫"数据结构服务器"的原因。
4.2 选型流程
面对一个需求时,建议按这 5 步判断:
- 数据是单值还是多字段对象。
- 是否需要顺序。
- 是否需要去重。
- 是否需要排序。
- 是否需要频繁局部更新。
4.3 内部设计的直觉
虽然你现在还没学到底层编码,但先建立这个概念:
- Redis 对外暴露的是统一命令。
- Redis 对内会根据数据规模和数据类型选择更省空间或更快的内部编码。
- 所以同样是
Hash,小对象和大对象在内部实现上可能不一样。
这也是为什么"理解类型语义"比背内部细节更重要。
4.4 类型之间的易混淆点
| 容易混淆 | 区别核心 | 正确选型 |
|---|---|---|
| String vs Hash | 一个整体值 vs 多字段对象 | 对象字段多且可能局部更新时用 Hash |
| List vs Set | 有顺序不去重 vs 无顺序去重 | 队列看顺序,用 List;标签看去重,用 Set |
| Set vs ZSet | 去重集合 vs 带分值排序集合 | 需要排名或区间排序时用 ZSet |
5. 示例
5.1 最小可运行示例
redis
SET page:view:1001 1
INCR page:view:1001
HSET user:1001 name "Alice" age 20 city "Shanghai"
HGET user:1001 name
LPUSH queue:order 1001 1002 1003
RPOP queue:order
SADD tag:redis user:1 user:2 user:2
SISMEMBER tag:redis user:1
ZADD rank:game 98 "u1" 100 "u2" 95 "u3"
ZREVRANGE rank:game 0 2 WITHSCORES
5.2 这个示例说明了什么
- 同样是"存数据",不同类型提供的是不同操作语义。
INCR说明字符串不仅能存文本,也能做数值原子自增。Hash适合对象字段。Set天然去重。ZSet天然适合榜单。
5.3 一个业务到类型的映射例子
| 业务需求 | 推荐类型 | 原因 |
|---|---|---|
| 文章浏览数 | String |
只需要自增计数 |
| 用户资料 | Hash |
多字段、可局部更新 |
| 待处理任务队列 | List |
头尾出入队 |
| 文章标签集合 | Set |
去重、成员判断 |
| 游戏积分排行榜 | ZSet |
按分数排序 |
6. 工程实践
6.1 真实工程场景
场景:做一个社区系统,需要同时支持用户资料、文章点赞、在线排行榜。
6.2 推荐建模
- 用户资料:
Hash
user:1001:profile - 某文章点赞用户集合:
Set
post:5001:likes - 周榜积分:
ZSet
rank:weekly
6.3 操作步骤
- 注册用户时写入
Hash。 - 点赞时
SADD post:5001:likes user:1001。 - 判断是否已点赞时
SISMEMBER。 - 用户得分变化时
ZINCRBY rank:weekly 10 user:1001。 - 查询前十名时
ZREVRANGE rank:weekly 0 9 WITHSCORES。
6.4 Node.js 最小工程示例
ts
import Redis from "ioredis";
const redis = new Redis("redis://127.0.0.1:6379");
async function main() {
await redis.hset("user:1001:profile", {
name: "Alice",
city: "Shanghai",
level: "3",
});
await redis.sadd("post:5001:likes", "user:1001");
await redis.zincrby("rank:weekly", 10, "user:1001");
console.log(await redis.hgetall("user:1001:profile"));
console.log(await redis.sismember("post:5001:likes", "user:1001"));
console.log(await redis.zrevrange("rank:weekly", 0, 9, "WITHSCORES"));
await redis.quit();
}
main().catch(console.error);
6.5 企业里的经验法则
- 能用语义明确的类型,就不要全部塞
StringJSON。 - 频繁局部更新的对象优先考虑
Hash。 - 榜单、排序需求优先考虑
ZSet。 - 需要去重关系时优先考虑
Set。 - 先关注业务建模,再关注命令技巧。
7. 常见误区
| 误区 | 问题所在 | 正确认知 |
|---|---|---|
| 一个对象统一序列化成字符串最简单 | 更新单字段要读全量、改全量、写全量 | 对象字段多时优先考虑 Hash |
List 就是消息队列终极方案 |
缺少专业消息中间件很多能力 | 简单队列可用,复杂可靠消息别强行替代 |
Set 可以做排行榜 |
它没有分值排序能力 | 排名用 ZSet |
ZSet 只是会排序的 Set |
忽略了 score 的业务含义 | 排序、区间、TopN 都依赖 score |
| Key 名无所谓 | 后期很难排查和统计 | Key 设计是工程规范的一部分 |
8. 面试题
- Redis 五大数据类型分别适合什么场景?
回答重点:类型语义 + 业务映射。 - 为什么对象存储常推荐 Hash,而不是直接 JSON String?
回答重点:局部更新、字段读取、内存/维护权衡。 - Set 和 ZSet 的区别是什么?
回答重点:去重 vs 去重+有序。 - ZSet 为什么适合排行榜?
回答重点:score 排序、排名查询、TopN。 - 如何设计 Redis Key?
回答重点:前缀、层级、语义、TTL、可维护性。
9. 自测题
- 用户资料、关注列表、文章点赞、实时排行榜分别适合哪种类型?
- 如果你要实现"浏览数 +1",为什么优先用
String而不是Hash? - 为什么"共同关注"场景适合
Set? - 为什么排行榜不用
List? - 请你自己设计 5 个规范的 Redis Key。
10. 学完标志
学完这一阶段后,你应该能做到:
- 看见业务需求时,快速选出合适的数据类型。
- 熟练使用五大类型最常见命令。
- 理解不同类型背后的业务语义。
- 独立设计一套可维护的 Key 规范。
- 解释"为什么这个场景用 Hash / Set / ZSet"。
第三阶段:核心机制
1. 学什么
这一阶段不再停留在"存什么",而是学习 Redis "怎么管这些数据"。
重点包括:
- 过期机制:
EXPIRE、TTL、惰性删除、定期删除。 - 内存淘汰:
maxmemory、淘汰策略。 - 事务机制:
MULTI、EXEC、WATCH。 - Pipeline:减少网络往返。
- 发布订阅:
PUBLISH/SUBSCRIBE。 - 持久化机制的入口认知:
RDB、AOF。
2. 为什么重要
初学者最容易只看到"写进去、读出来",却忽略了两个工程真相:
- 数据不是永远留在 Redis 里。
- Redis 不是把命令执行完就万事大吉,背后还有内存、持久化和一致性代价。
这一阶段解决的实际问题是:
- 为什么设置了 TTL 却不一定准点删除。
- 为什么 Redis 内存会打满。
- 为什么 Redis 事务和数据库事务不是一回事。
- 为什么批量请求会慢,Pipeline 为什么能提速。
3. 核心概念
3.1 过期相关术语
| 术语 | 定义 | 你要理解什么 |
|---|---|---|
| TTL | Key 剩余过期时间 | 观察 Key 生命状态 |
| EXPIRE | 设置秒级过期 | 临时数据最常用 |
| PEXPIRE | 设置毫秒级过期 | 更细粒度 TTL |
| 惰性删除 | 访问到过期 Key 时再删 | 降低无效扫描成本 |
| 定期删除 | 后台周期抽样扫描过期 Key | 防止过期数据长期堆积 |
3.2 内存淘汰策略
| 策略 | 含义 | 适用直觉 |
|---|---|---|
noeviction |
不淘汰,直接报错 | 不希望无感丢数据 |
allkeys-lru |
所有 Key 中淘汰最近最少使用 | 通用缓存常用 |
volatile-lru |
只在设置了 TTL 的 Key 中淘汰 | 缓存和永久数据混存时 |
allkeys-lfu |
所有 Key 中淘汰最不常使用 | 热点明显时很实用 |
volatile-ttl |
优先淘汰快过期的 Key | 较少作为首选 |
3.3 事务相关术语
| 术语 | 定义 | 易错点 |
|---|---|---|
MULTI |
开启事务队列 | 只是开始排队,不是立刻执行 |
EXEC |
一次性执行事务队列 | 不提供传统数据库那种回滚 |
WATCH |
乐观锁监听 Key 变化 | 适合 CAS 风格控制 |
| 原子性 | 单条命令执行不可被打断 | 不等于多命令天然全局事务 |
3.4 Pipeline 与 Pub/Sub
| 机制 | 解决什么问题 | 适用边界 |
|---|---|---|
| Pipeline | 减少多次命令的网络往返开销 | 批量读写提速 |
| Pub/Sub | 简单实时消息分发 | 适合轻量通知,不适合强可靠消息 |
4. 原理解释
4.1 过期删除为什么不是"准点秒杀"
Redis 之所以不对每个 Key 都单独开一个定时器,是因为代价太高。
它采用两种配合机制:
- 惰性删除
当客户端访问某个 Key 时,Redis 发现它已过期,就顺手删掉。 - 定期删除
Redis 后台会定期随机抽样带过期时间的 Key,清理其中已过期的部分。
设计思想:
用近似高效的方式管理过期,而不是为了绝对准点付出巨大成本。
4.2 内存淘汰为什么必要
Redis 以内存为主,内存不可能无限大。
当达到 maxmemory 后,Redis 必须做选择:
- 直接拒绝新写入。
- 或按策略淘汰一部分旧数据。
这就是为什么缓存系统必须关注淘汰策略,而关系型数据库更多关注磁盘空间。
4.3 Redis 事务为什么和 MySQL 不一样
Redis 事务的重点是:
- 命令会先进入队列。
EXEC时按顺序一次执行。- 执行期间不会被其他命令插队。
但它和传统 ACID 事务不同,关键差异有两点:
- Redis 不提供复杂回滚语义。
- 如果事务中某条命令运行时报错,其他命令通常不会像关系型数据库那样整体回滚。
所以它更像"批量顺序执行 + 可选乐观锁",而不是完整数据库事务。
4.4 Pipeline 为什么快
不使用 Pipeline 时:
- 客户端发 1 条命令。
- 等 Redis 回 1 次。
- 再发下一条。
如果有 1000 条命令,光网络往返就很浪费。
Pipeline 的本质是:
一次发多条,减少 RTT,不是减少 Redis 的命令执行次数。
4.5 持久化机制的入口认知
这一阶段先建立两句话:
RDB像"拍快照"。AOF像"记操作日志"。
后面第四阶段再深入讲它们底层是怎么工作的。
5. 示例
5.1 最小可运行示例
redis
SET sms:login:13800138000 "843201" EX 300 NX
TTL sms:login:13800138000
MULTI
INCR counter:daily:login
EXPIRE counter:daily:login 86400
EXEC
SUBSCRIBE order:event
PUBLISH order:event "order:1001:paid"
5.2 Pipeline 代码示例
ts
const pipeline = redis.pipeline();
for (let i = 1; i <= 3; i++) {
pipeline.incr(`article:${i}:view`);
}
const result = await pipeline.exec();
console.log(result);
5.3 这个示例说明了什么
- 验证码场景很适合 TTL。
MULTI/EXEC可以把多命令作为一个顺序执行单元。- Pipeline 优化的是网络开销。
- Pub/Sub 更偏"即时通知",而不是可靠消息存储。
6. 工程实践
6.1 真实工程场景:短信验证码
目标:
- 验证码只允许短期有效。
- 防止重复覆盖或无限发送。
步骤:
- 生成验证码。
SET sms:login:{phone} code EX 300 NX。- 如果返回失败,说明短期内已存在验证码,不再重复发送。
- 用户提交验证码时读取并校验。
- 校验成功后删除 Key。
6.2 真实工程场景:批量统计
比如要一次更新 1000 个文章阅读数,不适合逐条请求,可以用 Pipeline 批量发命令。
6.3 持久化配置最小示例
conf
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
这个配置说明:
- 开启 AOF。
- AOF 每秒刷盘一次,性能和安全性相对平衡。
- 也保留 RDB 快照规则。
7. 常见误区
| 误区 | 问题所在 | 正确认知 |
|---|---|---|
| 设置了 TTL 就会在那一秒立刻删除 | 把实现想得过于理想化 | Redis 采用惰性 + 定期删除 |
| Redis 事务和 MySQL 事务一样 | 忽略回滚和隔离语义差异 | Redis 事务更像队列化原子执行 |
| Pipeline 能让命令本身更快 | 混淆 CPU 执行和网络往返 | Pipeline 主要优化 RTT |
| Pub/Sub 可以替代 Kafka | 忽略持久化、重试、消费确认 | Pub/Sub 适合轻通知,不是强消息系统 |
只要设了 maxmemory 就够了 |
忽略淘汰策略 | 还必须选对淘汰策略 |
8. 面试题
- Redis 过期 Key 是怎么删除的?
- 惰性删除和定期删除分别解决什么问题?
allkeys-lru和volatile-lru的区别是什么?- Redis 事务和 MySQL 事务的区别是什么?
- Pipeline 为什么能提高性能?
- Pub/Sub 适合什么,不适合什么?
- RDB 和 AOF 分别是什么思路?
9. 自测题
- 为什么 Redis 不给每个 Key 单独挂一个定时器?
- 如果缓存和永久数据混在一个实例里,你会更倾向什么淘汰策略?为什么?
MULTI/EXEC为什么不能简单等同于数据库事务?- 批量执行 1000 次
INCR时,为什么建议用 Pipeline? - Pub/Sub 和专业消息队列相比缺了哪些能力?
10. 学完标志
学完这一阶段后,你应该能做到:
- 说清 Redis 过期机制是如何工作的。
- 理解内存淘汰策略并能做基础选型。
- 解释 Redis 事务和关系型事务的本质差异。
- 在批量命令场景下正确使用 Pipeline。
- 对持久化、消息通知这些能力建立初步边界感。
第四阶段:底层原理
1. 学什么
这一阶段要回答"Redis 为什么这样设计",重点包括:
- 请求执行生命周期。
- 事件循环与 I/O 多路复用。
- RESP 协议。
- 内部数据结构与编码。
RDB、AOF的底层思路。- 主从复制的基本同步过程。
2. 为什么重要
如果你只会用 Redis 而不理解底层,你会在两个场景里卡住:
- 面试被问"为什么快""为什么会阻塞""为什么会丢数据"时说不深。
- 线上出问题时不知道从哪个机制下手排查。
底层原理不是为了炫技,而是为了解释现象、做对权衡。
3. 核心概念
3.1 请求生命周期
Client
Socket / RESP 请求
事件循环
命令解析
命令执行
内存数据结构
回复结果
AOF / RDB / 复制等后台路径
3.2 关键术语
| 术语 | 定义 | 为什么重要 |
|---|---|---|
| 事件循环 | 单线程主循环处理网络事件与命令执行 | 是 Redis 高性能核心之一 |
| I/O 多路复用 | 一个线程监听多个连接事件 | 降低大量连接的调度成本 |
| RESP | Redis 序列化协议 | 客户端与服务端的通信规范 |
| SDS | Simple Dynamic String | Redis 自己的字符串实现 |
| dict | 哈希字典结构 | 支撑大量 Key 查找 |
| quicklist | List 的底层结构之一 | 兼顾链表与紧凑存储 |
| listpack | 紧凑编码结构 | 小数据更省内存 |
| skiplist | 跳表 | 支撑 ZSet 排序与范围查询 |
| fork + CoW | 子进程 + 写时复制 | 支撑 RDB/AOF 重写的关键机制 |
3.3 数据类型与底层结构的对应直觉
| 对外类型 | 常见内部实现直觉 |
|---|---|
| String | SDS / 整数编码 |
| Hash | listpack / hashtable |
| List | quicklist |
| Set | intset / hashtable |
| ZSet | listpack / skiplist + dict |
3.4 协议示意
一个简单的 PING 在 RESP 中大致会长这样:
text
*1
$4
PING
SET name redis 大致会是:
text
*3
$3
SET
$4
name
$5
redis
协议设计追求的是:
- 易解析。
- 可扩展。
- 适合高性能网络处理。
4. 原理解释
4.1 为什么 Redis 快,不只是"因为内存"
更完整的解释应该是四层原因叠加:
- 内存访问快
避免磁盘随机 I/O。 - 事件循环简单
主线程串行执行命令,避免大量锁竞争。 - I/O 多路复用
单线程也能高效处理很多连接的可读可写事件。 - 数据结构贴业务
例如ZSet的排序查询直接交给底层结构,不需要业务层手搓。
4.2 单线程执行模型的设计思想
Redis 的核心命令执行长期采用单线程模型,背后并不是"不会多线程",而是:
- 内存操作本身很快。
- 单线程可避免共享状态带来的锁竞争。
- 简化实现和一致性保证。
它的代价也很清楚:
- 长时间命令会阻塞其他命令。
- 大 Key、大批量遍历会拖垮延迟。
所以你会看到工程实践里一直强调:
避免阻塞命令、避免大 Key、避免长事务。
4.3 RDB 的底层思路
RDB 可以理解为"某一时刻内存数据的快照"。
典型过程:
- 主进程收到
BGSAVE。 fork出子进程。- 子进程把当前内存视图写成 RDB 文件。
- 主进程继续服务请求。
- 由于写时复制,主进程后续修改的数据页才会额外复制。
设计权衡:
- 恢复速度通常较快。
- 文件紧凑。
- 但两次快照之间仍可能丢数据。
4.4 AOF 的底层思路
AOF 可以理解为"把写命令按顺序追加到日志"。
典型过程:
- 写命令执行成功。
- 追加到 AOF 缓冲。
- 按配置策略刷盘。
- 重启时重新执行日志恢复数据。
设计权衡:
- 数据更完整。
- 文件可能变大,因此需要 AOF 重写。
- 恢复速度通常不如直接加载快照。
4.5 主从复制的基本过程
你先建立一个正确主线:
- 从节点连接主节点。
- 首次全量同步时,主节点生成 RDB 发给从节点。
- 从节点加载 RDB。
- 同步过程中及之后,主节点继续把增量命令传播给从节点。
- 断线重连后,若条件允许,使用
PSYNC做部分重同步。
这就是为什么复制会和 RDB、复制偏移量、复制积压缓冲区关联起来。
5. 示例
5.1 最小可运行示例
redis
SET age 18
OBJECT ENCODING age
HSET user:1001 name "Alice" age 20
OBJECT ENCODING user:1001
BGSAVE
INFO persistence
5.2 这个示例说明了什么
- Redis 对同一种逻辑类型可能采用不同编码。
OBJECT ENCODING能帮助你观察内部编码。BGSAVE和INFO persistence能帮助你理解快照状态。
5.3 一个主从配置最小示例
主节点:
conf
port 6379
appendonly yes
从节点:
conf
port 6380
replicaof 127.0.0.1 6379
6. 工程实践
6.1 真实工程场景:为什么线上会突然卡顿
如果线上 Redis 突然延迟抖动,底层角度常见原因是:
- 有大 Key 被遍历或删除。
fork触发 RDB/AOF 重写时内存压力大。- 某个命令阻塞了主线程。
- 网络层或连接数异常。
6.2 真实工程场景:为什么会丢几秒数据
如果你只开了 RDB,且快照间隔较长,那么 Redis 异常退出时,最后一次快照之后的数据可能丢失。
6.3 企业里的常见取舍
| 目标 | 常见选择 |
|---|---|
| 更快恢复 | 偏向保留 RDB |
| 更少数据丢失 | 开启 AOF,常见 everysec |
| 高可用 | 主从 + 哨兵或集群 |
| 大规模扩容 | 集群分片 |
7. 常见误区
| 误区 | 为什么错 | 正确认知 |
|---|---|---|
| Redis 快完全因为单线程 | 解释过窄 | 是内存、事件循环、协议、数据结构共同作用 |
| 单线程一定比多线程慢 | 忽略任务性质 | 内存短操作 + 无锁模型下单线程很高效 |
| RDB 就是实时持久化 | 误把快照当日志 | RDB 是时间点快照 |
| AOF 一定完全不丢数据 | 忽略刷盘策略 | 是否丢数据与 appendfsync 策略有关 |
| 主从复制就是实时强一致 | 误判一致性 | Redis 复制是异步为主 |
8. 面试题
- Redis 为什么快?请不要只回答"因为内存"。
- Redis 为什么采用单线程执行模型?
- I/O 多路复用在 Redis 里解决什么问题?
RDB和AOF的底层思路分别是什么?fork + CoW在 Redis 持久化里起什么作用?- 主从复制首次同步流程是什么?
- 为什么大 Key 会影响 Redis 延迟?
9. 自测题
- 请你完整讲一遍一次 Redis 请求从客户端到返回结果的生命周期。
- 为什么 Redis 不希望你在主线程执行很慢的大命令?
RDB为什么既高效又可能丢失一段时间的数据?AOF everysec在性能和安全性之间做了什么权衡?- 复制中的全量同步和部分重同步有什么区别?
10. 学完标志
学完这一阶段后,你应该能做到:
- 从架构层解释 Redis 为什么快。
- 理解 Redis 请求执行生命周期。
- 说清 RDB、AOF、复制的基本底层思路。
- 解释单线程模型的优点与代价。
- 把很多线上现象和底层机制对应起来。
第五阶段:工程实践
1. 学什么
这一阶段把前面学的概念真正落到业务里,重点覆盖:
- 缓存设计模式。
- 缓存一致性。
- 缓存穿透、击穿、雪崩。
- 分布式锁。
- 限流、幂等、会话共享。
- 排行榜、计数器、轻量队列。
- 持久化与高可用的工程选型。
2. 为什么重要
企业里很少有人因为不会 SET 而用不好 Redis,真正的问题通常是:
- 缓存设计不对,把数据库打挂。
- 锁设计不对,导致重复执行或死锁。
- 高可用方案理解不清,故障时切换混乱。
- 知道命令,但不会搭业务方案。
这一阶段的目标,就是让你从"会用命令"升级到"会做方案"。
3. 核心概念
3.1 缓存三种最常见模式
| 模式 | 流程 | 最常见程度 | 说明 |
|---|---|---|---|
| Cache Aside | 先查缓存,未命中查数据库,再回填缓存 | 最常用 | 应用控制缓存逻辑 |
| Read Through | 应用只管查缓存层,缓存层负责回源 | 较少直接手写 | 常见于平台组件化方案 |
| Write Through / Write Back | 写缓存时联动写库或延后写库 | 需谨慎 | 一致性设计更复杂 |
3.2 三大缓存问题
| 问题 | 现象 | 典型方案 |
|---|---|---|
| 穿透 | 查不存在的数据,缓存和数据库都被打 | 空值缓存、布隆过滤器 |
| 击穿 | 热点 Key 失效瞬间大量请求打数据库 | 互斥锁、逻辑过期、热点永不过期 |
| 雪崩 | 大量 Key 同时失效,流量打爆后端 | TTL 打散、多级缓存、限流降级 |
3.3 分布式锁关键点
| 要点 | 为什么重要 |
|---|---|
| 获取锁要原子 | 防止并发抢锁异常 |
| 锁要有 TTL | 防止业务异常后永不释放 |
| 解锁要校验 owner | 防止误删别人的锁 |
| 锁不是银弹 | 长事务、外部调用多时要谨慎 |
最常见安全写法:
SET lock:order:1001 requestId NX PX 5000
解锁时用 Lua 脚本校验 requestId 后再删除。
3.4 高可用拓扑
| 方案 | 适合场景 | 你至少要会解释什么 |
|---|---|---|
| 单机 Redis | 开发、测试、小规模低风险 | 简单,但单点风险大 |
| 主从复制 | 读扩展、基础备份 | 主写从读,复制异步 |
| 哨兵 Sentinel | 高可用主从切换 | 监控、选主、自动故障转移 |
| Redis Cluster | 大规模分片 + 高可用 | 16384 槽位、分片路由 |
3.5 常见配置
conf
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
这 4 行已经覆盖了大量线上 Redis 基础配置思路。
4. 原理解释
4.1 Cache Aside 为什么最常见
因为它把缓存控制权交给应用:
- 读时先查 Redis。
- 未命中查数据库。
- 查到后回填 Redis。
- 写时更新数据库,再删除缓存或延迟双删。
优点:
- 简单。
- 易理解。
- 适合绝大多数业务。
代价:
- 一致性要自己处理。
- 热点失效时容易击穿。
4.2 为什么很多更新是"先更新数据库,再删缓存"
这是一个高频面试点。
原因是:
- 如果先删缓存,再写数据库,期间并发读请求可能把旧数据重新写回缓存。
- 先写数据库,再删缓存,至少保证数据库先变成新值。
它仍不是绝对完美,但在大多数业务里是性价比很高的方案。
4.3 分布式锁为什么不能直接 SETNX 后 DEL
如果你只做:
SETNX lock- 业务执行
DEL lock
可能出现问题:
- 业务执行太久,锁过期。
- 其他线程拿到新锁。
- 原线程执行完再
DEL,把别人的锁删掉。
所以解锁时必须校验"锁是不是我加的",这就是 Lua 解锁脚本的原因。
4.4 Cluster 为什么要用槽位
Redis Cluster 不按"Key 哈希后直接映射机器"做,而是引入 16384 个槽位。
设计好处:
- Key 先映射到槽位。
- 槽位再分配给节点。
- 节点迁移时只需要迁槽,不需要全量重算所有 Key。
这就是集群可扩展性的核心设计。
5. 示例
5.1 最小可运行示例:缓存旁路
ts
async function getArticle(id: number) {
const key = `article:${id}:detail`;
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
const article = await db.article.findById(id);
if (!article) {
await redis.set(key, "null", "EX", 60);
return null;
}
await redis.set(key, JSON.stringify(article), "EX", 300);
return article;
}
5.2 最小可运行示例:安全释放分布式锁
ts
const requestId = crypto.randomUUID();
const lockKey = "lock:order:create";
const ok = await redis.set(lockKey, requestId, "NX", "PX", 5000);
if (!ok) {
throw new Error("获取锁失败");
}
const unlockScript = `
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
`;
try {
// 执行业务
} finally {
await redis.eval(unlockScript, 1, lockKey, requestId);
}
5.3 最小可运行示例:限流
redis
INCR rate:login:127.0.0.1
EXPIRE rate:login:127.0.0.1 60
这个示例表示 60 秒窗口内统计某来源请求次数,真实工程里通常会封装成 Lua 保证更严谨的原子流程。
6. 工程实践
6.1 场景一:商品详情缓存
步骤:
- 读取先查缓存。
- 未命中查数据库。
- 查不到也缓存空值,防止穿透。
- 设置随机 TTL,防止雪崩。
- 更新商品时,先更新数据库,再删除缓存。
6.2 场景二:登录会话共享
步骤:
- 登录成功后生成 token。
- 把会话信息写入 Redis:
session:{token}。 - 设置过期时间,例如 30 分钟。
- 网关或服务根据 token 去 Redis 校验身份。
- 用户活跃时刷新 TTL。
6.3 场景三:排行榜
步骤:
- 用户得分变化时
ZINCRBY。 - 查询前 N 名用
ZREVRANGE。 - 查单个用户排名用
ZREVRANK。
6.4 场景四:高并发扣减辅助控制
思路:
- Redis 用于高并发预扣减和快速判定。
- 核心订单结果仍要落到数据库。
- Redis 常作为"削峰 + 快速过滤 + 状态协同"层,而不是唯一真相源。
6.5 企业里的高可用建议
| 规模 | 常见方案 |
|---|---|
| 本地开发 | 单机 |
| 中小型生产 | 主从 + 哨兵 |
| 大流量、多分片 | Redis Cluster |
7. 常见误区
| 误区 | 为什么危险 | 正确认知 |
|---|---|---|
| Redis 缓存了,数据库就轻松了 | 忽略失效瞬间冲击 | 必须设计击穿、雪崩保护 |
| 分布式锁拿到了就绝对安全 | 忽略锁超时、GC、网络抖动 | 锁是降低并发冲突,不是万能事务 |
| Redis 能存,就能当主数据库 | 忽略持久化与一致性边界 | 核心账务、复杂关系数据不要轻率替代 |
| 哨兵就是分片 | 概念混淆 | 哨兵做高可用切换,不做数据分片 |
| 集群就天然强一致 | 误判分布式特性 | Redis 追求高可用和性能,不是强一致数据库 |
8. 面试题
- 说一下你们项目里的 Redis 缓存是怎么设计的。
- 缓存穿透、击穿、雪崩分别是什么,怎么处理?
- 为什么更新数据常用"先更新数据库,再删缓存"?
- Redis 分布式锁怎么实现?为什么解锁不能直接
DEL? - 哨兵和集群有什么区别?
- Redis 在秒杀系统里通常承担什么角色?
- Redis 能不能做消息队列?边界在哪里?
9. 自测题
- 设计一个商品详情缓存方案,并考虑穿透、击穿、雪崩。
- 设计一个短信验证码方案,并防止重复发送。
- 设计一个 1 分钟 10 次的登录限流方案。
- 设计一个排行榜方案,并给出核心命令。
- 说出单机、哨兵、集群分别适合什么场景。
10. 学完标志
学完这一阶段后,你应该能做到:
- 独立设计常见 Redis 业务方案。
- 说清缓存一致性与高并发问题处理方式。
- 正确实现基础分布式锁。
- 根据规模选择单机、哨兵或集群。
- 把 Redis 放到真实系统架构里思考,而不是把它当命令集合。
第六阶段:常见问题与排错
1. 学什么
这一阶段学习"线上 Redis 出问题时怎么办",重点包括:
- 大 Key、热 Key。
- 慢查询、阻塞命令。
- 内存飙升、OOM。
- 连接数过多、超时、网络抖动。
- 持久化失败、复制延迟。
- 缓存问题导致数据库被打爆时的排查路径。
2. 为什么重要
Redis 真正拉开工程水平差距的地方,不是在你会不会写 SET,而是在于:
出问题时你能不能迅速定位是 Key 问题、命令问题、网络问题、内存问题,还是架构问题。
这一阶段解决的是生产事故能力。
3. 核心概念
3.1 常见故障类型
| 问题 | 典型现象 | 常见根因 |
|---|---|---|
| 大 Key | 延迟抖动、删除卡顿、网络包大 | 一个 Key 里塞了过多元素或大对象 |
| 热 Key | 单 Key QPS 极高 | 热点流量集中 |
| 慢查询 | RT 上升 | 大量遍历、阻塞命令、CPU 紧张 |
| OOM | 写入失败 | 内存打满、淘汰策略不合适 |
| 复制延迟 | 从库数据落后 | 主从网络抖动、主库压力大 |
| 持久化异常 | 重启后数据恢复异常 | AOF/RDB 失败、磁盘问题 |
3.2 常用排查命令
| 命令 | 用途 |
|---|---|
INFO memory |
看内存使用情况 |
INFO stats |
看总体统计 |
INFO replication |
看主从复制状态 |
SLOWLOG GET 10 |
看慢命令 |
LATENCY DOCTOR |
看延迟诊断 |
MEMORY USAGE key |
看某个 Key 占用内存 |
SCAN |
安全分批扫描 Key |
OBJECT ENCODING key |
看内部编码 |
CLIENT LIST |
看客户端连接 |
MONITOR |
实时观察命令,慎用于生产 |
3.3 排错方法论
建议你固定按这 6 步走:
- 先确认现象:慢、错、丢、满、连不上。
- 再确认范围:单实例、单业务、单 Key,还是全局。
- 看核心指标:CPU、内存、QPS、连接数、复制延迟。
- 查关键命令:慢日志、热点命令、大 Key。
- 先止血,再追根因。
- 复盘并修规则。
4. 原理解释
4.1 为什么大 Key 危险
大 Key 的问题不只是"占空间大",而是会带来链式问题:
- 读取时网络包大。
- 删除或遍历时阻塞主线程。
- 复制和持久化成本更高。
- 一旦成为热 Key,问题会被放大。
4.2 为什么热 Key 危险
Redis 很快,但单 Key 热点无限集中也会出问题:
- 单个 Key 成为瓶颈。
- 某个实例负载异常倾斜。
- 热点失效时会造成击穿。
常见缓解方式:
- 本地缓存。
- 二级缓存。
- 热 Key 永不过期 + 异步刷新。
- 热点拆分。
4.3 为什么 KEYS * 危险而 SCAN 更安全
KEYS * 会一次性遍历所有 Key,可能长时间阻塞 Redis。
SCAN 则采用游标式渐进遍历:
- 一次返回一部分。
- 可以分批处理。
- 对线上更友好。
4.4 为什么慢日志重要
Redis 的问题很多时候不是"Redis 不行",而是某几个命令不合理。
慢日志能帮助你回答:
- 哪条命令慢。
- 参数大概是什么。
- 最近是否重复出现。
5. 示例
5.1 最小可运行示例:排查大 Key
bash
redis-cli --bigkeys
或者针对某个 Key:
redis
MEMORY USAGE user:1001:profile
OBJECT ENCODING user:1001:profile
5.2 最小可运行示例:排查慢命令
redis
SLOWLOG GET 10
LATENCY DOCTOR
INFO commandstats
5.3 最小可运行示例:排查复制
redis
INFO replication
5.4 一个常见故障定位示例
现象:商品详情接口 RT 飙升。
排查路径:
- 看应用日志,确认是否 Redis RT 高。
- 查
SLOWLOG GET。 - 查是否有热点 Key 失效。
- 查数据库是否因缓存失效被打爆。
- 看
INFO memory和INFO stats。
6. 工程实践
6.1 真实工程场景:缓存击穿导致数据库暴涨
处理步骤:
- 先对热点 Key 加互斥重建。
- 临时延长热点 TTL。
- 对数据库限流。
- 增加本地缓存或热点保护。
- 复盘为什么热点 Key 会同时失效。
6.2 真实工程场景:大 Hash 导致延迟波动
处理思路:
- 定位大 Key。
- 判断是否可拆分。
- 避免一次性
HGETALL拉全量。 - 对删除操作使用更温和的方式,避免高峰期粗暴处理。
6.3 真实工程场景:从库延迟严重
排查思路:
- 看主从网络。
- 看主库是否有大写入或
fork压力。 - 看是否存在大 Key 同步。
- 看从库机器资源是否不足。
7. 常见误区
| 误区 | 为什么错 | 正确认知 |
|---|---|---|
| Redis 慢了就一定是 Redis 本身问题 | 忽略业务命令设计 | 很多慢是大 Key、热 Key、错误命令导致 |
线上直接 KEYS * 最快 |
可能把实例打停顿 | 用 SCAN 渐进扫描 |
MONITOR 可以常开 |
命令很多时开销很大 | 只在短时间诊断时慎用 |
| 大对象问题只是内存多一点 | 忽略删除、复制、网络、阻塞成本 | 大 Key 是综合性风险 |
| 从库延迟只和网络有关 | 根因更复杂 | 还可能是主库压力、fork、大同步 |
8. 面试题
- 什么是大 Key?有什么危害?怎么排查?
- 什么是热 Key?怎么处理?
- 为什么不建议在线上用
KEYS *? - Redis 慢时你一般怎么排查?
- 如果 Redis 内存满了会发生什么?
- 从库延迟严重你会怎么分析?
- 为什么缓存击穿会把数据库打爆?
9. 自测题
- 请设计一个 Redis 故障排查 checklist。
- 大 Key 和热 Key 的危害分别是什么?
SLOWLOG GET、LATENCY DOCTOR、INFO memory分别解决什么问题?- 如果线上请求变慢,你会先看哪 3 个维度?
- 为什么删除大 Key 也可能成为问题?
10. 学完标志
学完这一阶段后,你应该能做到:
- 遇到 Redis 线上问题时有清晰排查路径。
- 会用最常见的诊断命令。
- 理解大 Key、热 Key、慢日志、复制延迟这些高频问题。
- 能把"现象"快速映射到"机制"。
- 初步具备生产级 Redis 排障思维。
第七阶段:面试与评估
1. 学什么
这一阶段不是新增知识点,而是训练你把前面内容变成:
- 能解释。
- 能比较。
- 能设计。
- 能排错。
- 能在面试里稳定输出。
2. 为什么重要
很多人会 Redis,但一到面试就容易暴露三个问题:
- 只会背名词,不会讲因果。
- 只会讲命令,不会讲场景。
- 只会讲方案,不会讲权衡。
面试官想看的不是你会不会敲命令,而是你是否具备:
- 基础认知是否扎实。
- 原理理解是否成体系。
- 工程判断是否成熟。
3. 核心概念
3.1 Redis 面试的 5 类题型
| 题型 | 典型问题 | 考察点 |
|---|---|---|
| 定义题 | Redis 是什么、为什么快 | 基础认知 |
| 对比题 | Redis vs MySQL / Memcached | 边界感 |
| 原理题 | 过期、淘汰、持久化、复制 | 机制理解 |
| 场景题 | 缓存设计、分布式锁、秒杀 | 工程能力 |
| 排错题 | 慢、满、丢、延迟 | 实战思维 |
3.2 回答框架
建议你固定用这个框架回答:
- 先下定义
先说它是什么。 - 再讲原理
它为什么这样工作。 - 再讲场景
它解决什么问题。 - 最后讲权衡
它的边界和代价是什么。
这比单纯堆术语稳定得多。
3.3 中级面试官最爱追问的点
- 为什么 Redis 快。
- 为什么缓存一致性难做到绝对完美。
- 分布式锁为什么不能直接删 Key。
- 事务为什么不像 MySQL 那样回滚。
- RDB 和 AOF 如何取舍。
- 哨兵和集群到底差在哪。
- 你项目里 Redis 出过什么问题,怎么排查。
4. 原理解释
4.1 面试官为什么总问"为什么"
因为"为什么"能迅速区分:
- 背答案的人。
- 真理解机制的人。
例如"Redis 为什么快",如果你只答"内存 + 单线程",通常只能到初级水平。
更好的回答要覆盖:
- 内存。
- 事件循环。
- I/O 多路复用。
- 数据结构贴业务。
- 单线程无锁化带来的简化收益。
4.2 场景题为什么总是开放题
因为真实工程没有标准答案。
面试官看的是:
- 你是否先识别问题本质。
- 你是否知道几个可选方案。
- 你是否能说明 trade-off。
例如缓存一致性,没有完美方案,关键是:
- 你是否知道为什么会不一致。
- 你是否知道常见工程折中。
4.3 如何把项目经验讲得有层次
建议顺序:
- 业务背景是什么。
- 为什么要用 Redis。
- 用了哪些类型和机制。
- 遇到过什么问题。
- 最后结果和优化效果。
5. 示例
5.1 一个合格的面试回答示例
问题:Redis 为什么快?
回答示例:
Redis 快主要有四个原因。第一,它的数据主要在内存里,避免了磁盘随机 I/O。第二,它的命令执行路径比较短,很多操作直接基于高效数据结构完成。第三,Redis 通过事件循环和 I/O 多路复用高效处理大量连接。第四,它核心命令执行长期采用单线程模型,减少了锁竞争和线程切换成本。当然,单线程也有代价,比如大 Key 和阻塞命令会影响整体延迟。
5.2 一个中级面试回答示例
问题:缓存击穿怎么处理?
回答示例:
缓存击穿是指某个热点 Key 失效时,大量并发请求同时打到数据库。常见处理方案有三类:第一,对热点 Key 做互斥重建,只允许一个线程回源;第二,对极热点数据采用逻辑过期或后台异步刷新,避免真正失效;第三,配合本地缓存、限流和降级保护后端。选择哪种方案要看热点稳定性、数据实时性要求和实现复杂度。
5.3 一个"项目表达"模板
text
我们在商品详情场景使用 Redis 做缓存旁路。读取先查 Redis,未命中再查 MySQL 并回填。为防止穿透,我们对空结果做短 TTL 缓存;为防止雪崩,我们对 TTL 做随机打散;为防止热点击穿,我们对热点商品加互斥重建。更新时采用先更新数据库再删除缓存的策略。线上曾遇到过热点 Key 失效导致数据库 QPS 暴涨,后续通过热点保护和本地缓存做了优化。
6. 工程实践
6.1 面试前怎么复习最有效
- 先把 20 个高频问题写出自己的答案。
- 每个问题都补"为什么"和"代价"。
- 每个工程题都补一段真实场景说明。
- 用 3 分钟、1 分钟、30 秒三种长度各讲一遍。
6.2 模拟面试顺序
- 先答定义题。
- 再答原理题。
- 再答场景题。
- 最后答排错题。
6.3 企业评估官最看重什么
- 你是否会把 Redis 放在系统里讲,而不是孤立讲。
- 你是否知道边界和风险。
- 你是否有过排错思路。
- 你是否会做取舍,而不是只给"标准答案"。
7. 常见误区
| 误区 | 为什么不好 | 正确做法 |
|---|---|---|
| 面试只背八股 | 一追问就露馅 | 用"定义-原理-场景-权衡"结构输出 |
| 一上来就讲冷门特性 | 偏离重点 | 先把高频核心讲扎实 |
| 项目经验只说"我们用了 Redis" | 信息量太低 | 讲业务目标、方案、问题、结果 |
| 把所有问题都回答成"用 Redis 集群" | 缺少边界感 | 先识别问题,再谈方案 |
8. 面试题
- Redis 为什么快?
- Redis 和 MySQL 的分工是什么?
- 五大数据类型怎么选?
- 过期删除和内存淘汰的区别是什么?
- 缓存穿透、击穿、雪崩分别怎么处理?
- 为什么更新数据库后通常删除缓存而不是直接更新缓存?
- RDB 和 AOF 如何选?
- Redis 分布式锁要注意什么?
- 哨兵和集群的区别是什么?
- 如果 Redis 线上变慢,你会怎么排查?
9. 自测题
- 请你用 1 分钟解释 Redis 是什么。
- 请你用 3 分钟解释 Redis 为什么快。
- 请你自己模拟回答"缓存一致性怎么做"。
- 请你讲一个 Redis 项目案例,包含问题、方案、风险、结果。
- 请你回答"你们为什么不用 MySQL 直接扛这个场景?"。
10. 学完标志
学完这一阶段后,你应该能做到:
- 比较稳定地回答 Redis 常见面试题。
- 不只会讲定义,还能讲机制、场景、权衡。
- 用项目表达方式讲清 Redis 价值。
- 初步具备基础到中级面试应答能力。
- 知道自己哪些部分还薄弱,需要回补。
第八阶段:学习总结与知识闭环
1. 学什么
这一阶段要做的是把前面所有内容连成一张网,而不是散成很多点。
你要完成:
- Redis 知识主干复盘。
- 学习顺序复盘。
- 工程方法论沉淀。
- 下一步深入方向规划。
2. 为什么重要
很多人学完一堆知识点却仍不会用,本质原因是没有形成闭环。
真正的闭环应该是:
能理解 -> 能解释 -> 能上手 -> 能排错 -> 能设计 -> 能面试输出
如果缺一环,知识就会很快散掉。
3. 核心概念
3.1 Redis 知识主干
Redis 定位
数据类型与命令模型
过期 / 淘汰 / 事务 / Pipeline
事件循环 / 协议 / 内部结构 / 持久化
缓存 / 锁 / 限流 / 排行榜 / 会话
高可用 / 集群 / 复制
排错 / 面试 / 项目复盘
3.2 学习本质
Redis 的学习本质不是背命令,而是掌握 4 种能力:
- 建模能力
业务需求如何映射到数据结构。 - 机制理解能力
过期、淘汰、持久化、复制为什么这样设计。 - 工程判断能力
什么时候适合 Redis,什么时候不适合。 - 排错表达能力
出问题时会查,会讲,会取舍。
3.3 必须吃透 vs 先知道
| 层级 | 必须吃透 | 先知道,后深入 |
|---|---|---|
| 基础 | 定位、五大类型、TTL、缓存场景 | 冷门数据类型 |
| 机制 | 过期、淘汰、事务、Pipeline、持久化 | 更深源码细节 |
| 工程 | 缓存一致性、击穿雪崩、锁、限流、高可用 | 极复杂分布式一致性问题 |
| 深入 | 请求生命周期、复制、集群槽位 | 内核级源码优化 |
4. 原理解释
4.1 为什么正确学习顺序必须是"先场景后原理"
因为 Redis 不是纯理论技术,它是极强工程属性的中间件。
如果顺序反了:
- 你会陷入术语海洋。
- 会把注意力放到源码细枝末节。
- 反而不知道真实项目怎么用。
4.2 为什么学习闭环一定要包含排错
因为很多技术只学"正常路径",但工程上真正值钱的是:
- 非正常路径怎么处理。
- 怎么快速止血。
- 怎么复盘避免重演。
4.3 为什么面试表现本质上是知识结构的映射
当你的知识是连贯的,你回答自然会有层次:
- 定位。
- 原理。
- 场景。
- 风险。
- 权衡。
这也是为什么"会做题"不等于"会面试",而"真正理解"通常能兼顾两者。
5. 示例
5.1 一个完整知识闭环示例
问题:设计商品详情缓存
你应该能这样串起来:
- 用
String缓存商品 JSON,Key 如product:{id}:detail。 - 使用 Cache Aside。
- 设置随机 TTL 防雪崩。
- 缓存空值防穿透。
- 热点商品互斥重建防击穿。
- 更新时先更新数据库再删缓存。
- 若出现 Redis RT 波动,优先检查热 Key、大 Key、慢日志。
- 若业务扩张,再考虑主从、哨兵或集群。
5.2 一个复盘模板
text
场景是什么?
为什么选择 Redis?
用了哪种数据结构?
用了哪些机制?
有哪些风险?
如何排查?
如何扩展?
6. 工程实践
6.1 建议你的学习循环
每学一个主题,都按这个顺序做:
- 用一句话解释它是什么。
- 用一个场景解释它解决什么问题。
- 用一个最小命令或代码示例验证。
- 用"为什么这样设计"解释原理。
- 写出 2 个误区。
- 回答 2 个面试题。
6.2 一周强化方法
- 第 1 天:复盘五大类型和命令。
- 第 2 天:复盘过期、淘汰、事务、Pipeline。
- 第 3 天:复盘持久化、复制、高可用。
- 第 4 天:做缓存与锁方案题。
- 第 5 天:做排错题。
- 第 6 天:做面试模拟。
- 第 7 天:总结错误点并补课。
6.3 下一步深入建议
- 更深入的 Redis Cluster。
- Stream、Bitmap、HyperLogLog、GEO。
- Lua 和 Redis Functions。
- 源码阅读:事件循环、对象系统、持久化、复制。
- 客户端连接池与应用侧容灾。
7. 常见误区
| 误区 | 表现 | 应对方式 |
|---|---|---|
| 学完就结束 | 很快遗忘 | 必须做复述和实操闭环 |
| 只刷面试题 | 实战能力弱 | 题目要和项目场景绑定 |
| 只看项目不看原理 | 一追问就断层 | 项目和原理必须双线并进 |
| 只学单机 Redis | 上线后认知不足 | 至少要掌握哨兵和集群边界 |
8. 面试题
- 如果让你从零系统学习 Redis,你会怎么安排顺序?
- Redis 这门技术你觉得最核心的设计哲学是什么?
- 你觉得 Redis 学习里最容易学偏的地方是什么?
- 如果继续深入 Redis,你下一步会学什么,为什么?
9. 自测题
- 请你画出 Redis 的知识树。
- 请你写出你目前最薄弱的 3 个点。
- 请你选一个业务场景,从建模、机制、排错、扩展四个角度讲一遍。
- 请你用自己的话总结 Redis 的设计哲学。
10. 学完标志
学完这一阶段后,你应该能做到:
- 把 Redis 主干知识串成体系。
- 知道自己已经掌握了什么、还缺什么。
- 能用工程视角而不是命令视角看 Redis。
- 能继续独立深入 Redis 的高级主题。
学习评估体系
1. 入门达标标准
满足下面条件,说明你已经入门:
- 能准确解释 Redis 是什么、解决什么问题。
- 能区分 Redis 和 MySQL 的职责边界。
- 能完成
SET/GET/EXPIRE/TTL/DEL基础操作。 - 能说出至少 3 个 Redis 适合的场景。
2. 初级达标标准
满足下面条件,说明你达到初级工程师可用水平:
- 能熟练使用五大核心数据类型。
- 能设计基础缓存方案。
- 能解释过期机制和淘汰策略。
- 能解释 RDB 和 AOF 的基本区别。
- 能回答常见基础面试题。
3. 中级达标标准
满足下面条件,说明你达到中级理解深度:
- 能设计缓存一致性、击穿、雪崩保护方案。
- 能实现基础分布式锁并说明风险。
- 能解释事件循环、I/O 多路复用、复制、高可用边界。
- 能根据单机、哨兵、集群做方案选型。
- 能给出 Redis 故障排查路径并说明依据。
4. 一套自测题
基础题
- Redis 为什么快?
- Redis 和 MySQL 的区别是什么?
- 五大数据类型分别适合什么场景?
机制题
- 过期删除和内存淘汰有什么区别?
- Redis 事务为什么不像 MySQL 那样回滚?
- RDB 和 AOF 如何取舍?
场景题
- 设计一个商品详情缓存。
- 设计一个短信验证码方案。
- 设计一个排行榜方案。
排错题
- Redis 慢了怎么查?
- 什么是大 Key、热 Key?
- 从库延迟严重怎么办?
5. 一套面试题
- Redis 是单线程吗?
- 为什么 Redis 不适合做复杂查询?
- 为什么 Hash 适合存对象?
- 缓存穿透、击穿、雪崩分别如何处理?
- 为什么更新数据库后通常删除缓存?
- Redis 分布式锁怎么实现?风险点有哪些?
- 哨兵和集群的区别是什么?
- Redis Cluster 为什么设计槽位?
- 线上 Redis 延迟抖动你怎么排查?
- 你项目里 Redis 的典型使用方式是什么?
6. 一套实战任务
任务 1:本地 Redis 环境
- 启动本地 Redis。
- 完成五大类型基础命令实验。
- 验证 TTL、事务、Pipeline。
任务 2:缓存实验
- 写一个"先查缓存,未命中查数据库模拟层"的示例。
- 加入空值缓存。
- 给 TTL 加随机值。
任务 3:锁与限流实验
- 用
SET NX PX实现基础锁。 - 用 Lua 安全释放锁。
- 用
INCR + EXPIRE实现一分钟限流。
7. 一套项目任务
项目题:做一个"社区内容服务"的 Redis 设计
要求至少覆盖:
- 用户资料:
Hash - 文章详情缓存:
String - 点赞关系:
Set - 热门排行榜:
ZSet - 登录会话:带 TTL 的
String/Hash - 接口限流:
INCR + EXPIRE - 高可用方案:说明为何选单机、哨兵或集群
- 排错预案:说明如何监控和排查热点、慢日志、大 Key
项目验收标准
- 你能讲清 Key 设计。
- 你能讲清类型选型理由。
- 你能讲清一致性和高并发保护。
- 你能讲清排错与扩展。
8. 对你回答的评分标准
| 分数段 | 水平 | 说明 |
|---|---|---|
| 90-100 | 中级偏上 | 定义准确,原理清楚,场景完整,能讲 trade-off 和排错 |
| 75-89 | 中级入门 | 主要知识点完整,工程表达较好,个别深度不足 |
| 60-74 | 初级可用 | 会基础概念和常见场景,但原理和排错偏弱 |
| 40-59 | 入门未稳 | 只会零散命令,体系不完整 |
| 0-39 | 需要重学主干 | 定位、类型、机制都不清楚 |
细项打分维度
| 维度 | 占比 | 评估点 |
|---|---|---|
| 基础定义 | 15% | 能否说清 Redis 定位与边界 |
| 类型选型 | 20% | 能否做对数据结构建模 |
| 机制理解 | 20% | 过期、淘汰、持久化、复制是否清楚 |
| 工程实践 | 20% | 缓存、锁、限流、高可用方案是否合理 |
| 排错能力 | 15% | 是否有诊断路径 |
| 面试表达 | 10% | 是否条理清晰,有因果和权衡 |
9. 如何根据错误结果反向补课
如果你总在"定义题"失分
回补内容:
- Redis 定位。
- Redis 与 MySQL / Memcached 对比。
- Redis 为什么快。
如果你总在"选型题"失分
回补内容:
- 五大类型对比表。
- 常见业务场景映射。
- Key 设计规范。
如果你总在"机制题"失分
回补内容:
- 过期删除。
- 淘汰策略。
- 事务与 Pipeline。
- RDB / AOF / 复制主线。
如果你总在"工程题"失分
回补内容:
- Cache Aside。
- 缓存一致性。
- 穿透、击穿、雪崩。
- 分布式锁。
- 哨兵与集群。
如果你总在"排错题"失分
回补内容:
- 大 Key、热 Key。
SLOWLOG、INFO、LATENCY DOCTOR。- 复制延迟与内存排查。
反向补课建议流程
- 先记录你答错的问题类型。
- 对应回到本文件相应阶段。
- 用"定义-原理-场景-排错"重新写一版答案。
- 自己口述录音复盘。
- 再做一次同类型题,直到能稳定输出。
最后总结
如果只用一句话概括 Redis:
Redis 是一个以内存为核心、以数据结构为能力、以高性能读写和状态协同为价值的系统。
如果只记住学习主线:
定位 -> 数据结构 -> 核心机制 -> 底层原理 -> 工程实践 -> 排错 -> 面试表达
如果只记住工程主线:
业务需求 -> 数据建模 -> Key 设计 -> TTL/持久化/高可用策略 -> 压测与排错 -> 复盘优化
到这里,这份 redis.md 已经形成完整闭环。后续如果你愿意,可以继续在这个文件基础上追加:
- Redis 实操实验记录。
- 你自己的面试答案。
- 你项目里的 Redis 方案复盘。