Redis 高可用与集群(Sentinel/Cluster)

共 40 题
📑 题目列表 40 题
#
★★★

1. Redis Cluster 的分片机制,16384 个哈希槽?

请说明 Redis Cluster 的分片机制,为什么使用 16384 个哈希槽,以及 key 如何映射到槽位?

  • 16384 个哈希槽的划分
  • CRC16 计算与取模
  • key 与节点映射、hash tag

Redis Cluster 将整个 keyspace 划分为 16384 个哈希槽(slot),每个节点负责一部分槽位。key 通过 CRC16(key) % 16384 计算所属槽位,再根据槽位分布定位到具体节点。槽位可以手工迁移实现数据扩缩容。选择 16384 是因为它足够大以支持大量节点且便于位图(bitmap)表示槽位分布,同时比 65536 更省内存(节点心跳用 16384 位(约 2048 字节)的位图)。使用 hash tag(key 中花括号部分)可让相关 key 落在同一槽位以支持多 key 操作。

槽位是"数据分发"的中间层,把 key 的解耦与数据迁移解耦——移动槽位即可迁移数据,无需知道具体 key,是集群扩缩容与负载均衡的基础。

# 计算 key 的槽位
redis-cli cluster keyslot mykey
(integer) 6556
#
★★★

2. Redis Sentinel 的高可用架构,监控、通知、故障转移?

请说明 Redis Sentinel 的高可用架构,以及它的监控、通知、故障转移三大功能?

  • Sentinel 的部署与作用
  • 主观下线与客观下线
  • 故障转移(failover)与领导者选举

Sentinel(哨兵)是 Redis 的高可用组件,通常部署 3 个及以上节点组成哨兵集群,监控主从节点。三大功能:监控(定期向主从发送命令判断存活)、通知(实例故障时通过 API 通知管理员或其他程序)、故障转移(主节点故障时自动选举新主并通过发布订阅通知客户端)。Sentinel 通过主观下线(单个哨兵判定)与客观下线(quorum 个哨兵确认)决策,故障转移时选举出一个领导者哨兵执行,新主上位后其他从库重新复制新主。

Sentinel 解决的是"主节点故障时自动切换"的可用性问题,通过哨兵集群的多数派裁定避免误判,并用配置管理与发布订阅让客户端感知新主。

#
★★★

3. 在线迁移工具,Redis-shake、redis-migrate?

请说明 Redis 在线迁移工具 Redis-shake 和 redis-migrate 的原理与适用场景?

  • Redis-shake 的同步与迁移能力
  • 全量同步 + 增量同步流程
  • 适用场景(跨集群、跨机房、版本升级)

Redis-shake 是阿里开源的数据同步工具,支持 RDB 全量同步 + 命令增量同步(通过解析复制流或 PSYNC),可跨集群、跨版本、跨机房在线迁移,也支持过滤、报警与断点续传。redis-migrate 是较早期的迁移工具,基于 SCAN 遍历 + 逐 key 迁移或 RDB 导入。Redis-shake 功能更完善,支持 Cluster 到 Cluster、双向同步、多活等复杂场景,是当前主流选择。

在线迁移的关键是"全量 + 增量"组合,先同步存量数据再持续追平增量,避免中断业务;Redis-shake 通过复制流实现增量,从而平滑迁移。

#
★★★

4. 多数据中心(Multi-DC)Redis 架构?

请说明多数据中心(Multi-DC)Redis 架构的常见方案与一致性考量?

  • 多机房部署模式(主从、双活、多活)
  • 数据同步方案(Redis-shake、CRDT、双写)
  • 一致性代价与冲突解决

多数据中心 Redis 架构常见有三种:主从异地(一个机房为主,其他机房只读,通过异步复制或 Redis-shake 同步)、双活/多活(多机房可写,通过双向同步或 CRDT 解决冲突)、以及客户端路由(按地域就近读写)。一致性上,异步复制存在延迟与冲突,多活需用 CRDT(如 Redis Enterprise 的 CRDT 副本)或冲突解决策略(LWW、版本号)。多活方案一致性与复杂度代价高,通常只在强需求场景使用。

多机房架构的核心权衡是"可用性(就近读写)"与"一致性(跨机房延迟)";多活提供高可用但需处理冲突与延迟,单主多从简单但有跨机房延迟与单点风险。

#
★★★

5. Redis Cluster 故障检测与自动 failover 的完整流程(节点间 PFAIL→FAIL 广播、cluster-node-timeout、从库发起选举并按 configEpoch/复制偏移胜出、广播新拓扑)是怎样的?

请完整描述 Redis Cluster 从节点故障检测到自动 failover 的流程,包括 PFAIL→FAIL 广播、cluster-node-timeout、从库选举与广播新拓扑?

  • 故障检测:PFAIL 与 FAIL 的判定
  • 从库发起选举与 configEpoch/复制偏移胜出
  • 新拓扑广播与客户端感知

流程如下:当主节点在 cluster-node-timeout(默认 15 秒)内未响应,发现它的节点将其标记为 PFAIL(主观下线);若该主节点被一定数量(半数以上持有该槽位的节点)其他节点标记为 FAIL(客观下线),则向全集群广播 FAIL。拥有该主节点槽位的从库会发起选举,通过 configEpoch 与复制偏移(replication offset)比较,复制偏移最大(数据最新)的从库胜出成为新主,并向集群广播新拓扑(PONG 携带新的槽位归属信息)。客户端通过 MOVED 重定向或更新拓扑感知新主。

