Skip to content

Redis 7.0 集群面试题 ​

生成时间:2026-06-06 21:22 侧重:Redis 7.0 集群运维与架构(非 Spring 集成方向)


题目 1:Redis 7.0 有哪些值得关注的新特性? ​

难度:⭐⭐

标准答案:

Redis 7.0 的核心新特性包括:

  1. Function API(替代 Lua 脚本):引入 FUNCTION LOAD / FCALL / FCALL_RO,支持将 Lua 脚本以"函数"形式持久化存储到 Redis 中,解决了 Lua 脚本在集群重启后丢失的问题,并支持版本管理。
  2. 多线程 IO 增强:Redis 7.0 对多线程 IO(Threaded I/O)进行了优化,支持在 io-threads 配置下并行处理网络读写,显著提升高并发场景下的吞吐量(官方测试最高提升 2x)。
  3. ACL 增强:支持更细粒度的权限控制,可以对键、命令、Channel 设置独立的 ACL 规则,并支持 ACL LOG 查看权限拒绝记录。
  4. Cluster 管理命令增强:新增 CLUSTER LINKS、CLUSTER SHARDS 等命令,方便运维查看集群拓扑和节点间连接状态。
  5. List 数据类型新实现(Listpack):List 底层从 quicklist 迁移到 listpack + quicklist 混合结构,减少内存碎片,提升缓存友好性。
  6. RDB 格式优化:RDB 版本升级到 v10,支持更大字典的增量保存,加速大规模实例的 RDB 生成和加载。
  7. Client Eviction:支持在内存达到上限时,驱逐客户端输出缓冲区(而非仅返回 OOM 错误),提升稳定性。
  8. ZSET 的 ZMPOP / BZMPOP:支持原子性地弹出多个有序集合中的成员,适合消息队列场景。

延伸思考:

  • Function 与 Lua 脚本的核心区别是什么?为什么推荐在新项目中使用 Function?
  • 多线程 IO 是否意味着 Redis 变成了多线程处理命令?为什么?

题目 2:Redis Cluster 的 Hash Slot 机制是如何工作的? ​

难度:⭐⭐

标准答案:

Redis Cluster 采用 16384 个哈希槽(Hash Slot) 进行数据分片:

  1. Slot 分配:每个 Key 通过 CRC16 算法计算校验和,再对 16384 取模,得到该 Key 所属的 Slot 编号(0 ~ 16383)。
  2. Slot 映射到节点:16384 个 Slot 被分配到集群中的不同节点,每个节点负责一部分 Slot。例如,3 个节点的集群,每个节点约负责 5461 个 Slot。
  3. 客户端路由:客户端计算 Key 的 Slot 后,直接向负责该 Slot 的节点发送请求;如果请求发到了错误的节点,该节点会返回 MOVED 重定向响应,客户端据此更新路由缓存。
  4. ASK 与 MOVED 的区别:MOVED 表示 Slot 已经永久迁移到新节点;ASK 表示 Slot 正在迁移过程中,下次请求仍需先尝试原节点。

关键命令:

  • CLUSTER ADDSLOTS <slot> [slot ...]:为当前节点分配 Slot
  • CLUSTER NODES:查看集群拓扑和 Slot 分布
  • CLUSTER KEYSLOT <key>:查询指定 Key 属于哪个 Slot

延伸思考:

  • 为什么 Slot 数量是 16384 而不是更多或更少?(提示:心跳包大小、网络开销、迁移粒度)
  • 在集群模式下,多 Key 操作(如 MSET、MGET)有什么限制?如何绕过?

题目 3:Redis Cluster 的故障转移(Failover)机制是怎样的? ​

难度:⭐⭐⭐

标准答案:

Redis Cluster 的故障转移分为 自动故障转移 和 手动故障转移 两种:

