Redis 集群(Cluster)
一、定义
1. 基本概念
Redis 8.4 集群(Redis Cluster)是官方提供的分布式存储解决方案,基于去中心化架构,将数据分片存储在多个节点中,同时提供高可用性(自动故障转移)、水平扩容能力,解决单机 Redis 的存储容量上限、并发瓶颈和单点故障问题。
2. 核心特性
- 无中心节点,所有节点平等通信(Gossip 协议)
- 数据按“槽位”分片,避免单点存储压力
- 支持主从复制 + 自动故障转移,保障服务可用性
- 支持水平扩容(动态添加/删除节点)
- 兼容 Redis 核心命令,部分多键操作需满足“槽位一致”
二、工作原理
1. 槽位(Slot)机制
Redis 集群将所有数据映射到 16384 个槽位(0~16383),每个槽位对应一部分数据,集群的核心是“槽位分配”而非“数据分配”:
- 每个节点负责一部分连续/离散的槽位(如节点 A 负责 0-5460,节点 B 负责 5461-10922)
- 客户端操作数据时,先计算键对应的槽位,再与集群节点通信(获取槽位-节点映射关系)
- 槽位是集群数据分片的最小单位,迁移数据时以“槽位”为单位迁移(而非单个键)
- 槽位的优势:方便扩容和数据分派查找
(1)槽位计算:CRC16 算法
Redis 采用 CRC16 算法计算键的哈希值,再通过取模映射到槽位,公式如下:
slot = CRC16(key) % 16384
(2)16384 个槽位的原因
- 2¹⁴ = 16384,16 位 CRC 值取模后范围合理,兼顾“分片粒度”和“节点通信开销”
- 槽位数量过多:节点间同步槽位映射信息的开销增大(Gossip 协议传输数据变多)
- 槽位数量过少:分片粒度不足,易导致数据分布不均(单个槽位数据量过大)
2. 分片与节点通信
(1)节点角色
- 主节点(Master)
- 负责处理槽位的读写请求,每个槽位仅对应 1 个主节点
- 每个主节点至少配置 1 个从节点(建议 2 个,提升可用性)
- 从节点(Slave)
- 复制主节点数据,主节点故障时自动晋升为主节点(故障转移)
(2)Gossip 协议(节点通信核心)
- 集群节点通过 Gossip 协议同步以下信息:
- 节点状态(在线/离线)
- 槽位分配信息
- 主从节点映射关系
- 故障节点标记
- 优点
- 去中心化,无需中心节点协调
- 异步通信,低开销(适合大规模集群)
- 扩展性好,新增节点自动同步信息
- 缺点
- 信息同步有延迟(最终一致性),可能导致短暂的槽位映射不一致
- 节点数量过多时,Gossip 消息会占用过多带宽(建议集群节点不超过 100 个)
3. 故障转移机制
- 心跳检测:从节点检测主节点心跳(默认每 1 秒发送 PING 请求)
- 故障标记:主节点超过
cluster-node-timeout(默认 15 秒)未响应,从节点标记主节点为“疑似故障” - 故障确认:集群中超过半数主节点标记该主节点为“故障”,触发故障转移
- 选举新主:该主节点的所有从节点通过“投票”选举 1 个从节点晋升为主节点
- 接管槽位:新主节点接管原主节点的所有槽位,其他从节点切换复制新主节点
- 重新认主:故障主节点恢复后,自动成为新主节点的从节点
三、配置方法
1. 环境准备
- 服务器:在同一台主机上模拟 6 台服务器(端口不同)
- 端口规划:开放端口 6391-6396
2. 单节点配置文件(redis.conf)
# 基础配置
bind 0.0.0.0 # 允许所有 IP 访问
port 6391 # 主节点端口
daemonize yes # 后台运行
pidfile /var/run/redis_6391.pid
logfile "/var/log/redis/6391.log"
dir /data/redis/6391 # 数据存储目录)
# 集群配置(核心)
cluster-enabled yes # 开启集群模式
cluster-config-file nodes-6391conf # 集群配置文件(自动生成,记录槽位/节点信息)
cluster-node-timeout 15000 # 节点超时时间(15 秒,故障检测阈值)
cluster-replica-validity-factor 10 # 从节点晋升主节点的有效性因子(默认 10)
cluster-migration-barrier 1 # 主节点至少保留的从节点数量(防止迁移后无从节点)
cluster-require-full-coverage no # 允许部分槽位不可用时集群仍可用(建议设为 no)
- cluster-enabled yes:开启集群模式
- cluster-config-file nodes-6391.conf:集群配置文件(自动生成,记录槽位/节点信息)
3. 启动所有节点
此时所有节点都是平等关系,不存在主从。
4. 创建集群
# --cluster-replicas 1 每个主节点对应 1 个从节点
[root@yingzai cluster]#redis-cli -a 12345678 --cluster create --cluster-replicas 1 \
192.168.17.30:6391 192.168.17.30:6392 192.168.17.30:6393 \
192.168.17.30:6394 192.168.17.30:6395 192.168.17.30:6396
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.17.30:6395 to 192.168.17.30:6391
Adding replica 192.168.17.30:6396 to 192.168.17.30:6392
Adding replica 192.168.17.30:6394 to 192.168.17.30:6393
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 6285a369982a996e9ee9d5ec0ab3830b62c12c3b 192.168.17.30:6391
slots:[0-5460] (5461 slots) master
M: 9060f2324ceccd8006e6900be345a3e582ff506b 192.168.17.30:6392
slots:[5461-10922] (5462 slots) master
M: 06016b7e4f379b8627a8eea990ffb1d3399a5c41 192.168.17.30:6393
slots:[10923-16383] (5461 slots) master
S: 00ccd230128996aad0d264b5643c4e75b0a8acc0 192.168.17.30:6394
replicates 06016b7e4f379b8627a8eea990ffb1d3399a5c41
S: 823889a54eb53a1fc0ebcb24d12bccfe2c5b07bd 192.168.17.30:6395
replicates 6285a369982a996e9ee9d5ec0ab3830b62c12c3b
S: e0546e1b91ec3dea9667aa4625549a4e73e61c67 192.168.17.30:6396
replicates 9060f2324ceccd8006e6900be345a3e582ff506b
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.17.30:6391)
M: 6285a369982a996e9ee9d5ec0ab3830b62c12c3b 192.168.17.30:6391
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 00ccd230128996aad0d264b5643c4e75b0a8acc0 192.168.17.30:6394
slots: (0 slots) slave
replicates 06016b7e4f379b8627a8eea990ffb1d3399a5c41
M: 9060f2324ceccd8006e6900be345a3e582ff506b 192.168.17.30:6392
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 823889a54eb53a1fc0ebcb24d12bccfe2c5b07bd 192.168.17.30:6395
slots: (0 slots) slave
replicates 6285a369982a996e9ee9d5ec0ab3830b62c12c3b
M: 06016b7e4f379b8627a8eea990ffb1d3399a5c41 192.168.17.30:6393
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: e0546e1b91ec3dea9667aa4625549a4e73e61c67 192.168.17.30:6396
slots: (0 slots) slave
replicates 9060f2324ceccd8006e6900be345a3e582ff506b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
创建集群时,会自动划分主从关系。
5. 验证集群
(1)查询集群状态
# 选择一个节点登录
redis-cli -p 6391 -a 12345678
# redis
127.0.0.1:6391> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:368
cluster_stats_messages_pong_sent:402
cluster_stats_messages_sent:770
cluster_stats_messages_ping_received:397
cluster_stats_messages_pong_received:368
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:770
total_cluster_links_buffer_limit_exceeded:0
cluster_slot_migration_active_tasks:0
cluster_slot_migration_active_trim_running:0
cluster_slot_migration_active_trim_current_job_keys:0
cluster_slot_migration_active_trim_current_job_trimmed:0
cluster_slot_migration_stats_active_trim_started:0
cluster_slot_migration_stats_active_trim_completed:0
cluster_slot_migration_stats_active_trim_cancelled:0
127.0.0.1:6391> CLUSTER NODES
00ccd230128996aad0d264b5643c4e75b0a8acc0 192.168.17.30:6394@16394 slave 06016b7e4f379b8627a8eea990ffb1d3399a5c41 0 1767056450166 3 connected
9060f2324ceccd8006e6900be345a3e582ff506b 192.168.17.30:6392@16392 master - 0 1767056449146 2 connected 5461-10922
823889a54eb53a1fc0ebcb24d12bccfe2c5b07bd 192.168.17.30:6395@16395 slave 6285a369982a996e9ee9d5ec0ab3830b62c12c3b 0 1767056451184 1 connected
06016b7e4f379b8627a8eea990ffb1d3399a5c41 192.168.17.30:6393@16393 master - 0 1767056448130 3 connected 10923-16383
e0546e1b91ec3dea9667aa4625549a4e73e61c67 192.168.17.30:6396@16396 slave 9060f2324ceccd8006e6900be345a3e582ff506b 0 1767056450000 2 connected
6285a369982a996e9ee9d5ec0ab3830b62c12c3b 192.168.17.30:6391@16391 myself,master - 0 0 1 connected 0-5460
(2)模拟故障转移
- kill 6392 节点
192.168.17.30:6393> CLUSTER NODES
06016b7e4f379b8627a8eea990ffb1d3399a5c41 192.168.17.30:6393@16393 myself,master - 0 0 3 connected 10923-16383
00ccd230128996aad0d264b5643c4e75b0a8acc0 192.168.17.30:6394@16394 slave 06016b7e4f379b8627a8eea990ffb1d3399a5c41 0 1767057163753 3 connected
9060f2324ceccd8006e6900be345a3e582ff506b 192.168.17.30:6392@16392 master - 1767057158637 1767057155000 2 disconnected 5461-10922
823889a54eb53a1fc0ebcb24d12bccfe2c5b07bd 192.168.17.30:6395@16395 slave 6285a369982a996e9ee9d5ec0ab3830b62c12c3b 0 1767057162000 1 connected
6285a369982a996e9ee9d5ec0ab3830b62c12c3b 192.168.17.30:6391@16391 master - 0 1767057162736 1 connected 0-5460
e0546e1b91ec3dea9667aa4625549a4e73e61c67 192.168.17.30:6396@16396 slave 9060f2324ceccd8006e6900be345a3e582ff506b 0 1767057161717 2 connected
- 此节点状态变为 disconnected
- 槽位发生迁移
四、动态扩容/缩容
1. 扩容(添加节点)
(1)添加主节点到集群
[root@yingzai redis-6392]#redis-cli -a 12345678 --cluster add-node 192.168.17.30:6392 192.168.17.30:6396
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Adding node 192.168.17.30:6392 to cluster 192.168.17.30:6396
>>> Performing Cluster Check (using node 192.168.17.30:6396)
M: e0546e1b91ec3dea9667aa4625549a4e73e61c67 192.168.17.30:6396
slots:[5461-10922] (5462 slots) master
M: 06016b7e4f379b8627a8eea990ffb1d3399a5c41 192.168.17.30:6393
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 823889a54eb53a1fc0ebcb24d12bccfe2c5b07bd 192.168.17.30:6395
slots: (0 slots) slave
replicates 6285a369982a996e9ee9d5ec0ab3830b62c12c3b
M: 6285a369982a996e9ee9d5ec0ab3830b62c12c3b 192.168.17.30:6391
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 00ccd230128996aad0d264b5643c4e75b0a8acc0 192.168.17.30:6394
slots: (0 slots) slave
replicates 06016b7e4f379b8627a8eea990ffb1d3399a5c41
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Getting functions from cluster
>>> Send FUNCTION LIST to 192.168.17.30:6392 to verify there is no functions in it
>>> Send FUNCTION RESTORE to 192.168.17.30:6392
>>> Send CLUSTER MEET to node 192.168.17.30:6392 to make it join the cluster.
[OK] New node added correctly.
192.168.17.30:6396 是集群中的某个节点,相当于新节点的领路人。
(2)分配槽位给新主节点(自动迁移槽位和数据)
redis-cli -a 12345678 --cluster reshard 192.168.17.30:6396
(3)添加从节点并关联主节点
# redis-cli --cluster add-node 192.168.1.103:6380 192.168.1.100:6379 --cluster-slave --cluster-master-id 主节点ID
redis-cli -a 12345678 --cluster add-node 192.168.17.30:6397 192.168.17.30:6396 \
--cluster-slave --cluster-master-id e0546e1b91ec3dea9667aa4625549a4e73e61c67
redis-cli -a 12345678 --cluster add-node 192.168.17.30:6398 192.168.17.30:6396 \
--cluster-slave --cluster-master-id 84c6e985f9e1c402971b7745586c712d291b381b
2. 缩容(删除节点)
(1)删除从节点
# redis-cli --cluster del-node 192.168.1.103:6380 从节点ID
redis-cli -a 12345678 --cluster del-node 192.168.17.30:6398 cd96fd8e891d8b6e3ea3c8eed9fdc439c4289d2e
(2)迁移主节点的槽位到其他主节点
redis-cli -a 12345678 --cluster reshard 192.168.17.30:6392
- 操作截图