PFAIL 是单点主观判断,FAIL 是多数派客观确认,避免局部网络抖动误判;选举以保证数据最新(复制偏移最大)的从库胜出,configEpoch 用于仲裁版本,广播保证拓扑一致。

#
★★★

6. Redis Cluster Gossip 的 MEET/PING/PONG/FAIL 消息类型各自承担什么职责?随机抽节点通信的带宽开销与集群收敛时间如何权衡?

请说明 Redis Cluster Gossip 协议中 MEET/PING/PONG/FAIL 消息类型的职责,以及随机抽节点通信的带宽开销与收敛时间的权衡?

  • 各消息类型的职责
  • Gossip 的收敛机制
  • 带宽与收敛时间的权衡参数

MEET 用于请求加入集群;PING 用于周期性探测节点存活并交换信息;PONG 是 PING 的应答,携带自己的状态与部分其他节点信息;FAIL 用于广播某个节点已客观下线。Gossip 通过周期性随机抽若干节点交换包含节点状态与槽位信息的消息,使状态逐步收敛到全集群一致。抽样节点数越多、周期越短,收敛越快但带宽开销越大;Redis 通过 cluster-node-timeout 动态调整 ping 间隔(超时时间越长,ping 越不频繁)来平衡。

Gossip 是"以带宽换去中心化"的协议:没有中心控制器,靠节点间随机信息交换实现状态传播。带宽与收敛是反向取舍,Redis 以超时时间动态调节探测频率来权衡。

#
★★★

7. Sentinel 的主观下线(SDOWN,单个 Sentinel 判定)与客观下线(ODOWN,quorum 个 Sentinel 同意)如何判定?failover 的领导者选举(类 Raft)与 quorum 各自防止什么问题?

请说明 Sentinel 的主观下线(SDOWN)与客观下线(ODOWN)的判定,以及 failover 领导者选举与 quorum 各自防止什么问题?

  • SDOWN 与 ODOWN 的判定条件
  • 领导者选举(Raft 风格)
  • quorum 防误判、选举防脑裂

主观下线(SDOWN)是单个 Sentinel 在 down-after-milliseconds 内未收到主节点 PONG 回复后的本地判定;客观下线(ODOWN)是当 SDOWN 的 Sentinel 获得 quorum 个其他 Sentinel 的确认后,将主节点判定为客观下线。判定客观下线后,哨兵间通过类似 Raft 的投票选举出一个领导者 Sentinel 执行故障转移。quorum 防止了单点误判(网络抖动导致个别哨兵误认为主节点挂了);领导者选举保证同一时刻只有一个哨兵执行 failover,防止多个哨兵同时切换造成脑裂与混乱。

SDOWN 是"先觉",ODOWN 是"共识",quorum 用多数派确认避免误判;领导者选举用唯一执行者避免并发切换。两者共同保证 failover 正确且不冲突。

#
★★★

8. Redis HA 的工程建议(在 Redis 数据结构与高可用范畴内)?

请给出 Redis 高可用(HA)的工程建议,涵盖主从、Sentinel、集群与数据安全方面?

  • 主从 + Sentinel 的基线配置
  • Cluster 的节点数与副本设计
  • 持久化、监控、备份与容灾

Redis HA 工程建议包括:至少部署一个从库并提供 Sentinel 或 Cluster 实现自动故障转移;主从建议开启复制(replicaof),并设置 min-replicas-to-write 防止主库孤立写入;Cluster 建议 3 主 3 从以上,副本数 ≥1,主从分属不同机器/机架;开启持久化(AOF 或 RDB)作为最后一道防线,并定期备份到异地;监控关键指标(延迟、内存、evicted_keys、复制积压);配置合理的 maxmemory 与淘汰策略防止内存溢出;对写入密集型场景关注复制延迟与积压缓冲区大小。

高可用不只是"有一台备用",而是"自动切换 + 数据安全 + 故障感知"的组合:从库做容灾、Sentinel/Cluster 做切换、持久化做兜底、监控做预警。

#
★★★

9. Redis Lua 脚本的应用,EVAL、EVALSHA?

请说明 Redis Lua 脚本的应用,以及 EVAL 与 EVALSHA 命令的区别与用法?

  • EVAL 直接执行脚本、原子性
  • EVALSHA 用 SHA1 缓存执行
  • 脚本缓存与 SCRIPT LOAD

Lua 脚本通过 EVAL 在 Redis 服务端执行,整个过程由单线程保证原子性,适合需要多步原子操作的场景(如分布式锁、限流、复杂计数)。EVAL 每次都要传脚本内容并解析;EVALSHA 通过脚本的 SHA1 摘要执行,前提是脚本已用 SCRIPT LOAD 缓存到服务端,可减少网络传输与解析开销。脚本天然支持 KEYS 与 ARGV 参数传递,做到原子且可复用。

Lua 脚本把"多步操作"压缩为一次原子执行,消除了客户端多步操作的竞态;EVALSHA 用缓存提升性能,是生产环境推荐用法。

> EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 k v
OK
> SCRIPT LOAD "return redis.call('GET', KEYS[1])"
"6eea1d..."
> EVALSHA 6eea1d... 1 k
#
★★★

10. Redis 事务(MULTI/EXEC)与 Lua 的差异?

请说明 Redis 事务(MULTI/EXEC)与 Lua 脚本在原子性、回滚和用途上的差异?

  • MULTI/EXEC 的队列执行与原子性
  • Lua 脚本的原子性与顺序执行
  • 回滚语义差异