自动故障转移流程 ​

  1. 故障检测(PFAIL → FAIL):

    • 每个节点定期向其他节点发送 PING;如果在 cluster-node-timeout(默认 15s)内未收到 PONG,则将该节点标记为 PFAIL(可能失效)。
    • 当集群中超过半数的主节点都认为某主节点为 PFAIL 时,该节点被标记为 FAIL(确认失效),并广播 FAIL 消息。
  2. 从节点选举:

    • 故障主节点的所有从节点中,会有一个发起选举(基于 Raft 算法的变体)。
    • 选举条件:从节点的复制偏移量(replication offset)越大,获得选票的概率越高(数据越新越优先)。
    • 获得超过半数主节点投票的从节点赢得选举。
  3. 晋升与新拓扑广播:

    • 当选从节点执行 SLAVEOF NO ONE,晋升为主节点。
    • 新主节点接管原主节点的所有 Slot,并广播 PONG 通知集群拓扑变更。

手动故障转移 ​

通过 CLUSTER FAILOVER [FORCE|TAKEOVER] 命令触发:

  • 不带参数:优雅转移,确保数据完全同步后再切换。
  • FORCE:在从节点未完全同步时也强制执行。
  • TAKEOVER:不经过选举,直接从节点立即晋升(适用于原主节点已无法通信的场景)。

延伸思考:

  • 默认 cluster-node-timeout 为 15s,这个参数应该如何根据实际场景调整?
  • 如果集群中有一半或以上的主节点同时故障,会发生什么?

题目 4:Redis 的持久化机制(RDB 与 AOF)有什么区别?如何选型? ​

难度:⭐⭐

标准答案:

维度RDB(Redis Database Backup)AOF(Append Only File)
原理定期将内存快照写入磁盘(fork 子进程)将每条写命令追加到文件(类似 binlog)
持久化时机可配置(如 save 900 1)或手动 SAVE/BGSAVE每个写命令立即或定期 fsync
文件大小紧凑的二进制文件,体积小文本文件,体积较大(可通过 BGREWRITEAOF 重写压缩)
恢复速度快(直接加载内存镜像)慢(需要重放所有命令)
数据安全性可能丢失最近一次快照后的所有数据可配置为 always(不丢失)、everysec(丢失 1s)、no(依赖 OS)
性能影响fork 时有短暂停顿(COW 机制),之后无影响always 模式性能影响大;everysec 较平衡

Redis 7.0 的混合持久化 ​

Redis 4.0+ 支持 RDB + AOF 混合持久化(默认开启,aof-use-rdb-preamble yes):

  • AOF 重写时,先写入 RDB 格式的全量数据,再追加增量 AOF 命令。
  • 重启时先加载 RDB 部分(快),再重放 AOF 增量(少),兼顾速度和安全性。

选型建议 ​

  • 允许少量数据丢失、追求快速重启 → RDB
  • 要求高数据安全、可以接受稍慢恢复 → AOF(everysec)
  • 生产环境推荐 → 混合持久化(RDB + AOF)

延伸思考:

  • RDB 的 fork() 操作在内存很大时会有什么问题?如何缓解?
  • AOF 的 everysec 模式下,如果磁盘 IO 饱和,Redis 主线程会阻塞吗?

题目 5:Redis 的内存淘汰策略(Eviction Policy)有哪些?应该如何选择? ​

难度:⭐⭐

标准答案:

当 Redis 内存达到 maxmemory 上限时,根据配置的淘汰策略决定如何处理新写入:

8 种淘汰策略(maxmemory-policy) ​

  1. noeviction(默认):不淘汰,对新写入返回 OOM 错误。
  2. allkeys-lru:从所有 Key 中淘汰最近最少使用(LRU) 的 Key。
  3. volatile-lru:从设置了过期时间的 Key 中淘汰 LRU 的 Key。
  4. allkeys-random:从所有 Key 中随机淘汰。
  5. volatile-random:从设置了过期时间的 Key 中随机淘汰。
  6. volatile-ttl:从设置了过期时间的 Key 中,淘汰 TTL 最短(即将过期)的 Key。
  7. allkeys-lfu(Redis 4.0+):从所有 Key 中淘汰最不经常使用(LFU) 的 Key。
  8. volatile-lfu(Redis 4.0+):从设置了过期时间的 Key 中淘汰 LFU 的 Key。

