Redis Cluster 详解

188 阅读5分钟

Redis Cluster是Redis的分布式方案,通过16384个哈希槽分片数据,支持高可用与自动故障转移,基于Gossip协议通信,客户端通过MOVED/ASK重定向访问,适用于大规模场景。

Redis Cluster 是 Redis 官方提供的分布式解决方案,支持 数据分片高可用自动故障转移。它通过将数据分散到多个节点,突破单机内存与性能限制,适用于大规模数据场景。

一、核心概念与架构

1. 数据分布

  • 哈希槽(Hash Slot) : Redis Cluster 将数据划分为 16384 个槽,每个键通过 CRC16 算法计算哈希值,再取模映射到具体槽:

    slot = CRC16(key) % 16384
    
  • 槽分配: 每个主节点负责一部分槽(如 Node1 负责 0-5000,Node2 负责 5001-10000 等)。

    # 查看槽分配
    CLUSTER SLOTS
    

2. 节点角色

  • 主节点(Master) :负责处理读写请求及槽管理。
  • 从节点(Replica) :复制主节点数据,主节点故障时替代为主节点。

3. 高可用

  • 每个主节点至少有一个从节点(推荐一主一从)。
  • 主节点故障时,从节点自动升级为新主节点。

二、搭建 Redis Cluster

1. 最小集群配置(6节点:3主3从)

  1. 节点配置: 每个节点的 redis.conf 中启用集群模式:

    port 7000
    cluster-enabled yes
    cluster-config-file nodes-7000.conf
    cluster-node-timeout 5000
    
  2. 启动节点

    redis-server redis-7000.conf
    # 重复启动 7001~7005 节点
    
  3. 创建集群: 使用 redis-cli 自动分配槽:

    redis-cli --cluster create \
      127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
      127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
      --cluster-replicas 1
    
  4. 验证集群状态

    redis-cli -p 7000 CLUSTER INFO
    redis-cli -p 7000 CLUSTER NODES
    

三、节点通信与请求路由

1. Gossip 协议

  • 节点间通过 PING/PONG 消息交换状态(节点存活、槽分配等)。
  • 每个节点维护全量节点元数据,每秒随机选择部分节点通信。

2. 客户端路由

  • MOVED 重定向:客户端访问错误槽时,返回正确节点地址。

    GET key
    # 返回 MOVED 1234 127.0.0.1:7001
    
  • ASK 重定向:槽迁移期间临时重定向到目标节点。

  • Smart Client:客户端缓存槽与节点映射,直接访问正确节点。


四、故障转移与恢复

1. 故障检测

  • 节点间通过心跳检测状态,若主节点超时(cluster-node-timeout),标记为 PFail(可能下线)
  • 多数主节点确认后,标记为 Fail(确认下线)

2. 从节点晋升

  • 从节点发起选举(基于 Raft 协议),获得多数主节点投票后升级为主节点。
  • 更新集群元数据,同步新主节点信息。

五、扩容与缩容

1. 扩容流程

  1. 添加新节点

    redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
    
  2. 分配槽

    redis-cli --cluster reshard 127.0.0.1:7000
    # 输入迁移槽数量及目标节点ID
    
  3. 添加从节点

    redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id <master-id>
    

2. 缩容流程

  1. 迁移槽:将待删除节点的槽迁移到其他节点。

  2. 删除节点

    redis-cli --cluster del-node 127.0.0.1:7000 <node-id>
    

六、客户端实现

1. Smart Client 逻辑

  1. 初始化时获取集群槽分布(CLUSTER SLOTS)。
  2. 计算 Key 的槽并缓存槽-节点映射。
  3. 遇到 MOVED 错误时更新缓存。

2. 示例(Python redis-py-cluster)

from rediscluster import RedisCluster

startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)

rc.set("key", "value")
print(rc.get("key"))  # 输出 "value"

七、优缺点分析

优点缺点
自动分片,支持水平扩展不支持多数据库(仅 DB0)
内置高可用,故障自动转移跨槽事务受限(需所有 Key 在同一槽)
无中心节点,去中心化架构批量操作需确保 Key 在同一槽(如 MGET
兼容大部分 Redis 命令集群规模过大时 Gossip 通信开销增加

八、运维实践

1. 监控与告警

  • 关键指标

    • 节点状态:cluster_statecluster_slots_assigned
    • 内存与延迟:used_memorylatency
  • 工具

    • redis-cli --cluster check:检查集群健康状态。
    • Prometheus + Grafana:监控集群指标。

2. 数据备份

  • RDB 备份:在每个节点配置 save 或手动执行 BGSAVE
  • AOF 备份:启用 appendonly yes,定期备份 AOF 文件。

3. 热点 Key 处理

  • 拆分 Key:将热点 Key 分片到多个槽(如 user:{1000}:profileuser:1000:profile_{1,2,3})。
  • 本地缓存:客户端缓存热点数据,减少集群压力。

4. 安全配置

  • 密码认证:所有节点配置 requirepassmasterauth

  • 禁用危险命令

    rename-command FLUSHDB ""
    rename-command CONFIG "HIDDEN_CONFIG"
    

九、常见问题与解决方案

问题原因解决方案
集群节点无法启动端口冲突或配置文件错误检查端口占用,验证配置文件
槽未完全分配节点未正确加入集群使用 redis-cli --cluster fix 修复
客户端频繁 MOVED 重定向槽映射缓存未更新客户端实现自动重试与缓存刷新
网络分区导致脑裂主节点间通信中断配置 cluster-require-full-coverage no 允许部分写入

总结

Redis Cluster 是构建大规模、高可用 Redis 服务的核心方案,适用于以下场景:

  • 数据量超过单机内存容量。
  • 需要高可用与自动故障转移。
  • 业务允许跨槽操作限制(如事务、Lua 脚本)。

通过合理设计分片策略、监控集群状态,并遵循最佳实践,可充分发挥 Redis Cluster 的优势。