MULTI/EXEC 把命令排队后一次性执行,保证不被其他命令打断,但执行中若某条命令报错,其他命令仍会继续执行(不整体回滚),也不支持条件判断。Lua 脚本由单线程执行全部逻辑,天然原子且可包含条件分支(if/while),可在同一个脚本内实现"检查-执行"等复合逻辑。两者都保证原子性,但 Lua 更灵活(可编程、可回滚语义),事务更简单但能力有限。

事务适合"批量执行的原子打包",Lua 适合"需要逻辑判断的原子操作"。由于 Lua 可编程且同样原子,实践中复杂原子操作多用 Lua,事务多用于简单批量。

#
★★★

11. Redis 函数(FUNCTION,Redis 7+)的应用?

请说明 Redis 7 引入的 Redis 函数(FUNCTION)的应用场景与与 Lua 脚本的差异?

  • FUNCTION 的库管理与部署
  • 函数与 Lua 脚本的差异(库隔离、版本、管理)
  • 应用场景

Redis 7 引入 Redis 函数,通过 FUNCTION 命令族(FUNCTION LOAD/FCALL/DELETE/FLUSH)管理函数库(library),每个库可包含多个函数。函数本质上仍是 Lua 脚本,但支持:库级封装与隔离、函数按需调用(FCALL)、无需担心脚本缓存失效(EVALSHA 的 NOSCRIPT 问题)、集中管理与版本化。适合部署需要长期维护、可复用的服务端逻辑,而 Lua 脚本更适合一次性/临时脚本。函数库可通过配置文件或启动时加载,保证在副本与故障切换后依然可用。

函数解决的是 Lua 脚本"缓存在内存、重启丢失、需手动 SCRIPT LOAD"的部署管理问题,把脚本提升为可版本化、可分类管理的库,强化了服务端逻辑的管理能力。

#
★★★

12. LRU 与 LFU(Redis 4.0+)的算法差异?

请说明 Redis 中 LRU 与 LFU 两种内存淘汰算法的差异,以及 Redis 4.0+ 为什么引入 LFU?

  • LRU(最近最少使用)原理
  • LFU(最不经常使用)原理,Redis 用带衰减的计数
  • 两者适用场景与差异

LRU(Least Recently Used)淘汰最近最少使用的 key,基于访问时间;LFU(Least Frequently Used,Redis 4.0+)淘汰访问频率最低的 key,基于访问频次。Redis 的 LRU/LFU 都是近似实现(采样 5 个左右候选 key 比较),LFU 用 8 位计数器记录访问频率,配合访问衰减(decay)避免长期热点 key 永远不被淘汰。差异:LRU 对"偶发访问的大量 key"不敏感,可能误淘汰接下来要用的 key;LFU 更能反映真实访问热度,适合存在长期冷热差异的缓存。纯缓存场景常用 allkeys-lru,关注访问频率时可用 allkeys-lfu。

LFU 弥补了 LRU 的"时间短但低频"与"时间久但高频"识别缺陷,通过周期性衰减让计数随时间老化,更贴近真实的冷热分布。选择取决于业务访问模式。

#
★★★

13. Redis 的内存淘汰策略,noeviction、allkeys-lru、volatile-lru 等?

请说明 Redis 的各种内存淘汰策略(noeviction、allkeys-lru、volatile-lru 等)的含义与适用场景?

  • 各淘汰策略的含义
  • volatile 与 allkeys 的区别
  • 选型建议

Redis 通过 maxmemory 限制内存,达到上限后按 maxmemory-policy 处理:noeviction 不淘汰,写入返回错误;volatile-lru/volatile-lfu/volatile-ttl/volatile-random 只淘汰设置了过期时间的 key;allkeys-lru/allkeys-lfu/allkeys-random 对所有 key 淘汰。纯缓存场景常用 allkeys-lru(或 lfu)充分利用内存;有持久化、需要保留数据的场景用 volatile-* 只淘汰可失效的 key;需保证数据完整时用 noeviction 并配合告警。

淘汰策略的选择取决于"哪些 key 可以被安全丢弃"。缓存可全部淘汰,业务数据应只淘汰有 TTL 的 key 或不淘汰,避免误删核心数据。

#
★★★

14. Redis 的过期策略,惰性删除 + 定期删除?

请说明 Redis 的过期删除策略,即惰性删除与定期删除的结合机制?

  • 惰性删除(访问时判断)
  • 定期删除(周期抽样)
  • 结合的原因与内存占用问题

Redis 过期删除采用"惰性删除 + 定期删除"结合:惰性删除指每次访问 key 时检查是否过期,过期则删除并返回空;定期删除指 serverCron 定期任务中随机抽样若干已过期 key 并删除,避免只有惰性删除导致长期不访问的过期 key 占用内存。惰性删除保证及时释放访问到的过期 key,定期删除兜底清理未被访问的过期 key,两者结合在 CPU 与内存间取得平衡。

纯惰性删除会积累大量过期 key 占内存,纯定期删除会频繁消耗 CPU。惰性+定期既保证读到过期 key 时及时删除,又周期性清理未访问的 key。

#
★★★

15. Cluster 的数据迁移,reshard、rebalance?

请说明 Redis Cluster 的数据迁移(reshard、rebalance)的概念与流程?

  • reshard 手动迁移槽位
  • rebalance 自动平衡槽位
  • 迁移过程与期间行为

