(四) Redis 面试必问 15 题及详解
Redis 面试必问 15 题及详解
本文汇总了 Redis 面试中最常被问到的 15 个核心问题,涵盖性能原理、高可用架构、持久化机制、分布式锁、缓存设计等多个维度
为什么 Redis 这么快?
主要原因包括:
- 内存级别读写:所有数据都存储在内存中,避免磁盘 IO。
- 单线程模型:避免多线程带来的上下文切换和加锁开销。
- 高效的数据结构:底层实现充分利用哈希表、跳表、压缩列表等。
- I/O 多路复用:基于 epoll 实现的事件驱动网络模型,效率极高。
Redis 是单线程的吗?它为什么还能这么快?
是的,Redis 的网络请求处理和命令执行是单线程的,但它仍然非常快,主要得益于:
内存操作本身速度极快
单线程避免线程切换和竞争
高效的事件机制(epoll)
epoll 是 Linux 内核提供的一种 事件通知机制,用来同时监听多个文件描述符(如 socket 连接),一旦有数据可读/可写,就立即通知程序处理,而不是轮询每一个连接,大大提升了效率。
当有客户端连接 Redis 时,这些 socket 会注册到 epoll 监听列表中;
epoll 会在某个连接可读/可写时通知 Redis;
Redis 就只处理那些“真的有事干”的连接,避免资源浪费
优势:
特性 说明 高性能 支持成千上万个连接,性能不随连接数线性下降 非阻塞 避免因为一个连接等待而阻塞整个服务 事件驱动 只在有事件发生时才处理,大大提高
命令执行本身耗时极短
缓存穿透、击穿、雪崩如何解决?
缓存穿透:查询不存在的 key,数据库被打爆
→ 使用 布隆过滤器、缓存空值
缓存击穿:热点 key 在高并发下过期,瞬间击穿数据库
→ 加 互斥锁、预加载、热点保护
缓存雪崩:大量 key 同时过期
→ 设置 过期时间随机化、使用 多级缓存、降级限流
Redis 的持久化方式有哪些?RDB 和 AOF 有什么区别?
RDB(快照):定时保存数据,适合备份恢复
AOF(日志):记录每次写操作,数据更完整
维度 RDB AOF 性能 高 较低 数据完整性 可能丢失最近 几乎不丢 启动恢复速度 快 慢 文件体积 小 大
如何实现 Redis 分布式锁?如何保证锁的可靠性?
- 使用命令:SET key value NX EX 10
- 保证原子性:加锁+过期同时完成
- 解锁安全:Lua 脚本判断锁是否属于当前客户端
- Redisson 实现:推荐使用 Redisson 提供的分布式锁,封装完善
Redis 过期键的删除策略有哪些?
Redis 使用 三种方式结合 删除过期 key:
- 定期删除:每隔一段时间随机抽样检查过期 key
- 惰性删除:访问某个 key 时才检查是否过期
- 主动淘汰(内存不足时):根据内存策略驱动淘汰
如何防止缓存与数据库双写不一致?
- 避免“缓存与数据库双写
只删除缓存,不更新缓存
- 延迟双删策略
- 删除缓存
- 更新数据库
- 睡眠几十毫秒
- 再次删除缓存(清理可能在睡眠期间读写导致的脏缓存)
- 消息队列异步同步
- Binlog 监听数据变更(如 Canal)
Redis 集群了解吗?一致性哈希了解吗?
Redis Cluster 是 Redis 官方提供的分布式部署方案,用来实现数据分片和高可用,解决单节点 Redis 容量限制和单点故障问题。
集群 架构核心
分片(Sharding):Redis Cluster 把所有 key 的空间(0~16383)划分成 16384 个 槽(slot)。
每个节点负责一部分槽。
在 Redis Cluster 中,每个节点管理一部分槽位,比如:
1
2
3节点 A:槽 0 ~ 5460
节点 B:槽 5461 ~ 10922
节点 C:槽 10923 ~ 16383- 每个槽只属于一个主节点;
- 主节点挂了会由对应的从节点接管这些槽;
- Redis 使用 CLUSTER SLOTS 命令可以查看槽分配情况;
- 当客户端访问 key 时,Redis 根据 key 算出的 slot,去对应的节点执行操作。
每个 key 根据 CRC16 计算哈希值,然后对 16384 取模确定所在槽。
Key 到槽(slot)的计算方式:
1
2
3slot = CRC16(key) % 16384
# Redis 使用 CRC16 算法计算 key 的哈希值;
# 对结果 % 16384,得到 key 所在的槽编号。特殊规则:Hash Tag(哈希标签)
Redis 支持通过 {} 显式指定 key 的哈希部分,仅 {} 中的内容参与 hash 计算:
1
2SET order:{1001}:user 123 # 实际哈希 key 为 "1001"
SET order:{1001}:goods 456 # 实际哈希 key 也为 "1001"
项目 说明 槽总数 固定为 16384 Key 到槽的映射 使用 CRC16(key) % 16384 槽到节点映射 Redis 自动维护,分布到主节点上 客户端路由 客户端维护槽 -> 节点映射表,按槽选择目标节点 支持跨 key 操作 必须使用 {} 包裹共同 hash tag,确保 key 落在同一个槽上
多主多从架构:
- 主节点(Master)负责存储和处理请求;
- 从节点(Slave)做主节点的备份,主挂了自动选举。
自动故障转移:通过集群间的 Gossip 协议检测节点状态,节点故障后可自动 failover。
一致性 Hash
一致性哈希是一种分布式系统中常用的 负载均衡与数据分布算法,用于解决节点变动导致大量 key 重定位的问题。
Redis 的内存淘汰策略有哪些?
通过 maxmemory-policy 设置,包括:
- volatile-lru:只淘汰设置了过期时间的 key 中最近最少使用的
- allkeys-lru:淘汰所有 key 中最少使用的
- volatile-random / allkeys-random
- volatile-ttl:淘汰即将过期的 key
- noeviction:不淘汰(返回错误)
使用管道(Pipeline)的场景与优势?
- 减少网络 IO 开销:一次性发送多个命令,批量接收响应
- 适合大量读写操作,如批量写入排行榜
⚠️ Pipeline 不是事务,不能保证原子性
Redis 主从同步原理?
- 启动时从节点发送 PSYNC 命令请求全量同步
- 主节点生成 RDB 发送给从节点
- 后续使用 命令传播(命令复制 binlog 给从节点)
- 从节点断线重连时支持部分同步
Redis 哨兵机制(Sentinel)?
1. 监控
- 每个哨兵进程会定期向主节点和从节点发送 PING 命令,判断节点是否在线。
- 如果某个 Redis 实例连续几次未响应 PING,哨兵会认为其处于 SDOWN(主观下线) 状态。
2. 主观下线 vs 客观下线
| 状态 | 描述 |
|---|---|
| SDOWN(Subjectively Down) | 单个哨兵节点判断某主节点宕机 |
| ODOWN(Objectively Down) | 多个哨兵节点达成共识后认定主节点宕机 |
默认哨兵需要 超过半数同意,才会将主节点标记为客观下线(ODOWN)。
3. 故障转移
当哨兵确定主节点 ODOWN 后,会触发故障转移流程:
- 从节点中选择一个最合适的(数据最新的)作为新的主节点。
- 通知其他从节点复制新主节点。
- 客户端通过哨兵重新获取当前主节点地址。
4. 服务发现
客户端可以连接哨兵集群,使用 Sentinel 命令(如 SENTINEL get-master-addr-by-name
Redis 与 Kafka、RabbitMQ 的区别?
| 特性 | Redis Stream / List | Kafka / RabbitMQ |
|---|---|---|
| 持久性 | 弱 | 强 |
| 顺序性 | 有序 | 有序 |
| 消费模型 | 主动拉取 | 消费订阅 |
| 消费确认 | 无确认机制 | 有确认机制 |
Redis 更适合作为轻量消息队列,适合实时性要求高的任务缓存
Redis 会内存泄漏吗?
可能会:
- 忘记设置过期时间
- 大 key 或嵌套结构未及时清理
- 长时间使用 Pipeline 导致客户端内存积压
- Lua 脚本死循环
如何做 Redis 的监控与性能分析?
命令:INFO、MONITOR、SLOWLOG
工具推荐:
- RedisInsight(图形界面分析)
- Prometheus + Grafana(可视化监控)
- 自建面板采集 INFO 指标定期推送