- 检查集群状态
[root@yingzai redis-6392]#redis-cli -a 12345678 --cluster check 192.168.17.30:6391
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.17.30:6391 (6285a369...) -> 1 keys | 9706 slots | 2 slaves.
192.168.17.30:6393 (06016b7e...) -> 0 keys | 3339 slots | 1 slaves.
192.168.17.30:6396 (e0546e1b...) -> 0 keys | 3339 slots | 1 slaves.
[OK] 1 keys in 3 masters.
6392 的状态自动由 master 变为 slave。
(3)删除主节点(需确保槽位已迁移完成)
redis-cli --cluster del-node 192.168.1.103:6379 主节点ID
五、常用操作
1. 集群管理命令
- cluster info:查看集群整体信息(槽位使用、节点数量、状态)
- cluster nodes:查看所有节点详情(ID、角色、槽位、主从关系)
- cluster slots
92.168.17.30:6393> CLUSTER SLOTS
1) 1) (integer) 0
2) (integer) 5460
3) 1) "192.168.17.30"
2) (integer) 6391
3) "6285a369982a996e9ee9d5ec0ab3830b62c12c3b"
4) (empty array)
4) 1) "192.168.17.30"
2) (integer) 6395
3) "823889a54eb53a1fc0ebcb24d12bccfe2c5b07bd"
4) (empty array)
2) 1) (integer) 5461
2) (integer) 10922
3) 1) "192.168.17.30"
2) (integer) 6392
3) "9060f2324ceccd8006e6900be345a3e582ff506b"
4) (empty array)
4) 1) "192.168.17.30"
2) (integer) 6396
3) "e0546e1b91ec3dea9667aa4625549a4e73e61c67"
4) (empty array)
3) 1) (integer) 10923
2) (integer) 16383
3) 1) "192.168.17.30"
2) (integer) 6393
3) "06016b7e4f379b8627a8eea990ffb1d3399a5c41"
4) (empty array)
4) 1) "192.168.17.30"
2) (integer) 6394
3) "00ccd230128996aad0d264b5643c4e75b0a8acc0"
4) (empty array)
查看槽位分配情况(哪个节点负责哪些槽位)
- cluster keyslot k1
192.168.17.30:6393> CLUSTER KEYSLOT k1
(integer) 12706
查看 k1 所属槽位
- cluster addslots
…:为主节点分配槽位(手动分配) - cluster delslots
…:删除主节点的槽位 - cluster failover:手动触发从节点晋升为主节点(主从切换)
- cluster forget
192.168.17.30:6393> CLUSTER FORGET 9060f2324ceccd8006e6900be345a3e582ff506b
OK
移除故障节点(需所有节点执行)
2. 故障处理命令
- cluster reset:重置节点(脱离集群,清空槽位信息)
- cluster replicate
:让当前节点成为指定主节点的从节点 - redis-cli --cluster check ip:port:检查集群健康状态(槽位、主从、数据一致性)
3. 数据操作命令(与单机差异)
- 支持绝大多数单机命令(get、set、hset、lpush 等)
- 多键操作限制
- 仅支持 “同一槽位” 的多键命令(如 mset {user}:100 {user}:101)
- 操作其他不同槽位的 key 会有路由提示
192.168.17.30:6393> keys *
(empty array)
192.168.17.30:6393> get k1
-> Redirected to slot [12706] located at 192.168.17.30:6391
"v1"
192.168.17.30:6391> mset k1 v1 k2 v2
(error) CROSSSLOT Keys in request don't hash to the same slot
192.168.17.30:6391> mset k1:{x} v1 k2:{x} v2
-> Redirected to slot [16287] located at 192.168.17.30:6393
OK
192.168.17.30:6393> mget k1:{x} k2:{x}
1) "v1"
2) "v2"
用 {} 括起来,表示放到同一个槽位。
- 不支持命令:keys *(集群模式下需用 scan)、flushdb(需指定节点或批量执行)
- 槽位分配导致 MOVED 报错
127.0.0.1:6391> set k1 v1
(error) MOVED 12706 192.168.17.30:6393
127.0.0.1:6391> get k1
(error) MOVED 12706 192.168.17.30:6393
127.0.0.1:6391> quit
[root@yingzai cluster]#redis-cli -p 6391 -a 12345678 -c
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6391> get k1
-> Redirected to slot [12706] located at 192.168.17.30:6393
(nil)
192.168.17.30:6393> set k1 v1
OK
192.168.17.30:6393> get k1
"v1"
登录时加 -c 参数,防止路由失效。
- 查看槽位占用
127.0.0.1:6391> CLUSTER KEYSLOT k1:{x}
(integer) 16287
127.0.0.1:6391> CLUSTER COUNTKEYSINSLOT 16287
(integer) 0
- CLUSTER KEYSLOT key:查看某个 key 的槽位
- CLUSTER COUNTKEYSINSLOT slot:查看某个槽位是否被占用(0 表示未被占用)
六、业务场景
1. 高并发读写场景
- 适用:电商秒杀、直播弹幕、游戏排行榜(QPS 10 万 +)
- 优势:槽位分片分散读写压力,主节点并行处理请求,从节点分担读压力
2. 海量数据存储场景
- 适用:用户画像存储、日志缓存、物联网数据(数据量 100GB+)
- 优势:水平扩容突破单机存储上限,槽位迁移支持动态扩容,不影响业务
3. 高可用核心业务场景
- 适用:支付系统、订单系统、核心缓存(不允许单点故障)
- 优势:主从复制 + 自动故障转移,故障切换秒级完成,服务可用性 99.99%+
4. 异地容灾场景
- 适用:跨地域业务(如全国分布式应用)
- 实现:跨机房部署集群节点,主节点在 A 机房,从节点在 B 机房,故障时 B 机房从节点晋升
七、注意事项
1. 槽位与数据分布
- 避免 “槽位倾斜”:确保槽位在主节点间均匀分配(可通过 cluster slots 检查)
- 避免 “大 key”:单个 key 数据量超过 100MB 会导致槽位迁移卡顿,建议拆分大 key(如哈希表拆分)
- 哈希标签合理使用:多键操作必须用 {} 强制同一槽位,否则报错 MOVED
2. 高可用性配置
- 每个主节点至少配置 2 个从节点(防止单从节点故障导致主节点无备份)
- 调整 cluster-node-timeout:根据业务延迟设置(如网络不稳定设为 30 秒)
- 关闭 cluster-require-full-coverage:避免部分槽位故障导致整个集群不可用
- 也就是说,集群不必完整,也能提供服务
3. 扩容/缩容注意事项
- 扩容时优先添加主节点,再添加从节点(避免主节点无备份)
- 缩容时必须先迁移槽位,再删除主节点(否则会导致槽位丢失)
- 槽位迁移期间会有短暂 “读写延迟”,建议在业务低峰期操作
4. 性能优化
- 关闭主节点持久化(AOF/RDB):持久化会占用 CPU/IO,建议从节点开启持久化(主从复制同步数据)
- 调整 Gossip 协议参数:cluster-gossip-period(默认 100ms),高并发场景可适当增大(如 500ms)减少通信开销
5. 数据一致性
- 主从复制是异步的:主节点故障可能导致少量数据丢失(可通过 repl-diskless-sync 优化同步速度)
- 避免跨节点事务:Redis 集群不支持跨槽位事务,建议拆分事务或使用本地事务
八、面试题
1. Redis 集群生产上用过吗?说说集群 slot 分配原理?槽位和分片用什么算法?拓扑响应了解吗?
(结合上文槽位机制、CRC16 算法等内容回答)
2. Redis 集群为什么用 16384 个槽位?
- 槽位数量需兼顾 “分片粒度” 和 “通信开销”:2¹⁴=16384 是平衡后的结果
- 槽位过多:Gossip 协议同步槽位映射信息的开销增大(节点间传输数据量多)
- 最主要的原因是网络开销
- 槽位过少:分片粒度不足,易导致数据分布不均(单个槽位数据量过大,迁移卡顿)
3. CRC16 算法在 Redis 集群中的作用是什么?如何处理多键操作?
- 作用
- 计算键的 16 位哈希值,对 16384 取模得到槽位,实现数据到槽位的映射
- 多键操作处理
- 若键包含 {},则仅对 {} 内的内容计算 CRC16(哈希标签)
- 示例:{user}:100 和 {user}:101 会映射到同一槽位,支持 mset 操作
- 无哈希标签的多键操作会报错 MOVED(槽位不一致)
4. Redis 集群故障转移的完整流程是什么?
(见上文“故障转移机制”部分)
5. Redis 集群的 Gossip 协议有什么作用?有哪些优缺点?
(见上文“Gossip 协议”部分)
6. Redis 集群出现 “槽位倾斜” 怎么办?如何避免?
- 原因
- 槽位分配不均、部分槽位存储大量数据(大 key)、节点扩容后未重新分配槽位
- 解决方法
- 手动重分配槽位:执行 redis-cli --cluster reshard,将过载节点的槽位迁移到其他节点
- 拆分大 key:将哈希表、列表等大 key 拆分为小 key(如 user:100 拆分为 user💯info、user💯orders)
- 扩容节点:新增主节点,重新分配槽位,分散压力
- 避免方案
- 集群创建时自动分配槽位(–cluster create 命令)
- 定期检查槽位分布(cluster slots),低峰期调整
- 限制大 key 大小(通过 Redis 配置 max-bulk-output-len 或监控工具检测)
7. Redis 集群扩容时,槽位迁移的过程是什么?会影响业务吗?
- 槽位迁移流程(以主节点 A→主节点 B 为例)
- 发起迁移:执行 reshard 命令,指定迁移的槽位数量和目标节点 B
- 数据迁移:节点 A 将槽位内的键逐个迁移到节点 B(先迁移数据,再更新槽位映射)
- 槽位更新:节点 A 删除槽位,节点 B 添加槽位,通过 Gossip 协议同步给所有节点
- 对业务的影响
- 迁移期间,该槽位的读写请求会暂时路由到节点 A(旧主),迁移完成后路由到节点 B(新主)
- 单个键迁移时会加短暂锁(微秒级),高并发场景可能出现少量延迟,但不会丢数据
- 建议在业务低峰期扩容,避免迁移大 key 导致卡顿
8. 如何设计 Redis 集群的异地容灾方案?
(结合“异地容灾场景”部分回答)