reshard(redis-cli --cluster reshard)手动将若干槽位从源节点迁移到目标节点,迁移时先把目标节点标记为槽位接收方,再将源节点槽位中的 key 逐个移动(MIGRATE),迁移期间源节点对该槽位 key 仍可读写,访问不存在的 key 返回 ASK 重定向引导到目标节点。rebalance(redis-cli --cluster rebalance)自动根据各节点槽位数量在集群内均衡分配槽位。两者都通过"MIGRATE + ASK/MOVED 重定向"保证迁移期间数据不中断。

槽位迁移以"槽"为单位移动数据,key 逐个迁移期间客户端可能收到 ASK 重定向,需要客户端处理;迁移是平滑的,不会中断业务。

#
★★★

16. Cluster 的节点通信,Gossip 协议?

请说明 Redis Cluster 节点间通信所使用的 Gossip 协议的工作原理?

  • Gossip 的信息交换方式
  • 状态传播与拓扑感知
  • 节点故障检测

Redis Cluster 节点间通过 Gossip 协议通信,每个节点周期性向随机选取的其他节点发送 PING,消息携带自身状态、槽位信息以及随机附带的若干其他节点状态;收到 PONG 后更新本地视图。通过这种"随机交换"信息在集群内逐步传播,使所有节点最终收敛到一致的拓扑与故障状态。Gossip 提供去中心化的故障检测(PFAIL→FAIL)与拓扑发现,无需中心节点。

Gossip 的"随机抽样 + 信息冗余"带来高可扩展性与容错,但收敛是异步的、有延迟;用带宽换取去中心化与简单性。

#
★★

17. Redis Cluster 的从节点读写,默认不服务读请求,READONLY 命令开启后的数据一致性风险与适用场景?

请说明 Redis Cluster 从节点默认不服务读请求,以及 READONLY 命令开启后的数据一致性风险与适用场景?

  • 从节点默认处理 MOVED 重定向
  • READONLY 开启从库读
  • 数据一致性风险(复制延迟、读旧数据)

在 Redis Cluster 中,从节点默认不承担读请求,客户端访问从节点会收到 MOVED 重定向到主节点。执行 READONLY 命令后,从节点可对该命令所在槽位提供读服务,从而分担读压力。但主从复制是异步的,从库可能读到旧数据(复制延迟),且主从切换后从库数据可能不是最新。因此 READONLY 只适用于对一致性要求不高的场景(如缓存、展示类读多写少),且需配合主从同步健康监控。

READONLY 是"以一致性换读吞吐":从库读分担主库压力,但牺牲强一致。适用场景是能容忍短暂读旧数据的读多写少业务。

#
★★

18. Redis Cluster 的槽位倾斜与热点治理,hash tag、手动迁移槽位、多 key 操作的 slot 限制?

请说明 Redis Cluster 的槽位倾斜与热点治理手段,包括 hash tag、手动迁移槽位,以及多 key 操作的 slot 限制?

  • 槽位倾斜的原因与影响
  • hash tag 使相关 key 落在同槽
  • 多 key 操作需同槽

槽位倾斜指部分节点槽位或数据量过大,导致负载不均。治理手段:用 hash tag(key 中 {...} 部分参与哈希)将相关 key 聚到同槽,支持多 key 操作;手动迁移槽位(redis-cli --cluster reshard)把热点槽位从高负载节点迁到低负载节点;拆分热 key 为多份。多 key 操作(MGET、MSET、事务、Lua)要求所有 key 落在同一槽位,否则报 CROSSSLOT 错误,因此需要 hash tag 保证同槽。

槽位倾斜本质是"数据/流量分布不均"。hash tag 既解决同槽多 key 需求,也可能制造热点(大量 key 挤到同一槽),需综合评估;手动迁移用于再平衡。

#
★★

19. Redis Cluster 在线扩缩容,新增节点、reshard、槽位迁移、下线节点的完整流程与客户端影响?

请说明 Redis Cluster 在线扩缩容的完整流程(新增节点、reshard、槽位迁移、下线),以及期间的客户端影响?

  • 新增主从节点流程
  • reshard 迁移槽位
  • 下线节点流程

扩容流程:CLUSTER MEET 让新节点加入集群,通过 redis-cli --cluster reshard 把部分槽位迁移到新节点,最后为节点添加从库。缩容流程:先把要下线节点的槽位移到其他节点(reshard),迁移完成后用 CLUSTER FORGET 让其他节点遗忘该节点,最后下线。期间客户端可能收到 MOVED(槽位已迁移)或 ASK(槽位迁移中)重定向,需按提示重发请求;因 key 逐槽迁移,业务不中断。

整个扩缩容以"槽位迁移"为核心,数据以槽为单位平滑移动,客户端通过重定向自动适应拓扑变化,从而实现在线无损扩缩容。

#
★★

20. Redis 主从全量同步的代价,RDB 生成与传输对主从节点的影响,diskless replication(无盘复制)的取舍?

请说明 Redis 主从全量同步的代价,即 RDB 生成与传输对主从节点的影响,以及 diskless replication(无盘复制)的取舍?

  • 全量同步过程(RDB 生成 + 传输 + 加载)
  • 对主库(fork + 内存)与从库(加载阻塞)的影响
  • diskless replication 的取舍

主从全量同步时,主库 fork 生成 RDB 快照并通过网络传给从库,从库加载 RDB 到内存。代价:主库 fork 会因 COW 复制增加内存与 CPU 开销,生成 RDB 可能阻塞或影响磁盘 IO;从库加载 RDB 期间阻塞读写命令。diskless replication(repl-diskless-sync yes)让主库直接把 RDB 数据流式发送给从库而不落盘,减少磁盘 IO 与延迟,但要求主从网络带宽充足、且主库内存中的 RDB 数据需保留在内存以便发送。取舍:diskless 适合网络好、磁盘慢、从库大量增加的场景;普通场景落盘更简单可靠。

