Redis Cluster集群拓扑设计与槽位迁移故障恢复实战

Redis Cluster是Redis官方提供的分布式方案,通过哈希槽分片实现数据水平拆分,支持自动故障转移。在数据库高可用架构设计中,Redis Cluster既能满足大容量缓存需求,又能保证单节点故障不影响整体服务。本文从集群拓扑设计、槽位管理、故障恢复到性能优化,完整覆盖Redis Cluster的运维实践。

Redis Cluster集群架构与哈希槽位分配

Redis Cluster采用16384个哈希槽(Hash Slot)将键空间划分为16384个区间。每个键通过CRC16算法计算哈希值后对16384取模,确定所属槽位。集群中的每个Master节点负责一部分槽位。

最小高可用集群需要6个节点(3主3从),每个Master配一个Replica节点。常见部署拓扑:

– 3主3从:每个节点分配约5461个槽位
– 6主6从:更高吞吐,每节点约2730个槽位
– 9主9从:大规模场景,每节点约1820个槽位

使用redis-cli创建集群:

redis-cli --cluster create   192.168.1.101:6379 192.168.1.102:6379 192.168.1.103:6379   192.168.1.104:6379 192.168.1.105:6379 192.168.1.106:6379   --cluster-replicas 1

创建后查看集群状态和槽位分配:

# 查看集群信息
redis-cli -c cluster info

# 查看节点和槽位分布
redis-cli -c cluster nodes

# 输出示例
# 192.168.1.101:6379 master - 0-5460
# 192.168.1.102:6379 master - 5461-10922
# 192.168.1.103:6379 master - 10923-16383
# 192.168.1.104:6379 slave of 192.168.1.101
# 192.168.1.105:6379 slave of 192.168.1.102
# 192.168.1.106:6379 slave of 192.168.1.103

每个节点的cluster.conf配置文件需开启集群模式:

port 6379
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec

cluster-node-timeout设置节点心跳超时时间,超过该时间未收到节点响应则判定为故障。生产环境建议5000-15000毫秒。

集群节点扩容缩容与槽位迁移操作

扩容操作分三步:添加新节点、迁移槽位、重新分配从节点。

添加新Master节点到集群:

# 将新节点加入集群
redis-cli --cluster add-node 192.168.1.107:6379 192.168.1.101:6379

# 为新Master添加Replica
redis-cli --cluster add-node 192.168.1.108:6379 192.168.1.101:6379   --cluster-slave --cluster-master-id <new-node-id>

使用redis-cli的reshard功能迁移槽位:

redis-cli --cluster reshard 192.168.1.101:6379

# 交互式输入:
# How many slots? 4096
# Receiving node ID? <new-node-id>
# Source node ID? all (从所有节点迁移)

程序化方式迁移槽位,逐个槽迁移确保数据完整性:

import redis

src = redis.RedisCluster(host='192.168.1.101', port=6379)
new_node_id = 'abcdef1234567890'

for slot in range(0, 4096):
    src.cluster('setslot', slot, 'node', new_node_id)
    keys = src.cluster('getkeysinslot', slot, 100)
    for key in keys:
        src.migrate('192.168.1.107', 6379, key, 0, 5000)

缩容操作反向执行:先将目标节点的槽位迁移到其他节点,再移除节点。

# 将要移除节点的槽位迁移到其他节点
redis-cli --cluster reshard 192.168.1.101:6379   --cluster-from <node-to-remove-id>   --cluster-to <target-node-id>   --cluster-slots 4096 --cluster-yes

# 移除节点
redis-cli --cluster del-node 192.168.1.101:6379 <node-to-remove-id>

主从故障转移与Cluster Failover恢复

当Master节点故障,Cluster自动检测并触发故障转移。cluster-node-timeout超时后,其他节点标记故障Master为PFAIL状态,经过gossip协议传播后升级为FAIL状态,Replica节点发起选举成为新Master。

手动故障转移场景:Master节点需要维护时,执行手动Failover实现平滑切换:

# 在Replica节点上执行
redis-cli -h 192.168.1.104 -p 6379 cluster failover

# FORCE模式:不等待Master确认直接切换
redis-cli -h 192.168.1.104 -p 6379 cluster failover FORCE

# TAKEOVER模式:强制接管(无其他节点同意时使用,有脑裂风险)
redis-cli -h 192.168.1.104 -p 6379 cluster failover TAKEOVER

手动Failover流程:Replica停止复制,通知Master停止写入,等待Master回复,更新自身配置epoch,广播新拓扑。

验证故障转移后集群状态:

# 检查所有节点是否正常
redis-cli -c cluster nodes | grep -E "fail|handshake"

# 确认新Master已接管槽位
redis-cli -c cluster slots

故障Master恢复后,会自动成为新Master的Replica,无需手动干预。

Cluster网络分区脑裂问题与处理

网络分区导致集群分裂为多个子网。持有半数以上Master节点的分区(Majority Partition)继续服务;少数派分区(Minority Partition)的Master进入下线状态,拒绝读写请求。

cluster-node-timeout决定分区检测灵敏度。设置过短会在网络抖动时误判,设置过长会延长故障恢复时间。生产环境根据网络质量选择5000-15000ms。

分区期间少数派分区的Replica不会自动提升为Master,因为无法获得多数派投票。当网络恢复后,少数派分区的Master重新加入集群并同步数据。

应对分区导致的数据不一致问题,写入时使用WAIT命令确保数据复制到指定数量的节点:

# 写入后等待至少1个Replica确认,超时100ms
SET key value
WAIT 1 100

Redis Cluster性能优化与Pipeline批量操作

Cluster模式下跨槽位操作受限。普通MSET命令在Cluster中会报CROSSSLOT错误,需使用Hash Tag确保相关键落在同一槽位:

# 使用大括号指定Hash Tag
SET {user:1001}:name "Alice"
SET {user:1001}:age 30
SET {user:1001}:email "alice@example.com"

# CRC16仅计算大括号内的部分
# {user:1001}的三个键都在同一槽位
MGET {user:1001}:name {user:1001}:age {user:1001}:email

使用Pipeline减少网络往返,批量执行命令:

import redis

rc = redis.RedisCluster(host='192.168.1.101', port=6379)

# Pipeline批量执行
pipe = rc.pipeline()
for i in range(1000):
    pipe.set(f"key:{i}", f"value:{i}")
results = pipe.execute()

Cluster Pipeline自动按节点分组,每个节点维护独立Pipeline连接,减少跨节点RTT。实测1000个SET命令,Pipeline模式耗时约5ms,逐条执行约500ms。

读写分离配置,在Replica节点读取数据降低Master压力:

import redis

rc = redis.RedisCluster(
    host='192.168.1.101', port=6379,
    readonly_mode=True  # 允许从Replica读取
)

# READONLY命令启用从节点读取
# 注意:Replica数据存在复制延迟,不适合强一致场景

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rediscluster-ji-qun-tuo-pu-she-ji-yu-cao-wei-qian-yi-gu/

(0)
小编小编
上一篇 12小时前
下一篇 12小时前

相关推荐