LRU vs LFU ​

  • LRU(Least Recently Used):关注"最近是否被访问",适合突发流量场景。
  • LFU(Least Frequently Used):关注"访问频率",适合长期热点场景(如缓存用户资料)。

选型建议 ​

场景推荐策略
通用缓存allkeys-lru
有冷热数据区分,且设置了过期时间volatile-lru 或 volatile-lfu
需要保留没有设置过期时间的"永久 Key"volatile-* 系列
访问频率差异大(少数 Key 被频繁访问)allkeys-lfu

延伸思考:

  • Redis 的 LRU 是精确的吗?为什么采用近似 LRU?(提示:性能与内存权衡)
  • 如何监控和分析当前实例的 Key 淘汰情况?

题目 6:Redis 7.0 的 Function(函数)是什么?与 Lua 脚本有什么区别? ​

难度:⭐⭐⭐

标准答案:

Function 是什么? ​

Redis Function 是 Redis 7.0 引入的 服务器端函数 机制,允许将 Lua 脚本以"函数"的形式持久化存储在 Redis 实例中,并通过 FCALL / FCALL_RO 调用。

与 Lua 脚本(EVAL)的核心区别 ​

维度Lua 脚本(EVAL / EVALSHA)Function(FCALL)
存储方式每次调用需传递脚本或 SHA1 摘要;重启后丢失持久化存储在 Redis 中(RDB/AOF 均会保存)
生命周期临时(仅在当前实例生命周期内有效)永久(除非显式删除 FUNCTION DELETE)
版本管理无支持 FUNCTION LOAD 时指定 REPLACE 更新函数
调用方式EVAL <script> <numkeys> ... 或 EVALSHA <sha1> ...FCALL <function_name> <numkeys> ...
只读函数无法声明只读,可能路由到主节点可通过 FCALL_RO 声明只读,可路由到从节点
集群模式需保证所有相关 Key 在同一 Slot(否则报错)同 Lua 脚本(需使用 Hash Tag 保证 Key 在同一 Slot)

使用示例 ​

redis
# 加载函数
FUNCTION LOAD "#!lua name=mylib\nredis.register_function('myfunc', function(keys, args) return #keys end)"

# 调用函数
FCALL myfunc 2 key1 key2 arg1 arg2

延伸思考:

  • 在 Redis 7.0 中,为什么推荐使用 Function 而不是 EVAL?
  • Function 在集群模式下的限制与 Lua 脚本是否完全相同?

题目 7:Redis 7.0 的多线程 IO 是如何工作的?是否意味着 Redis 变成了多线程? ​

难度:⭐⭐⭐

标准答案:

多线程 IO 的工作机制 ​

Redis 的多线程 IO(Threaded I/O)是 网络 IO 的多线程化,而非命令执行的并行化:

  1. 主线程 仍然负责:

    • 接收客户端连接
    • 解析命令
    • 执行命令(单线程,保证原子性)
    • 将响应结果写回客户端(可卸载到 IO 线程)
  2. IO 线程(配置 io-threads 数量)负责:

    • 读取客户端请求(read)
    • 将响应写回客户端(write)
    • 这两个操作在多核 CPU 上并行执行,提升吞吐量
  3. 启用条件:

    • 配置 io-threads-do-reads yes(Redis 6.0+ 默认关闭,需手动开启)
    • 配置 io-threads <N>(建议设置为 CPU 核心数的 1/2 ~ 2/3,最大 128)

Redis 仍然是单线程执行命令的 ​