全量同步的代价集中在"fork 内存复制 + RDB 传输 + 从库加载阻塞"。diskless 用内存换磁盘 IO,加速同步但增加内存与网络压力,需按环境权衡。

#
★★

21. 复制积压缓冲区(repl-backlog-size)与 PSYNC 断线续传,如何避免频繁全量重同步?

请说明复制积压缓冲区(repl-backlog-size)与 PSYNC 断线续传机制,以及如何避免频繁全量重同步?

  • repl-backlog-size 的作用
  • PSYNC 部分重同步(增量续传)
  • 避免全量同步的配置

复制积压缓冲区(repl-backlog)是主库为每个从库维护的环形缓冲,保存最近写命令的复制偏移量。当从库断线重连时,通过 PSYNC 携带自己的复制偏移请求续传,若所需偏移仍在主库积压缓冲区内,则仅同步缺失部分(部分重同步);若偏移已超出缓冲区(或从库 runid 不匹配),则退化为全量重同步。适当调大 repl-backlog-size 可覆盖更长的断线时间,减少全量同步。

PSYNC 的增量续传依赖积压缓冲区覆盖断线期间产生的增量;缓冲区太小时断线稍久就触发全量重同步,浪费带宽与内存。因此按断线时长与写速率合理设置 repl-backlog-size。

#
★★

22. 缓存雪崩的工程治理全景,过期时间随机化、多级缓存、限流降级与热点数据不设置过期?

请说明缓存雪崩的工程治理全景,包括过期时间随机化、多级缓存、限流降级与热点数据不设置过期?

  • 缓存雪崩的成因
  • 过期时间随机化
  • 多级缓存、限流降级、热点不设过期

缓存雪崩是大量 key 同时过期或缓存集群故障,导致大量请求穿透到数据库,数据库被压垮。治理手段:过期时间随机化(在原 TTL 基础上加减随机值,避免同时过期);热点数据不设置过期(或逻辑过期);多级缓存(本地 Caffeine + Redis)分散压力;限流与降级(缓存未命中时用互斥锁/令牌限制回源并发,保护数据库);缓存集群高可用(多副本、Sentinel/Cluster)避免整体故障。核心是"错峰过期 + 分层缓存 + 兜底保护"。

雪崩的破坏在于"瞬间大量请求打到 DB"。随机化错峰、多级缓存分流、过期/降级控制回源并发,三者共同把 DB 压力限制在可承受范围。

#
★★

23. Redis Cluster 与 Redis Sentinel 的选型边界,数据量、QPS、多 key 事务与运维复杂度如何权衡?

请说明 Redis Cluster 与 Redis Sentinel 的选型边界,从数据量、QPS、多 key 事务与运维复杂度权衡?

  • Sentinel 的适用场景(单机主从 + 高可用)
  • Cluster 的适用场景(水平扩展)
  • 多 key 事务与运维复杂度差异

Sentinel 基于主从复制提供高可用,数据量受单机内存限制,适合中小数据量、QPS 适中、需多 key 事务/跨 key 原子操作的场景,运维简单。Cluster 通过分片实现水平扩展,适合大数据量、高 QPS、需要横向扩容的场景,但多 key 操作需同槽(hash tag),跨 key 事务受限,运维复杂度更高(槽位管理、迁移、Gossip)。选型边界:数据量小但需高可用与多 key 事务用 Sentinel;数据量大需水平扩展用 Cluster。

Sentinel 解决"可用性",Cluster 解决"扩展性"。多 key 操作的自由度是两者重要差异:Sentinel 无槽位限制,Cluster 需 hash tag 聚槽。运维复杂度上 Cluster 明显更高。

#
★★

24. Cluster 的 ASK 与 MOVED 重定向?

请说明 Redis Cluster 中 ASK 与 MOVED 重定向的区别与处理方式?

  • MOVED(槽位已迁移,需更新路由)
  • ASK(槽位迁移中,临时重定向)
  • 客户端处理方式

MOVED 表示请求的 key 所在槽位已整体迁移到其他节点,客户端应更新本地路由表并把后续对该槽位的请求发往新节点;ASK 表示槽位正在迁移中,目标节点尚未完全接管,客户端需先发 ASKING 再重发请求(仅本次请求重定向,不更新路由表)。两者都返回 -MOVED/-ASK 错误及目标节点地址。MOVED 是"永久性"路由变更,ASK 是"临时性"迁移中的引导。

MOVED 通知客户端更新缓存路由,ASK 是迁移窗口内的临时引导,避免客户端误缓存不稳定路由。客户端需正确区分以保持性能与正确性。

#
★★

25. Sentinel vs Cluster 的取舍,HA vs 水平扩展?

请说明 Sentinel 与 Cluster 在"高可用(HA)"与"水平扩展"上的取舍?

  • Sentinel 提供 HA 不提供水平扩展
  • Cluster 提供水平扩展 + 内置 HA
  • 使用场景与复杂度

Sentinel 的核心价值是 HA(主从故障自动切换),但数据仍存于单主节点,无法水平扩展容量与吞吐,适合单机内存够用、QPS 中等的场景。Cluster 提供水平扩展(分片扩容)并内置 HA(每片可配从库自动切换),适合大数据量、高 QPS 场景,但引入槽位管理、重定向与迁移复杂度。取舍:数据规模与 QPS 是主要决策变量,能力需求(跨 key 事务)与运维成本是次要约束。

