Redis
校招考察频度:★ 高频(核心必背·高频生死线) 复习主线:Redis 是大厂高并发架构面试的绝对主角。校招面试核心聚焦点:底层数据结构精细推导(SDS 优势、EMBSTR 为什么是 44 字节、跳表 SkipList 为什么不用红黑树)、缓存三连(穿透/击穿/雪崩)终极防御方案、缓存与数据库双写一致性严谨推导、分布式锁(SETNX + Lua / Redisson 看门狗续期)、单线程命令执行与 6.0 多线程 I/O、持久化(RDB COW 写时复制 vs AOF 瘦身重写)。
Redis 是高性能内存键值数据库,官方定位是“数据结构服务器”。它构成了现代高并发互联网服务中最常用的缓存与协调层。
分类考频地图
| 专题 | 核心页面 | 校招考频星级 | 重点考查要点 |
|---|---|---|---|
| 底层数据结构 | Redis 数据结构与底层 | ★ 高频(生死线) | 5+N 大对象与底层编码(RAW/EMBSTR/Dict/ZipList/QuickList/SkipList)、44 字节内存紧凑推导、跳表随机层数与范围查询 |
| 缓存经典事故 | 缓存穿透击穿雪崩 | ★ 高频(核心必考) | 穿透(布隆过滤器与空值缓存)、击穿(互斥锁与逻辑过期)、雪崩(随机过期时间与多级缓存) |
| 分布式锁 | 分布式锁与 RedLock | ★ 高频(高频实战) | SET key value NX PX、唯一 UUID 标识、Lua 脚本原子释放、Redisson 看门狗(Watch Dog)自动续期、Redlock 争议 |
| 双写一致性 | 缓存一致性 | ★ 高频(大厂深挖) | 先写 DB 再删缓存(Cache Aside)、读写并发极端时序推导、延时双删、Canal 监听 binlog 异步重试补偿 |
| 持久化机制 | 持久化 | ★ 高频(核心必背) | RDB bgsave 与 Linux COW(写时复制)、AOF 刷盘策略(always/everysec/no)、AOF 重写后台子进程与混合持久化 |
| 线程模型 | 线程模型 | ★ 高频(核心必背) | 单线程为什么快、基于 epoll 的文件事件处理器、Redis 6.0 多线程 I/O(仅多线程解析协议与写网络 buffer,命令执行仍单线程) |
| 过期与淘汰 | 过期与内存淘汰 | ☆ 中频(大厂分水岭) | 惰性删除 + 定期抽样删除、8 种内存淘汰策略(LRU vs LFU vs 随机 vs TTL)、近似 LRU 的时钟衰减算法 |
| 生产大坑排查 | 大 key/热 key 排查 | ☆ 中频(生产避坑) | 大 Key 阻塞主线程与网络拥塞、热 Key 单分片打爆、本地缓存(Caffeine)二级兜底、拆分与读写分离 |
| 主从与哨兵 | 主从与哨兵 | ☆ 中频(高可用架构) | 主从全量(psync/repl_backlog)与增量同步、哨兵 Leader 选举与故障转移、脑裂与 min-replicas 防护 |
| Cluster 集群 | Cluster 集群 | ☆ 中频(分布式分片) | Cluster 16384 虚拟槽分区、MOVED 与 ASK 重定向、集群伸缩与槽迁移数据安全 |
| 事务与 Lua 脚本 | 事务与 Lua | ☆ 中频(原子性操作) | MULTI/EXEC 弱事务、Lua 脚本原子性保证与超时处理机制 |
| 高级扩展应用 | 高级应用 | 低频(特性拓展) | HyperLogLog 基数统计、Bitmap 位图与布隆过滤器原理、Geohash 地理空间索引 |
定位
- 数据全放内存,读写都是内存操作,单机轻松支撑十万级 QPS
- 提供丰富的数据结构(string/hash/list/set/zset 加 Stream 等),不只是 get/set
- 有持久化(RDB/AOF),但定位仍是缓存与辅助存储,不是主存储
- 单机内存有限,容量扩展靠 Cluster 分片
为什么快
| 因素 | 说明 |
|---|---|
| 纯内存操作 | 数据在内存,无磁盘 IO |
| 单线程执行命令 | 无锁竞争、无上下文切换、无死锁问题 |
| IO 多路复用 | 单线程用 epoll 同时管理大量连接 |
| 高效数据结构 | SDS、跳表、压缩表,按场景定制 |
| 批量与管道 | 减少网络往返(RTT) |
面试加分细节:Redis 单线程是指命令执行单线程,网络 IO 在 6.0 后可以多线程(见线程模型篇)。单线程快的前提是命令都是微秒级内存操作,所以慢命令(KEYS、大 key 操作)会阻塞整个实例。
典型应用场景
| 场景 | 用的能力 |
|---|---|
| 缓存 | 热点数据,配合缓存一致性方案 |
| 会话存储 | string/hash 存 session |
| 排行榜 | zset 按分数排序 |
| 分布式锁 | SETNX + Lua,见分布式锁篇 |
| 限流 | INCR + 过期,见高级应用篇 |
| 消息队列 | Stream、List 的轻量方案 |
| 计数与 UV | INCR、HyperLogLog、位图 |
| 附近的人 | GEO |
与 Memcached 的对比
| 维度 | Redis | Memcached |
|---|---|---|
| 数据类型 | 丰富结构 | 只有 string |
| 持久化 | RDB/AOF | 无 |
| 主从/集群 | 完整高可用方案 | 不支持(靠客户端分片) |
| 线程模型 | 单线程命令执行 | 多线程 |
| 典型地位 | 事实标准 | 已边缘化 |
面试追问
- Redis 为什么快? 内存操作加单线程免竞争加 IO 多路复用。单线程的前提是命令微秒级,慢命令是事故源头
- 单线程怎么处理并发连接? IO 多路复用,一个线程监听大量 socket,事件就绪才处理
- Redis 是数据库吗? 有持久化但定位是缓存与辅助存储。数据可靠性弱于关系库,重启或宕机会丢数据
- 什么场景不该用 Redis? 数据必须持久且事务复杂、超过内存容量的数据、需要 SQL 查询的场景
- Memcached 为什么被淘汰? 只有 string、无持久化、无高可用方案。Redis 覆盖面完全超过它