Redis 面试题精选
2026/1/14大约 5 分钟
Redis 面试题精选
基础篇
1. Redis 是什么?有什么特点?
Redis 是一个基于内存的高性能键值对数据库。
特点:
- 基于内存,读写速度快(10万+ QPS)
- 支持丰富的数据类型(String、Hash、List、Set、ZSet)
- 支持持久化(RDB、AOF)
- 支持主从复制、哨兵、集群
- 单线程模型,避免线程切换开销
2. Redis 为什么这么快?
- 纯内存操作:数据存储在内存中,读写无磁盘 IO
- 单线程模型:避免多线程上下文切换和锁竞争
- IO 多路复用:使用 epoll 等机制处理大量并发连接
- 高效数据结构:如跳表、压缩列表等优化的底层实现
3. Redis 是单线程还是多线程?
- Redis 6.0 之前:单线程处理命令
- Redis 6.0 之后:网络 IO 多线程,命令执行仍是单线程
核心命令执行始终是单线程,保证原子性。
4. Redis 的数据类型及应用场景?
| 类型 | 应用场景 |
|---|---|
| String | 缓存、计数器、分布式锁、Session |
| Hash | 对象存储(用户信息、商品详情) |
| List | 消息队列、最新列表、时间线 |
| Set | 去重、共同好友、抽奖 |
| ZSet | 排行榜、延迟队列、范围查询 |
持久化篇
5. RDB 和 AOF 的区别?
| 对比项 | RDB | AOF |
|---|---|---|
| 原理 | 定时快照 | 记录写命令 |
| 文件大小 | 小(二进制压缩) | 大(文本命令) |
| 恢复速度 | 快 | 慢 |
| 数据安全 | 可能丢失最后一次快照后的数据 | 最多丢失1秒数据 |
| 性能影响 | fork 子进程时有影响 | 写入时有影响 |
生产建议:同时开启 RDB 和 AOF,用 AOF 恢复数据。
6. RDB 触发机制?
- 手动触发:
SAVE(阻塞)、BGSAVE(后台) - 自动触发:
- 配置
save m n(m 秒内 n 次修改) - 主从复制时
SHUTDOWN命令FLUSHALL命令
- 配置
7. AOF 重写是什么?
AOF 文件会越来越大,重写机制将多条命令合并为最终结果的一条命令。
# 原始命令
SET count 1
INCR count
INCR count
INCR count
# 重写后
SET count 4缓存篇
8. 什么是缓存穿透?如何解决?
定义:查询不存在的数据,请求直接打到数据库。
解决方案:
- 缓存空值:查不到也缓存,设置较短过期时间
- 布隆过滤器:在缓存前加一层过滤,判断数据是否存在
- 参数校验:拦截非法请求
// 缓存空值示例
String value = redis.get(key);
if (value == null) {
value = db.query(key);
if (value == null) {
redis.setex(key, 60, ""); // 缓存空值60秒
} else {
redis.set(key, value);
}
}9. 什么是缓存击穿?如何解决?
定义:热点 Key 过期瞬间,大量请求打到数据库。
解决方案:
- 互斥锁:只让一个线程查库,其他等待
- 热点数据永不过期:逻辑过期,后台异步更新
- 提前续期:快过期时自动延长
// 互斥锁示例
String value = redis.get(key);
if (value == null) {
if (redis.setnx(lockKey, "1", 10)) { // 获取锁
try {
value = db.query(key);
redis.set(key, value);
} finally {
redis.del(lockKey); // 释放锁
}
} else {
Thread.sleep(50);
return get(key); // 重试
}
}10. 什么是缓存雪崩?如何解决?
定义:大量 Key 同时过期,或 Redis 宕机,请求全部打到数据库。
解决方案:
- 过期时间加随机值:避免同时过期
- Redis 高可用:主从 + 哨兵 / 集群
- 限流降级:保护数据库
- 多级缓存:本地缓存 + Redis
// 过期时间加随机值
int expireTime = 3600 + new Random().nextInt(300);
redis.setex(key, expireTime, value);11. 如何保证缓存与数据库一致性?
常用策略:
Cache Aside(旁路缓存)- 推荐
- 读:先读缓存,没有则读库并写缓存
- 写:先更新数据库,再删除缓存
延迟双删
redis.del(key); // 先删缓存 db.update(data); // 更新数据库 Thread.sleep(500); // 延迟 redis.del(key); // 再删缓存消息队列:通过 MQ 异步更新缓存
分布式篇
12. Redis 如何实现分布式锁?
// 加锁
String result = redis.set(lockKey, requestId, "NX", "EX", 30);
if ("OK".equals(result)) {
// 获取锁成功
}
// 解锁(Lua 脚本保证原子性)
String script =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
redis.eval(script, Collections.singletonList(lockKey),
Collections.singletonList(requestId));注意事项:
- 设置合理的过期时间
- 解锁时验证持有者
- 考虑使用 Redisson 框架
13. Redis 主从复制原理?
- 全量复制:从节点首次连接,主节点生成 RDB 发送
- 增量复制:主节点将写命令发送到从节点
- 复制偏移量:记录复制进度,断线重连后增量同步
14. 哨兵模式的作用?
- 监控:检测主从节点是否正常
- 通知:节点故障时通知管理员
- 自动故障转移:主节点故障时自动选举新主节点
- 配置中心:客户端通过哨兵获取主节点地址
15. Redis Cluster 集群原理?
- 数据分片:16384 个槽位,每个节点负责一部分
- 去中心化:节点间通过 Gossip 协议通信
- 高可用:每个主节点有从节点,主挂了从顶上
# 计算 Key 属于哪个槽
CLUSTER KEYSLOT mykey其他高频题
16. Redis 内存淘汰策略?
| 策略 | 说明 |
|---|---|
| noeviction | 不淘汰,内存满时报错(默认) |
| allkeys-lru | 所有 Key 中淘汰最近最少使用的 |
| volatile-lru | 设置了过期时间的 Key 中淘汰 LRU |
| allkeys-random | 随机淘汰 |
| volatile-ttl | 淘汰即将过期的 Key |
| allkeys-lfu | 淘汰最不经常使用的(Redis 4.0+) |
17. Redis 事务支持回滚吗?
不支持。Redis 事务中某条命令执行失败,其他命令仍会执行。
MULTI
SET key1 value1
INCR key1 # 这条会失败(字符串不能自增)
SET key2 value2 # 仍会执行
EXEC18. Pipeline 是什么?
批量发送命令,减少网络往返次数。
Pipeline pipeline = jedis.pipelined();
for (int i = 0; i < 1000; i++) {
pipeline.set("key" + i, "value" + i);
}
pipeline.sync(); // 一次性发送19. Redis 大 Key 问题如何处理?
识别大 Key:
redis-cli --bigkeys解决方案:
- 拆分:将大 Hash 拆成多个小 Hash
- 压缩:序列化时压缩数据
- 异步删除:
UNLINK代替DEL
20. 热点 Key 如何处理?
- 本地缓存:JVM 内存缓存热点数据
- 读写分离:从节点分担读压力
- Key 分散:
key_1、key_2分散到不同节点 - 限流:控制访问频率