Sentinel 解决"挂了怎么办"(可用性),Cluster 解决"不够用怎么办"(扩展性)。当数据量增长到单机瓶颈时需从 Sentinel 演进到 Cluster,而 Cluster 的复杂度是代价。

#
★★

26. Codis(豌豆荚)与 Cluster 的对比?

请对比 Codis(豌豆荚)与 Redis Cluster 的架构与差异?

  • Codis 的 proxy + 分片架构
  • Cluster 的去中心化架构
  • 两者的优缺点

Codis 是豌豆荚开源的 Redis 分布式方案,采用"Proxy + 分片"架构:客户端连接 Proxy,Proxy 按 key 哈希分片路由到多个 Redis 实例,通过 ZooKeeper 管理元数据与槽位。Redis Cluster 是官方去中心化方案,客户端直接连接节点,通过 16384 槽位与 Gossip 协议路由。Codis 的优点是无缝兼容单机 Redis、客户端无需感知分片、支持多 key 操作(经由 Proxy 处理),但多一跳 Proxy 增加延迟且需额外维护 ZK;Cluster 无 Proxy、延迟低、官方支持,但客户端需处理重定向、多 key 操作受限。

Codis 是"集中式代理 + 外部元数据"实现分片,Cluster 是"去中心化 + 内置槽位"实现分片。Codis 适合兼容旧客户端、需透传多 key 的场景;Cluster 是官方主流、性能更好。

#
★★

27. 大 Key(Bigkey)的检测与拆分?

请说明大 Key(Bigkey)的检测方法与拆分治理手段?

  • 大 Key 的危害
  • 检测方法(--bigkeys、MEMORY USAGE、SCAN)
  • 拆分方案

大 Key 指单个 key 的 value 过大(如超大 List/Hash/Set 或大字符串),会导致主线程阻塞、内存碎片、主从同步放大、扩容困难。检测方法:redis-cli --bigkeys(SCAN 采样统计各类型最大 key)、MEMORY USAGE key 精确测量、DEBUG OBJECT 查看序列化长度。拆分方案:把大 Hash/List 按业务或时间分片成多个小 key;用多个小 String 替代大 String;对序列化对象压缩;超大 key 用 UNLINK 惰性删除避免阻塞。

大 Key 治理原则是"避免单 key 承载过大",从结构(拆分、压缩)与运维(识别、惰性删除)两方面入手,降低主线程阻塞与内存放大。

#
★★

28. Redis Cluster 的在线迁移,如何用 redis-cli --cluster reshard 或 Redis-shake 平滑迁移槽位与数据,迁移期间对读写与内存的影响如何控制?

请说明如何用 redis-cli --cluster reshard 或 Redis-shake 平滑迁移槽位与数据,以及迁移期间对读写与内存的影响如何控制?

  • reshard 的槽位迁移流程
  • Redis-shake 的全量 + 增量迁移
  • 迁移期间读写与内存影响控制

redis-cli --cluster reshard <host>:<port> 交互式指定要迁移的槽位数与目标节点,通过 MIGRATE 逐个迁移 key;或用 Redis-shake 做全量 RDB 同步 + 增量命令同步,适合跨集群/跨机房迁移。迁移期间对读写的影响:被迁移 key 在源节点仍可读,写操作迁移中的 key 会通过 ASK 重定向;内存影响:迁移要复制数据,目标节点内存上升、源节点在迁移后释放,需预留内存空间。控制手段:分批迁移、低峰期执行、监控内存与延迟、设置迁移速率限制。

reshard 以槽为单位、Redis-shake 以流为单位,两者都保证"全量 + 增量"衔接不丢数据。内存影响是迁移的关键风险,需预留双份内存并错峰执行。

#
★★

29. Redis HA 与一致性?

请说明 Redis 高可用(HA)与数据一致性之间的关系与权衡?

  • 主从异步复制的强一致缺失
  • HA 切换可能丢失写入
  • 一致性缓解手段(WAIT、min-replicas、应用层补偿)

Redis 高可用依赖主从异步复制,主库写命令先执行、异步同步给从库。故障切换时,若主库的最新写入尚未同步到从库,这些写入会丢失,因此 Redis HA 提供的是"可用性",而非"强一致性"。缓解手段:WAIT 命令等待指定从库确认复制、min-replicas-to-write 限制从库不足时禁止写入、应用层补偿(重放或对账)、结合业务兜底。HA 与一致性在分布式系统是"CAP"权衡,Redis 默认倾向可用性。

Redis 的 HA 牺牲了部分一致性(切换丢写),换取低延迟与高可用。业务需根据对数据丢失的容忍度选择缓解手段,强一致场景需配合应用层或数据库。

#
★★

30. Redis Cluster 的一致性模型,为什么主从复制是异步的、故障切换可能丢失写入,业务上如何通过 WAIT 命令或应用层补偿缓解?

请说明 Redis Cluster 的一致性模型,为什么主从复制是异步的、故障切换可能丢失写入,以及如何通过 WAIT 或应用层补偿缓解?

  • 异步复制的一致性模型
  • 切换丢写的场景
  • WAIT 命令与应用层补偿