多线程 IO 仅加速网络读写,命令的执行仍然是单线程的(在主线程中顺序执行),因此:

  • 命令的原子性仍然得到保证(无需担心并发修改)
  • 慢查询(如 KEYS *、大 Value 操作)仍然会阻塞所有后续命令

性能提升场景 ​

多线程 IO 在高并发、大 Value(网络传输耗时长)场景下效果显著;对于小 Value、低并发场景,提升有限。

延伸思考:

  • 为什么 Redis 不将命令执行也改为多线程?(提示:锁竞争、复杂度、原子性保证)
  • 如何验证当前实例是否真正受益于多线程 IO?

题目 8:Redis Stream 的消息消费模型是怎样的?与 Kafka 有什么异同? ​

难度:⭐⭐⭐

标准答案:

Redis Stream 的消费模型 ​

Redis Stream 是 Redis 5.0 引入的持久化、可分区、支持消费者组的消息队列:

  1. 消息 ID:每条消息有一个唯一 ID(格式:timestamp-seq,如 1650000000000-0),可自动生成或手动指定。
  2. 消费者组(Consumer Group):
    • 多个消费者可以组成一个"消费者组",组内每条消息只被一个消费者处理(竞争消费)。
    • 不同消费者组之间互相独立,每条消息会被每个组各消费一次(发布-订阅模式)。
  3. Pending 机制:
    • 消费者读取消息后,消息进入 PEL(Pending Entries List),状态为 pending。
    • 消费者处理完成后,需调用 XACK 确认消息,消息才会从 PEL 中移除。
    • 未确认的消息可以通过 XCLAIM 转移给其他消费者(故障转移)。

与 Kafka 的对比 ​

维度Redis StreamKafka
存储内存 + 可选 AOF/RDB 持久化磁盘(顺序写,吞吐极高)
分区不支持原生分区(需应用层实现)原生支持多分区,每个分区有序
消费语义at-least-once(需 XACK)at-least-once(可配置 exactly-once)
消息保留可配置 MAXLEN 限制长度按时间/大小保留,支持回溯
适用场景轻量级消息队列、实时性要求高海量消息、高吞吐、需回溯

关键命令 ​

redis
# 创建消费者组
XGROUP CREATE mystream mygroup $ MKSTREAM

# 消费消息(组内竞争)
XREADGROUP GROUP mygroup consumer1 COUNT 10 STREAMS mystream >

# 确认消息
XACK mystream mygroup <message-id>

延伸思考:

  • 如何使用 Redis Stream 实现"至少一次"和"精确一次"消费语义?
  • 在集群模式下,Stream 的 Key 应该如何设计才能保证同一 Stream 的所有数据在同一节点?

题目 9:如何对 Redis Cluster 进行扩容和缩容?需要注意哪些问题? ​

难度:⭐⭐⭐

标准答案:

扩容(添加新节点) ​

  1. 添加主节点:

    • 启动新 Redis 实例,配置为集群模式。
    • 使用 CLUSTER MEET <ip> <port> 将新节点加入集群。
    • 使用 redis-cli --cluster reshard 或 CLUSTER SETSLOT 手动将部分 Slot 迁移到新节点。
  2. 添加从节点:

    • 将新节点加入集群后,执行 CLUSTER REPLICATE <master-node-id>,使其成为指定主节点的从节点。

缩容(下线节点) ​

  1. 下线从节点:直接停止该节点即可(需确保其主节点有其他从节点,或主节点本身健康)。
  2. 下线主节点:
    • 先将该主节点负责的所有 Slot 迁移到其他主节点(redis-cli --cluster reshard)。
    • 确认 Slot 迁移完成后,使用 CLUSTER FORGET <node-id> 从集群中移除该节点。

