Redis Cluster集群数据分片哈希槽与故障转移自动恢复详解

Redis Cluster架构与哈希槽分片机制

Redis Cluster是Redis官方分布式方案,采用去中心化的Gossip协议实现节点通信,通过16384个哈希槽(Hash Slot)将数据均匀分布到多个节点上。每个键根据CRC16校验和取模映射到特定哈希槽,每个节点负责一部分槽位。当集群拓扑发生变化时,只有迁移的槽位数据需要重新分配,其余槽位不受影响。

Redis Cluster最少需要6个节点(3主3从)才能保证完整的高可用性。每个主节点负责一部分哈希槽,从节点实时复制主节点数据,当主节点故障时从节点自动晋升。

集群搭建与哈希槽分配

# 最小化6节点集群配置(redis.conf)
port 7001
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 5000
appendonly yes
bind 0.0.0.0

使用redis-cli创建集群并分配哈希槽:

# 创建3主3从集群
redis-cli --cluster create \
  192.168.1.101:7001 192.168.1.102:7002 192.168.1.103:7003 \
  192.168.1.104:7004 192.168.1.105:7005 192.168.1.106:7006 \
  --cluster-replicas 1

# 查看集群槽位分配
redis-cli -c -h 192.168.1.101 -p 7001 cluster slots

# 输出示例:
# 1) 1) (integer) 0       - 起始槽位
#    2) (integer) 5460    - 结束槽位
#    3) 1) "192.168.1.101"
#       2) (integer) 7001
#    4) 1) "192.168.1.104"
#       2) (integer) 7004

默认均匀分配,3主节点各负责5460、5461、5462个槽位。手动调整槽位分配:

# 将槽位1000从节点A迁移到节点B
redis-cli --cluster reshard 192.168.1.101:7001 \
  --cluster-from <node-a-id> \
  --cluster-to <node-b-id> \
  --cluster-slots 1000 \
  --cluster-yes

哈希标签与Key分组设计

Redis Cluster中不同Key默认可能分布在不同的槽位上,无法直接执行跨Key原子操作(如MGET、SUNION)。哈希标签(Hash Tag)机制允许将相关Key强制映射到同一槽位:

# 使用{}包裹哈希标签部分
SET user:{1000}:name "Alice"    # 槽位由"1000"计算
SET user:{1000}:age 25           # 同一槽位
SET user:{1000}:profile "..."    # 同一槽位

# 现在可以安全地执行批量操作
MGET user:{1000}:name user:{1000}:age user:{1000}:profile

哈希标签的设计需要在数据局部性和数据均匀性之间权衡。过度使用哈希标签会导致部分槽位热点集中,影响集群负载均衡。通常仅在需要原子操作或批量操作的业务实体上使用,如用户维度、订单维度的关联数据。

故障检测与自动转移机制

Redis Cluster通过Gossip协议进行节点间心跳通信。故障检测分为两个阶段:

# 节点故障标记过程:
# 1. PFAIL(疑似故障):节点A在cluster-node-timeout内未收到节点B的PONG响应
# 2. FAIL(确认故障):超过半数主节点标记B为PFAIL后,B被标记为FAIL

# 查看节点故障状态
redis-cli -c -h 192.168.1.101 -p 7001 cluster nodes

# 输出标识:
# master  - 主节点
# slave   - 从节点
# fail    - 已确认故障
# fail?   - 疑似故障
# handshake - 握手中

主节点被标记为FAIL后,其从节点发起选举:

# 从节点选举流程:
# 1. 从节点检测到主节点FAIL
# 2. 从节点向其他主节点发送CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST
# 3. 其他主节点投票(每个槽位负责节点一票)
# 4. 获得多数票的从节点晋升为新主节点
# 5. 集群配置更新广播到所有节点

# 手动触发故障转移(运维场景)
redis-cli -c -h 192.168.1.104 -p 7004 cluster failover takeover

从节点选举的优先级由复制偏移量(replication offset)决定,偏移量最大(数据最新)的从节点优先当选。选举过程中集群该槽位暂时不可用,典型中断时间在秒级。

数据迁移与在线扩缩容

Redis Cluster支持在线数据迁移,无需停机即可调整槽位分配:

# 添加新主节点
redis-cli --cluster add-node 192.168.1.107:7007 192.168.1.101:7001

# 新节点加入后槽位为空,需要从其他节点迁移槽位
redis-cli --cluster reshard 192.168.1.101:7001 \
  --cluster-from all \
  --cluster-to <new-node-id> \
  --cluster-slots 2048 \
  --cluster-yes

# 迁移过程中查看进度
redis-cli --cluster check 192.168.1.101:7001

数据迁移期间,客户端访问迁移中槽位的请求会被重定向(ASK/MOVED响应),客户端驱动自动跟随重定向完成请求。迁移完成前源节点和目标节点均保留数据副本,确保请求不会丢失。缩容操作先迁移走槽位再移除节点:

# 缩容:移除节点
redis-cli --cluster del-node 192.168.1.101:7001 <node-id>

# 缩容前确保该节点已无槽位负责
redis-cli --cluster reshard ...  # 先迁走槽位

生产环境建议每个主节点至少配置1个从节点,cluster-node-timeout根据网络质量调整(跨机房部署建议10秒以上)。客户端应使用支持集群拓扑缓存的驱动(如Jedis、Lettuce、go-redis),减少MOVED重定向开销。集群规模建议控制在数百节点以内,Gossip协议在大规模集群中会产生显著的心跳流量和故障检测延迟。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rediscluster-ji-qun-shu-ju-fen-pian-ha-xi-cao-yu-gu-zhang/

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

相关推荐