Redis 知识卡片(简历版)
这份卡片按你当前简历的项目强度整理。
目标不是 Redis 运维 / 底层源码级全覆盖,而是:
- 能撑住
黑马点评的缓存治理、秒杀并发控制、异步削峰追问 - 能撑住
苍穹外卖 AI 智能客服 Agent里的多级缓存、一致性、限流、分布式锁追问 - 能过常规后端一面 / 二面的 Redis 主干题
1. Redis 为什么快
- Redis 快的核心不是只因为“在内存里”
- 关键原因:
- 基于内存,避免磁盘随机 IO
- 数据结构高效,命令执行路径短
- IO 多路复用,高效监听大量连接
- 命令执行层保持单线程,减少锁竞争和线程切换
- 记一句:
并发监听很多连接- 不等于
多线程并发执行命令
2. IO 多路复用 / 单线程
- IO 多路复用解决的是网络连接监听问题
- 一个线程能同时感知很多 socket 的读写事件
- Linux 下常见实现是
epoll - Redis 命令执行仍然主要是单线程串行
- Redis 6 引入多线程,主要是为了优化网络 IO,不是把命令执行彻底并行
3. 常见数据结构
string:缓存、计数器、分布式锁hash:对象属性存储list:简单消息队列、顺序队列set:去重、共同好友、标签集合zset:排行榜、按分数排序bitmap:签到、布尔位统计hyperloglog:基数统计stream:可靠消息流、消费组场景
4. 缓存穿透 / 击穿 / 雪崩
缓存穿透:
Redis 没有
数据库也没有
请求还反复打进来
常见方案:
空值缓存
布隆过滤器
缓存击穿:
热点 key 失效
高并发同时回源数据库
常见方案:
互斥锁
逻辑过期
缓存雪崩:
大量 key 同时过期
或 Redis 整体不可用
常见方案:
TTL 加随机值
高可用架构
限流、降级、熔断
多级缓存
5. 逻辑过期
- 适合热点数据
- 核心不是“更一致”,而是“更抗并发”
- 逻辑过期流程:
- 缓存里存数据 + 逻辑过期时间
- 未过期直接返回
- 过期后只让一个线程抢锁异步重建
- 其他线程直接返回旧值
- 本质:
- 用短暂不一致换吞吐和可用性
- 不保证强一致
- 保证最终一致
6. 空值缓存 / 布隆过滤器
- 空值缓存适合拦截重复查询同一个不存在 key
- 缺点:
- 占内存
- 对分散恶意请求效果有限
- 布隆过滤器适合做前置存在性判断
- 优点:
- 拦截能力强
- 缺点:
- 有误判率
- 维护成本更高
7. 多级缓存
- 完整的形式:浏览器 → CDN → Nginx (proxy_cache / Lua) → Redis → Caffeine (JVM) → MySQL (Buffer Pool)
- 常用的形式:Nginx + Lua -> Redis -> Caffine (JVM)
- 你项目里的典型形态:
Caffeine + Redis- 本地缓存负责更快命中
- Redis 负责分布式共享缓存
- 好处:
- 降低远程 Redis 访问频率
- 降低数据库压力
- 记一句:
- 本地缓存快
- 分布式缓存统一
- 一致性最难
8. 多级缓存一致性
- 常见问题:
- 本地缓存和 Redis 脏读窗口
- 多实例本地缓存不一致
- 常见方案:
- 删除缓存而不是直接更新缓存
- Redis Pub/Sub 广播本地缓存重载
- TTL + 主动刷新结合
- FAQ 场景下:
- 后台 FAQ 更新后
- 通过 Redis Pub/Sub 通知各 JVM 重载本地语义缓存
9. 分布式锁
- 最基础思路:
setnx + expire- 常见问题:
- 原子性
- 可重入
- 锁过期
- 锁误删
- Redisson 的价值:
- 封装分布式锁实现
- 提供可重入
- 提供 watchdog 自动续期
- 简化工程使用
10. 秒杀防超卖
- 不能靠业务代码
if(stock > 0) stock-- - 核心要点:
- 库存检查
- 一人一单检查
- 预扣库存
- 这些要做成原子操作
- 你项目里的主线:
- Redis + Lua 做资格校验和预扣
- MySQL 作为最终落库兜底
- 数据库侧还要有:
where stock > 0- 唯一约束
- 事务 / 幂等控制
11. Lua 脚本
- Lua 在 Redis 里执行
- 本质价值是:
- 多个操作原子执行
- 常见放进去的动作:
- 库存检查
- 一人一单检查
- 预扣库存
- 写入异步消息
- 记一句:
- 不是操作 MySQL
- 是在 Redis 里原子完成资格校验和预扣
12. Redis Stream
- 比简单 List 更适合可靠消息场景
- 核心点:
- 消费者组
- ACK
- Pending List
- 如果消费成功才 ACK
- 如果消费失败或宕机
- 未 ACK 消息留在 Pending List
- 重启后可恢复消费
- 适合:
- 秒杀异步下单
- 削峰
- 消息不丢场景
13. 最终一致性链路
- 你项目里的完整链条:
- Redis Lua 做库存检查、一人一单、预扣库存、写 Stream
- 异步消费者消费消息
- MySQL 侧落正式订单
- 数据库侧用事务、唯一约束、条件更新兜底
- 记一句:
Redis 保入口不超卖MySQL 保最终落库一致
14. Redis 和数据库的一致性边界
- 展示型数据可以短暂旧
- 扣减型数据不能靠缓存值做最终判断
- 读优化:
- 逻辑过期
- 多级缓存
- 空值缓存
- 写一致性:
- Lua 原子预扣
- 数据库条件更新
- 事务
- 唯一约束
15. 持久化
- RDB:
- 快照式持久化
- 恢复快
- 可能丢最近一段数据
- AOF:
- 记录写命令
- 数据更完整
- 文件更大,恢复更慢
- 面试里常见口径:
- Redis 高性能主因不在持久化
- 持久化是可恢复性能力,不是性能来源
16. 高可用
- 主从复制:读扩展、数据备份
- 哨兵:故障检测与主从切换
- 集群:分片 + 高可用
- 雪崩场景下不能只答哨兵
- 还要补:
- 限流
- 降级
- 本地缓存
- 热点预热
17. 限流
- 你简历里的限流点:
- Redisson 滑动窗口
- HTTP 场景:AOP 拦截
- WebSocket 场景:双通道限流
- 面试里要会说:
- 为什么不只做单机限流
- 为什么 Redis 适合做分布式限流
- HTTP AOP 限流:
- 自定义限流注解
- AOP 拦截 Controller 或接口方法
- 根据用户、接口、IP、租户拼接限流 key
- 调 Redisson 滑动窗口判断当前窗口请求数
- 超过阈值直接返回限流响应
- 不进入后续业务逻辑
- WebSocket 限流:
- WebSocket 没有传统 HTTP 请求生命周期
- 通常在消息入口做拦截
- 每条消息按用户维度或会话维度计数
- 超过阈值返回错误消息
- 或关闭连接 / 降级提示
- 为什么用 Redisson 滑动窗口:
- 单机计数只能限制当前节点
- 多实例部署下会失效
- Redis 是共享状态
- Redisson 封装分布式计数和过期窗口
- 滑动窗口比固定窗口更平滑
- 不容易在窗口边界被突刺打穿
- key 设计:
- HTTP 可以是
rate:http:{userId}:{uri} - WebSocket 可以是
rate:ws:{userId}:{sessionId}或rate:ws:{userId}:{scene} - 管理端接口可以加角色或租户维度
- 超限返回:
- HTTP 返回统一错误码
- 比如
429 Too Many Requests - WebSocket 返回限流消息
- 比如
操作太频繁,请稍后再试 - 记一句:
HTTP 限流拦接口,WebSocket 限流拦消息,Redis 负责多实例共享计数
18. 结合你项目必须会落的 Redis 口径
黑马点评- 为什么热点查询选逻辑过期
- 为什么拿不到锁直接返回旧值
- 为什么秒杀校验放 Lua
- Redis Stream 怎么保证消息不丢
- 预扣后 MySQL 怎么兜底最终一致
苍穹外卖 AI 智能客服 Agent- FAQ 本地语义缓存怎么做
- Redis Pub/Sub 怎么做多实例缓存重载
- Redis 持久化执行状态怎么服务高风险确认挂起与恢复
- 分布式锁和限流为什么都落在 Redis
19. 当前完成标准
- 如果目标是常规后端一面 / 二面
- 补齐上面 1 到 18,基本算 Redis 主干完成
- 如果目标是项目深挖
- 还要继续补:
- 热 key 治理
- 大 key / big key
- Redis 内存淘汰策略
- 双写一致性方案
- 集群数据迁移与 slot