Redis Cluster 的主从复制是异步的:主库执行写命令后立即返回,后台异步同步给从库,因此主库与从库之间总存在复制延迟。故障切换时,若主库最新写入未同步到从库,切换后这部分写入会丢失,属于"非强一致"模型。缓解手段:WAIT 命令要求写命令复制到 N 个从库后才返回,可降低丢写概率但增加延迟;min-replicas-to-write 保证从库数量;应用层补偿(对账、重放、消息队列兜底)处理极端丢写。业务应根据对数据丢失的容忍度选择强度。

异步复制换取低延迟与高吞吐,代价是弱一致。WAIT 可提升"写后读"的复制保证,但无法完全消除切换丢失,需应用层兜底。

#
★★

31. Lua 脚本的原子性,单线程执行?

请说明 Lua 脚本在 Redis 中如何保证原子性,以及单线程执行机制?

  • Lua 脚本一并执行、不被打断
  • 单线程模型下的原子性来源
  • 长脚本的阻塞风险

Redis 的命令执行是单线程的,Lua 脚本在被执行时整个脚本作为一条命令执行,期间其他命令不会插入,因此脚本内的所有操作是原子的。这种原子性来自"单线程 + 脚本不被打断"的机制:脚本执行期间事件循环被阻塞,其他客户端命令排队等待。代价是长脚本会阻塞主线程,影响其他请求,因此应控制脚本执行时间(lua-time-limit)。

Lua 的原子性天然来自单线程模型,无需加锁。但"原子"也意味着"阻塞",长脚本或含阻塞操作会拖慢整个实例,需用短脚本、避免非纯函数。

#
★★

32. EVAL 与 EVALSHA 的脚本缓存机制(SCRIPT LOAD/SCRIPT FLUSH)与集群模式下的差异?

请说明 EVAL 与 EVALSHA 的脚本缓存机制(SCRIPT LOAD/SCRIPT FLUSH),以及集群模式下的差异?

  • SCRIPT LOAD 缓存脚本、SCRIPT FLUSH 清空
  • EVALSHA 用 SHA1 执行
  • 集群模式下脚本与 key 的槽位限制

EVAL 每次执行需传脚本内容,EVALSHA 通过 SCRIPT LOAD 缓存得到 SHA1 后按摘要执行,减少网络与解析开销。SCRIPT FLUSH 清空脚本缓存。集群模式下,EVAL/EVALSHA 的脚本内所有 key 必须落在同一槽位(否则报 CROSSSLOT),因为脚本在单节点执行;与函数(FUNCTION)不同,脚本缓存是节点本地的,节点重启后需重新 SCRIPT LOAD。因此生产环境建议用 FUNCTION 或确保脚本 key 聚合。

脚本缓存提升执行效率,但集群下脚本 key 必须同槽,且缓存是节点本地的(重启丢失)。这是集群脚本使用的关键约束。

#
★★

33. Redis 7 的 FUNCTION 与 Lua 脚本在部署、管理与库隔离上的差异?

请说明 Redis 7 的 FUNCTION 与 Lua 脚本在部署、管理与库隔离上的差异?

  • 函数库的部署与集中管理
  • 库隔离与版本化
  • 与 Lua 脚本(EVALSHA)的对比

FUNCTION 以"库(library)"为单位管理,可包含多个函数,通过 FUNCTION LOAD/FCALL/DELETE/FLUSH 集中管理,支持库隔离、版本化与命名空间,函数在启动时加载或通过配置持久化,故障切换后仍可用。Lua 脚本通过 EVAL/EVALSHA 执行,脚本缓存在内存、重启即丢失,需手动 SCRIPT LOAD,且无库隔离与版本管理。差异:FUNCTION 适合生产长期维护的服务端逻辑,Lua 脚本适合一次性临时脚本;FUNCTION 管理更规范、可复用。

FUNCTION 把"散落的脚本"升级为"可管理的函数库",解决部署、缓存、隔离与版本问题,是 Redis 7 对脚本管理能力的增强。

#
★★

34. Redis Lua 与一致性?

请说明 Redis Lua 脚本如何保证一致性,以及在不同场景下的边界?

  • Lua 单节点执行的原子性
  • 集群下多 key 的槽位限制
  • 跨节点/跨库的一致性边界

Lua 脚本在单节点内通过单线程执行保证原子性与一致性:脚本内所有操作要么全部执行,要么因脚本错误整体回滚,期间不被打断。但一致性边界限于单节点:集群模式下脚本内 key 必须同槽,无法跨节点执行;脚本不保证跨节点事务(如涉及多个槽位/多主节点)。此外脚本执行期间阻塞主线程,需控制脚本长度。因此 Lua 的一致性本质是"单节点原子",跨节点一致性需通过业务层或额外机制保证。

Lua 的强一致性限定在单节点脚本内,跨槽位/跨节点操作超出其能力。理解这个边界才能正确设计脚本与 key 分布。

#
★★

35. Redis Cluster 的槽位迁移、reshard 与客户端重定向的成本如何评估?

请评估 Redis Cluster 槽位迁移、reshard 与客户端重定向带来的成本?

  • 迁移期间的数据复制成本
  • 客户端重定向(MOVED/ASK)的代价
  • 对延迟与内存的影响

槽位迁移成本包括:数据复制成本(key 逐个 MIGRATE,源库与目标库网络带宽、目标库内存增加)、迁移期间主线程开销(MIGRATE 是同步命令,可能增加延迟)、客户端重定向成本(MOVED 使客户端更新路由、ASK 使客户端多一次 RTT 引导)。评估要点:迁移量大小、迁移速率、目标节点内存余量、客户端是否支持重定向。控制手段:分批迁移、低峰执行、监控内存与延迟、预留缓存。

