Skip to content

Redis 面试题汇总

恭喜你学完了 Redis 核心知识点!

这一节,我们来汇总面试中常考的 Redis 面试题,并给出回答思路。

基础篇

Q1: Redis 为什么这么快?

标准答案:

  1. 纯内存操作:内存访问速度是纳秒级,比磁盘快 10 万倍
  2. 单线程模型:避免了锁竞争和上下文切换
  3. I/O 多路复用:单线程同时处理成千上万的连接
  4. 高效数据结构:SDS、跳表、压缩列表等为 Redis 量身定制
  5. C 语言实现:编译型语言,执行效率高

追问:单线程如何处理并发?

通过 I/O 多路复用,监听多个 socket 的事件,在一个线程中处理所有客户端请求。

Q2: Redis 有哪几种数据类型?

标准答案:

类型底层实现特点
StringSDS二进制安全
ListQuickList双向链表
HashHT / ZipList对象存储
SetHT / IntSet无序去重
ZSetSkipList + HT有序去重
BitmapString位图
HyperLogLogString概率统计
GeoZSet地理位置
StreamRadixTree日流

Q3: Redis 和 Memcached 的区别?

标准答案:

特性RedisMemcached
数据类型丰富只支持字符串
持久化支持 RDB/AOF不支持
集群原生 Cluster需要客户端实现
内存管理多种淘汰策略LRU
线程模型单线程 + 多线程 I/O多线程

结论:如果只需要简单的 K-V 缓存,Memcached 足够;如果需要更多功能,Redis 是更好的选择。

数据结构篇

Q4: ZSet 的底层实现是什么?

标准答案:

ZSet 底层是跳表(Skip List)+ 哈希表的组合。

  • 跳表:支持 O(log n) 的范围查找和排序
  • 哈希表:支持 O(1) 的 member 查找

两者结合,实现了「按分数排序」和「按 member 查分数」两种操作。

追问:为什么不用红黑树?

  1. 跳表实现更简单,代码量少
  2. 跳表范围查询更高效(链表天然支持)
  3. 跳表更容易做并发(不需要旋转平衡)

Q5: 什么是 QuickList?

标准答案:

QuickList 是 Redis 3.2 推出的 List 新实现,结合了「压缩列表」和「双向链表」的优点:

QuickList = [ZipList] <=> [ZipList] <=> [ZipList]
  • 每个 ZipList 默认 8KB
  • 元素多时,增加新的 ZipList
  • 空间利用率高,插入也快

持久化篇

Q6: RDB 和 AOF 的区别?

标准答案:

特性RDBAOF
原理定时快照记录命令
文件大小
恢复速度
数据安全性高(可配置)
性能影响fork 子进程持续写入

推荐配置:同时开启 RDB 和 AOF,使用混合持久化(Redis 4.0+)。

Q7: 持久化会影响性能吗?

标准答案:

  • RDB:fork 子进程时可能阻塞,但 COW 机制让影响可控
  • AOFeverysec 模式下,异步写入对主线程影响很小

生产环境中,持久化的性能影响是可以接受的,数据安全更重要。

高可用篇

Q8: 主从复制的原理?

标准答案:

  1. 完整同步:从节点首次连接或断线重连时,执行 BGSAVE 生成 RDB,发送给从节点加载
  2. 增量同步:日常通过命令传播,主节点每条写命令同时发送给从节点

关键机制:

  • 复制偏移量:记录主从同步位置
  • 复制积压缓冲区:默认 1MB,保存最近的写命令

Q9: Sentinel 和 Cluster 的区别?

标准答案:

特性SentinelCluster
数据分片
自动故障转移
最小节点数3 Sentinel + 2 Redis6 Redis
适用场景数据量小海量数据

选型建议:数据量小需要高可用选 Sentinel,数据量大需要分片选 Cluster。

Q10: 什么是脑裂?如何预防?

标准答案:

脑裂是网络分区导致集群中出现多个主节点的現象。

预防措施:

  1. 合理配置 Sentinel 数量:至少 3 个,分布在不同机房
  2. 设置足够的超时时间down-after-milliseconds 不要太短
  3. 配置写入确认min-replicas-to-write 要求写入同步到从节点

