Redis Cluster集群槽位迁移与Sentinel哨兵故障转移机制解析

Redis Cluster和Sentinel是Redis高可用架构的两种主要方案。Cluster通过分片实现横向扩展和自动故障转移,Sentinel为主从架构提供监控和自动切换能力。理解两者的工作原理和配置方法,对构建高可用Redis服务至关重要。

Redis Cluster分片原理与槽位机制

Redis Cluster将数据分布在16384个槽位(slot)上,每个节点负责一部分槽位。客户端根据键的CRC16哈希值对16384取模确定槽位,再根据槽位路由到对应节点。槽位计算公式:

slot = CRC16(key) mod 16384

使用hash tag可以强制多个键分配到同一槽位,支持多键操作。hash tag用花括号包裹键的子串:

# 这两个键会分配到同一槽位
SET {user:1000}:profile "value1"
SET {user:1000}:settings "value2"

# 验证槽位
CLUSTER KEYSLOT {user:1000}:profile
CLUSTER KEYSLOT {user:1000}:settings
# 两者输出相同

hash tag在事务(MULTI/EXEC)和Lua脚本中特别有用,因为Redis Cluster要求同一事务中的所有键必须在同一节点上。

集群搭建与节点配置

最小Redis Cluster需要6个节点(3主3从)。每个节点的redis.conf配置:

# redis-7000.conf
port 7000
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes
appendfilename "appendonly-7000.aof"
bind 0.0.0.0
protected-mode no
cluster-announce-ip 192.168.1.100
cluster-announce-port 7000
cluster-announce-bus-port 17000

cluster-enabled 启用集群模式,cluster-node-timeout 设置节点超时(毫秒),超过该时间未通信则判定节点故障。cluster-announce-* 在NAT或Docker环境中尤为重要,告知集群节点的真实可达地址和端口。bus端口固定为数据端口+10000,用于节点间内部通信。

使用redis-cli创建集群:

# 创建6节点集群,每个主节点1个从节点
redis-cli --cluster create 192.168.1.100:7000 192.168.1.100:7001 192.168.1.101:7000 192.168.1.101:7001 192.168.1.102:7000 192.168.1.102:7001 --cluster-replicas 1

# 检查集群状态
redis-cli -p 7000 CLUSTER INFO
redis-cli -p 7000 CLUSTER NODES

CLUSTER NODES输出中,每行包含节点ID、地址、角色(master/slave)、连接状态、槽位范围。cluster_state为ok表示集群正常运行,cluster_slots_assigned应等于16384。

槽位迁移与集群扩缩容

新增节点到集群后需要迁移槽位实现负载均衡。添加新节点:

# 添加新主节点(空槽位)
redis-cli --cluster add-node 192.168.1.103:7000 192.168.1.100:7000

# 为新主节点添加从节点
redis-cli --cluster add-node 192.168.1.103:7001 192.168.1.100:7000 --cluster-slave --cluster-master-id <new_master_id>

# 重新分片,将槽位迁移到新节点
redis-cli --cluster reshard 192.168.1.100:7000 --cluster-from <source_node_id> --cluster-to <target_node_id> --cluster-slots 5461 --cluster-yes

手动迁移槽位的底层操作流程,理解原理有助于排查迁移中断问题:

# 1. 通知目标节点准备导入槽位
CLUSTER SETSLOT 8000 IMPORTING <source_node_id>

# 2. 通知源节点准备迁出槽位
CLUSTER SETSLOT 8000 MIGRATING <target_node_id>

# 3. 从源节点迁移键
# 查找槽位中的键
CLUSTER GETKEYSINSLOT 8000 100

# 逐个迁移键到目标节点
MIGRATE 192.168.1.103 7000 "" 0 5000 KEYS key1 key2 key3

# 4. 向集群广播槽位归属变更
CLUSTER SETSLOT 8000 NODE <target_node_id>

MIGRATE命令是原子操作,源节点在迁移完成后删除该键。迁移过程中客户端访问该键会收到MOVED或ASK重定向:MOVED表示槽位已完成迁移需重新路由;ASK表示槽位正在迁移,临时到目标节点获取数据。

故障检测与自动故障转移

Redis Cluster通过Gossip协议传播节点状态。节点定期发送PING/PONG消息检测存活,cluster-node-timeout超时后标记节点为PFAIL(疑似故障)。超过半数主节点确认PFAIL后升级为FAIL,触发从节点选举。

从节点选举流程:从节点检测到主节点FAIL → 从节点提升自身复制偏移量 → 发起选举请求(Raft变体) → 获得多数主节点投票 → 成为新主节点 → 接管原主节点槽位 → 广播PONG消息更新集群拓扑。

# 查看故障转移状态
redis-cli -p 7001 CLUSTER FAILOVER

# 手动触发故障转移(在从节点执行)
redis-cli -p 7001 CLUSTER FAILOVER TAKEOVER

# 强制故障转移(忽略主节点确认)
redis-cli -p 7001 CLUSTER FAILOVER FORCE

TAKEOVER模式无需主节点同意,适用于主节点已完全不可达的紧急切换。FORCE模式跳过握手阶段直接切换,可能导致数据丢失。生产环境优先使用不带参数的CLUSTER FAILOVER确保数据一致性。

Sentinel哨兵架构与配置

Sentinel适用于不需要分片的主从架构,独立部署Sentinel进程监控Redis实例,在主节点故障时自动选举从节点切换。最小Sentinel部署需要3个实例避免脑裂:

# sentinel-26379.conf
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster YourPassword

# 启动Sentinel
redis-sentinel sentinel-26379.conf

sentinel monitor的最后一个参数2表示quorum,即2个Sentinel同意才判定主节点下线(客观下线)。down-after-milliseconds设置主观下线超时。failover-timeout限制故障转移总时长。parallel-syncs控制每次故障转移后多少个从节点并行同步新主节点数据,值越大恢复越快但新主节点负载越高。

Sentinel故障切换流程与客户端连接

Sentinel故障切换步骤:主观下线(单个Sentinel检测超时) → 客观下线(quorum个Sentinel确认) → 选举Leader Sentinel → Leader选择最优从节点 → 执行切换 → 通知其他Sentinel和客户端更新拓扑。

客户端通过Sentinel获取主节点地址,Sentinel在切换后通过Pub/Sub通知客户端拓扑变更:

import redis
from redis.sentinel import Sentinel

sentinel = Sentinel([
('192.168.1.100', 26379),
('192.168.1.101', 26379),
('192.168.1.102', 26379),
], socket_timeout=0.5)

# 获取主节点连接(自动故障转移后自动更新)
master = sentinel.master_for('mymaster', socket_timeout=0.5)
master.set('key', 'value')

# 获取从节点连接
slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
value = slave.get('key')

redis-py的Sentinel连接池在连接断开时自动重新查询Sentinel获取最新主节点地址,实现透明故障转移。读写分离场景中从节点读取需容忍最终一致性,故障切换瞬间可能有短暂读取不可用。

Cluster与Sentinel选型对比

Redis Cluster适合数据量大需水平扩展的场景,支持自动分片和多主多从,但不支持跨槽位事务,客户端需支持集群协议。Sentinel适合数据量可单机承载的场景,主从架构支持全部Redis命令,客户端集成简单但无自动分片能力。实际部署中,数据量低于单机内存上限时优先选择Sentinel,数据增长需分片时迁移到Cluster。

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

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

相关推荐