迁移成本 = 数据复制带宽/内存 + 主线程阻塞 + 客户端重定向开销。重定向本身通常不致命,但迁移量大或速率过快会放大延迟与内存压力,需量化评估。

#
★★

36. 哨兵与 Cluster 的选型边界,读写分离在 Cluster 下的实现?

请说明哨兵(Sentinel)与 Cluster 的选型边界,以及读写分离在 Cluster 下的实现方式?

  • Sentinel 与 Cluster 的选型依据
  • Cluster 下读写分离(READONLY)
  • 一致性代价

选型边界:数据量小、QPS 中等、需多 key 事务与跨 key 操作时用 Sentinel + 主从;数据量大、QPS 高、需水平扩展时用 Cluster。集群下读写分离通过从节点 READONLY 命令开启,让从库承担读请求,但需注意:从库读会读到旧数据(复制延迟),且从库默认不服务读请求(需要 READONLY)。实现时客户端应先定位槽位的主节点,再通过 READONLY 让从节点读,并容忍一致延迟。适合读多写少、对一致性要求不高的场景。

读写分离是"以读延迟换一致性",Cluster 下用 READONLY 实现。选择哨兵还是 Cluster 取决于容量与扩展需求,读写分离只适用于能容忍延迟的场景。

#

37. Redis 跨机房/多活的同步方案,Redis Enterprise CRDT、自研双向同步与双写冲突解决(LWW)的取舍?

请说明 Redis 跨机房/多活的同步方案(Redis Enterprise CRDT、自研双向同步、双写冲突解决 LWW)的取舍?

  • Redis Enterprise CRDT 多活
  • 自研双向同步
  • 双写冲突解决(LWW)

跨机房/多活方案:Redis Enterprise 内置 CRDT(无冲突复制数据类型)实现多活,自动同步并解决冲突,但需商业版;自研双向同步(如 Redis-shake 双向)需自行处理冲突与环路;双写冲突解决常用 LWW(Last-Writer-Wins,最后写入者胜),以时间戳/版本决定最终值,但可能造成数据丢失。取舍:CRDT 一致性最好但成本高,自研双向同步灵活但复杂,双写 LWW 简单但可能丢数据。选择取决于一致性与成本要求。

多活的核心是"两处可写 + 冲突解决"。CRDT 提供数学上无冲突的合并,LWW 简单但可能丢失旧值,自研方案需权衡复杂度与可靠性。

#

38. maxmemory 配置与内存回收?

请说明 Redis 的 maxmemory 配置与内存回收机制?

  • maxmemory 的作用
  • 内存回收(淘汰策略)
  • 相关监控指标

maxmemory 设置 Redis 可用的最大内存,达到上限后按 maxmemory-policy 触发淘汰(LRU/LFU/随机/noeviction)回收内存。合理配置 maxmemory 可防止 Redis 占用过多系统内存导致 OOM,同时配合淘汰策略控制内存水位。内存回收还包括:过期 key 的惰性+定期删除、内存碎片的整理(activedefrag)。监控指标:used_memory、maxmemory、evicted_keys、mem_fragmentation_ratio。

maxmemory 是 Redis 内存的"上限红线",淘汰策略决定"满了之后怎么办"。配置需结合业务对数据丢失的容忍度与缓存/持久化场景。

#

39. Redis 大 Key 的检测手段,redis-cli --bigkeys、MEMORY USAGE 与 SCAN 采样的精度和代价差异?检测后如何拆分或压缩大 Key?

请说明 redis-cli --bigkeys、MEMORY USAGE 与 SCAN 采样三种大 Key 检测手段的精度与代价差异,以及检测后如何拆分或压缩大 Key?

  • 三种检测手段的原理与精度
  • 各自的代价(阻塞、时间)
  • 拆分与压缩手段

redis-cli --bigkeys 对全库 SCAN 采样,统计各类型中最大的 key,精度近似(只统计采样到的样本,且逐个序列化统计长度,有开销但可接受);MEMORY USAGE key 精确测量单个 key 的内存占用,可针对性排查;SCAN 手动遍历 + 逐 key 判断,灵活但需自行实现。--bigkeys 适合快速全局摸底,MEMORY USAGE 适合精确定位。检测后拆分:大 Hash/List 按业务或时间分片;大 String 拆成多个小 String 或用 Hash 存储字段;压缩:序列化对象用压缩算法(如 snappy/gzip),或将大对象落地到对象存储。

三种手段的取舍是"精度 vs 代价":--bigkeys 快但近似、MEMORY USAGE 准但需逐个调用、SCAN 灵活但需自写。拆分与压缩从根本上降低单 key 体积。

#

40. Redis 多活/跨机房方案(CRDT 与双写)的一致性代价?

请说明 Redis 多活/跨机房方案(CRDT 与双写)的一致性代价?

  • CRDT 的冲突解决与一致性
  • 双写的一致性代价
  • 网络延迟与故障处理

多活/跨机房方案让多个机房可写,一致性代价包括:网络延迟导致复制滞后,跨机房读写可能读到旧数据;双写与 CRDT 都需要处理冲突,CRDT 通过无冲突合并保证最终一致但仅适用于特定类型(寄存器、计数器、集合),双写(如 LWW)可能丢失写入;同步故障时需降级或采取断裂处理。核心代价是"以最终一致性换取就近可用性",牺牲强一致与实时性。

多活的一致性模型是"最终一致",代价是跨机房延迟、冲突解决与故障补偿。强一致业务(库存、余额)通常不适合多活,需权衡 SLA。