缓存篇

Q11: 缓存穿透、击穿、雪崩的区别?

标准答案:

概念描述区别
穿透查询不存在的数据数据库也没有
击穿热点 key 过期大量请求涌入
雪崩大量 key 同时过期key 同时失效

解决方案:

  • 穿透:布隆过滤器 + 缓存空值
  • 击穿:互斥锁 / 逻辑过期 / 预热
  • 雪崩:过期时间随机化 + 多级缓存 + 熔断降级

Q12: 缓存一致性怎么保证?

标准答案:

推荐 Cache Aside 模式

读:缓存命中 → 返回;未命中 → 查库 → 回填缓存
写:先更新数据库 → 再删除缓存

注意:删除缓存而不是更新缓存,因为删除比更新更简单,避免并发问题。

Q13: 如何实现分布式锁?

标准答案:

bash
# 加锁
SET key value NX EX seconds

# 解锁(Lua 脚本)
if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

关键点:

  1. value 要用唯一标识(UUID),防止误删
  2. 解锁要用 Lua 脚本保证原子性
  3. 过期时间要设置足够长

生产环境推荐使用 Redisson,它提供了看门狗续命、公平锁等高级功能。

Q14: Redis 6.0 的多线程是什么?

标准答案:

Redis 6.0 引入了多线程 I/O,但命令执行仍然是单线程

客户端请求 → 多线程网络 I/O → 主线程命令执行 → 多线程响应发送

适用场景:

  • 小 Value:提升有限(瓶颈不在 I/O)
  • 大 Value:提升明显(I/O 并行化效果好)

实战篇

Q15: 如何排查 Redis 变慢?

标准答案:

  1. 查看 INFO 命令:检查内存使用、命中率、持久化状态
  2. 查看慢查询日志SLOWLOG GET 找出耗时命令
  3. 检查大 keyredis-cli --bigkeys 扫描
  4. 检查热 keyredis-cli --hotkeys 或客户端埋点

常见原因:

  • 大 key 操作
  • 使用了慢命令(KEYS、FLUSHALL 等)
  • 内存满了,大量淘汰
  • fork 子进程(持久化、复制)

Q16: Redis 内存满了怎么办?

标准答案:

根据 maxmemory-policy 配置的淘汰策略处理:

策略说明
allkeys-lru淘汰最久未使用的(推荐缓存场景)
volatile-lru只淘汰有过期时间的
noeviction不淘汰,返回错误

建议:

  1. 设置 maxmemory,根据机器内存预留一部分
  2. 选择合适的淘汰策略
  3. 监控 evicted_keys,如果持续增长说明内存不够

Q17: Redis 如何做性能优化?

标准答案:

  1. 客户端优化

    • 使用连接池代替直连
    • 使用 Pipeline 批量操作
    • 避免大 Value
  2. 服务端优化

    • 选择合适的淘汰策略
    • 合理设置过期时间
    • 开启懒删除(UNLINK)
  3. 架构优化

    • 读写分离
    • 分片存储
    • 本地缓存兜底

总结

Redis 核心知识点

┌─────────────────────────────────────────────┐
│                 Redis                          │
├─────────────────────────────────────────────┤
│  数据结构:String, List, Hash, Set, ZSet...   │
│  持久化:RDB, AOF, 混合持久化               │
│  高可用:主从, Sentinel, Cluster            │
│  缓存策略:穿透, 击穿, 雪崩, 一致性         │
│  分布式:锁, 队列, 计数器, 排行榜           │
└─────────────────────────────────────────────┘

面试技巧

  1. 原理要懂:不仅要知道怎么用,还要知道为什么这样设计
  2. 实践要会:能写出基本的 Java 代码
  3. 场景要熟:知道这些技术在实际项目中怎么用
  4. 追问要答:面试官追问时,能深入展开

祝你面试成功!


核心记忆点:Redis 面试主要考察数据结构、持久化、高可用、缓存策略、分布式应用五大方面。原理 + 实践 + 场景,是应对 Redis 面试的关键。

基于 VitePress 构建