关键注意事项 ​

  • 迁移过程中服务可用性:Slot 迁移是在线进行的,但在 MIGRATE 命令执行期间,涉及的热 Key 会有短暂阻塞(毫秒级)。
  • 避免大 Key 迁移:如果某个 Slot 中包含大 Key(如百万级成员的 Set),迁移会非常慢,甚至导致超时。建议提前拆分大 Key。
  • 副本数保证:下线主节点前,需确保其 Slot 已迁移,且集群中每个主节点至少有一个从节点(生产环境建议 1 主 2 从)。
  • 客户端路由更新:扩容/缩容后,客户端需要更新 Slot 路由缓存(大多数客户端会自动处理 MOVED 重定向)。

官方工具 ​

推荐使用 redis-cli --cluster 系列命令,而非手动执行 CLUSTER 命令:

bash
# 扩容:添加新节点并自动重新分片
redis-cli --cluster add-node <new_ip>:<new_port> <existing_ip>:<existing_port>

# 缩容:下线节点(会自动迁移 Slot)
redis-cli --cluster del-node <ip>:<port> <node-id>

延伸思考:

  • 在迁移 Slot 的过程中,如果客户端正在访问被迁移的 Key,会发生什么?
  • 如何评估集群扩容后性能是否达到预期?

题目 10:如何监控 Redis Cluster 的健康状态?有哪些关键指标? ​

难度:⭐⭐⭐

标准答案:

健康检查的核心维度 ​

  1. 集群拓扑健康:

    • CLUSTER INFO:查看 cluster_state(应为 ok)、cluster_slots_assigned(应为 16384)、cluster_slots_fail(应为 0)。
    • CLUSTER NODES:检查每个主节点是否有至少 1 个从节点,且从节点状态为 connected。
  2. 节点间通信健康:

    • CLUSTER LINKS(Redis 7.0+):查看节点间的 TCP 连接状态,重点关注 state(应为 connected)和 send_buf_free(发送缓冲区不应持续积压)。
    • 如果 CLUSTER LINKS 显示大量 disconnected,可能是网络分区或节点故障。
  3. 数据同步健康:

    • INFO replication:检查主从节点的 master_link_status(up)、master_repl_offset 与从节点的 slave_repl_offset 差值(应小于 1000,即延迟 < 1MB)。
    • 如果从节点长时间无法同步,可能是网络问题或主节点 repl-backlog-size 配置过小。
  4. 资源使用健康:

    • INFO memory:关注 used_memory(不应超过 maxmemory 的 80%)、mem_fragmentation_ratio(正常 1.0 ~ 1.5,超过 1.5 可能存在内存碎片)。
    • INFO stats:关注 evicted_keys(淘汰 Key 数量,持续增加说明内存不足)、expired_keys(过期 Key 数量,正常)、rejected_connections(被拒绝的连接数,应为 0)。
    • INFO persistence:关注 rdb_last_bgsave_status(应为 ok)、aof_last_write_status(应为 ok)。

关键告警指标 ​

指标告警阈值建议
cluster_state != ok立即告警(集群故障)
cluster_slots_fail > 0立即告警(有 Slot 无主)
主从复制延迟 > 10MB警告(可能网络问题或从节点慢)
used_memory > maxmemory * 0.8警告(内存即将耗尽)
mem_fragmentation_ratio > 2.0警告(内存碎片严重,建议重启)
evicted_keys 持续增长警告(内存不足,需扩容或优化)

监控工具推荐 ​

  • Redis 官方:redis-cli --cluster check <host>:<port>(快速检查集群健康)
  • Prometheus + Grafana:使用 redis_exporter 采集指标,配置仪表盘和告警
  • Redis Insight:官方 GUI 工具,可可视化集群拓扑和性能指标

延伸思考:

  • 在大规模集群(如 100+ 节点)中,如何高效地监控每个节点的健康状态?
  • CLUSTER LINKS 命令在 Redis 7.0 中解决了之前哪些运维痛点?

生成工具:OpenClaw + GLM-5.1 | 内容仅供参考,请结合实际生产经验使用。