Redis Cluster分片架构设计原理
Redis Cluster是Redis官方分布式方案,采用去中心化的哈希槽(Hash Slot)分片策略,将整个键空间划分为16384个哈希槽,每个主节点负责一部分槽位。客户端通过CRC16(key) % 16384计算键所属的槽位,直接路由到目标节点,无需代理层。这种设计消除了中心节点的性能瓶颈,单集群可横向扩展到数百个节点,官方推荐配置不超过1000个节点。
哈希槽分配与键路由机制
每个键通过CRC16校验和取模映射到0-16383的某个槽位。Cluster默认对整个键名做哈希,但支持hash tag语法——当键名中包含{…}时,仅对花括号内的部分做哈希。这保证了相关键分配到同一槽位,使MGET、Pipeline等多键操作可以在单节点上完成。
# 哈希槽计算示例
# key = 'user:1001'
# CRC16('user:1001') = 5478
# slot = 5478 % 16384 = 5478
# hash tag示例
# key = 'user:{1001}:profile' -> 只对'1001'做哈希
# key = 'user:{1001}:orders' -> 同样对'1001'做哈希
# 这两个键一定落在同一节点
# 查看键的哈希槽
CLUSTER KEYSLOT user:1001
# 返回: 5478
CLUSTER KEYSLOT user:{1001}:profile
CLUSTER KEYSLOT user:{1001}:orders
# 两者返回相同的槽位号
集群搭建与槽位分配实践
生产环境的标准Cluster配置为6节点:3主3从。每个主节点分配一段连续的哈希槽,从节点复制主节点数据并提供故障转移能力。
# 最小化集群配置 - 6节点(3主3从)
# 每个节点的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 --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 info
redis-cli -c -h 192.168.1.101 -p 7001 cluster nodes
# 查看槽位分配
redis-cli -c -h 192.168.1.101 -p 7001 cluster slots
MOVED重定向与ASK临时重定向
客户端发送命令到错误节点时,目标节点返回MOVED或ASK重定向响应。MOVED表示槽位已永久迁移到新节点,客户端应更新本地槽位映射表。ASK表示槽位正在迁移中,临时重定向到新节点,不更新映射表。
# MOVED响应示例
# -MOVED 5478 192.168.1.103:7003
# ASK响应示例(槽位迁移过程中)
# -ASK 5478 192.168.1.103:7003
# 客户端处理逻辑伪代码
def send_command(key, command):
slot = crc16(key) % 16384
node = slot_map.get(slot)
response = node.send(command)
if response.is_moved():
slot_map[response.slot] = response.target_node
return response.target_node.send(command)
elif response.is_ask():
response.target_node.send('ASKING')
return response.target_node.send(command)
故障检测与自动故障转移全流程
Redis Cluster的故障检测采用Gossip协议的PING/PONG消息机制。每个节点定期向其他节点发送PING,如果在cluster-node-timeout内未收到PONG响应,则将目标节点标记为PFAIL(疑似故障)。当超过半数的主节点将某节点标记为PFAIL时,该节点状态升级为FAIL,触发故障转移。
# 故障转移流程:
# 1. 从节点检测到主节点FAIL
# 2. 从节点发起选举
# 3. 主节点投票:每个主节点只有一票,先到先得
# 4. 获得多数票的从节点晋升为主节点
# 5. 新主节点接管原主节点的所有槽位
# 6. 通知集群其他节点更新槽位映射
# 手动触发故障转移
redis-cli -c -h 192.168.1.104 -p 7004 cluster failover
# 强制故障转移
redis-cli -c -h 192.168.1.104 -p 7004 cluster failover takeover
故障转移的选举延迟策略:从节点在发起选举前会等待一段时间,延迟时间 = 500ms * (rank + 1),rank是复制偏移量的排名。复制偏移量最大的从节点延迟最短,最可能先发起选举并获得投票,保证数据最完整的从节点优先晋升。
在线扩容与槽位迁移操作
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
# 自动均衡槽位
redis-cli --cluster rebalance 192.168.1.101:7001 \
--cluster-threshold 1
# 添加从节点
redis-cli --cluster add-node \
192.168.1.108:7008 192.168.1.101:7001 \
--cluster-slave --cluster-master-id <master-id>
Cluster模式下的限制与规避方案
Redis Cluster的核心限制是跨槽操作不被支持。MGET、MSET、Pipeline等多键操作要求所有键在同一槽位,否则返回CROSSSLOT错误。这一限制可通过hash tag和客户端侧聚合两种方式规避。
# CROSSSLOT错误示例
MGET user:1001 user:1002 user:1003
# (error) CROSSSLOT Keys in request don't hash to the same slot
# 方案一:hash tag确保相关键在同一槽位
MGET user:{1001}:profile user:{1001}:orders
# 方案二:客户端侧聚合
# 对每个键单独发送GET命令,在客户端聚合结果
# 现代Redis客户端(JedisCluster, Lettuce)已自动处理
生产环境运维最佳实践
cluster-node-timeout需要根据网络延迟审慎设置。设置过短会导致网络抖动误判为故障,触发不必要的故障转移;设置过长则故障响应延迟增大。同城双机房部署建议设为5秒,跨地域部署建议10秒以上。
从节点的复制延迟监控同样关键。从节点如果大幅落后主节点的复制偏移量,故障转移后数据丢失量会很大。通过INFO replication命令查看master_repl_offset和slave_repl_offset的差值,差值持续增大需要排查网络带宽或从节点负载问题。
内存碎片率(mem_fragmentation_ratio)在Cluster模式下更容易被忽视,因为运维人员通常只关注单个节点的内存使用。当某个主节点因热点键导致内存碎片率偏高时,需要通过热点键分析(redis-cli –hotkeys)定位问题键,考虑拆分到更多主节点上。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rediscluster-ji-qun-mo-shi-shu-ju-fen-pian-ji-zhi-yu-gu/