Redis 集群 是指将多个 Redis 实例组合起来,形成一个具备分布式存储、高可用性、读写分离和自动故障转移能力的系统。随着业务数据量的增长和并发压力的提升,单个 Redis 实例的内存、CPU、网络带宽往往会成为瓶颈。Redis 集群通过将数据分散到多个节点(分片)上,并为每个分片配备副本,从而解决单点故障和扩展性问题,确保 Redis 服务的持续稳定运行。

核心思想:
Redis 集群旨在提供横向扩展高可用的能力,通过数据分片解决容量和性能瓶颈,通过主从复制故障转移确保持续可用。


一、为什么需要 Redis 集群?

单个 Redis 实例在实际生产环境中存在以下局限性:

  1. 内存容量限制:单个 Redis 实例的所有数据都存储在一台服务器的内存中,随着数据量的不断增长,最终会达到硬件内存的上限。
  2. 处理能力限制 (CPU/网络):单个 Redis 实例只能利用一台服务器的 CPU 核心和网络带宽。在高并发读写场景下,可能会遇到性能瓶颈。
  3. 单点故障 (Single Point of Failure, SPOF):如果单个 Redis 实例所在的服务器宕机,整个服务将不可用,导致数据丢失和业务中断。

Redis 集群旨在解决这些问题,提供:

  • 高可用性 (High Availability):通过主从复制和故障转移机制,当部分节点出现故障时,集群仍能继续对外提供服务。
  • 水平扩展 (Horizontal Scalability):通过将数据分布到多个 Redis 节点上,突破单个服务器的内存和并发限制,实现容量和性能的线性扩展。
  • 读写分离 (Read/Write Splitting):可以将读请求分流到从节点,减轻主节点的压力,提高读操作的吞吐量。
  • 自动分片 (Automatic Sharding):数据自动分配到集群中的不同节点,客户端无需关心数据存储在哪台服务器上。

二、Redis 集群的两种常见模式

Redis 提供了两种主要的集群解决方案:主从复制 + Sentinel (哨兵) 模式和 Redis Cluster (官方原生集群) 模式。

2.1 主从复制 + Sentinel 模式 (高可用而非分片)

核心特点
这种模式主要解决了 Redis 的高可用性问题,通过主从复制实现数据冗余,并通过 Sentinel 自动进行故障转移,但不提供数据分片能力。所有数据都存储在主节点及其从节点上。

2.1.1 主从复制 (Replication)

  • 工作原理:一个 Redis 实例作为主节点 (Master),可以有一个或多个从节点 (Slave)。主节点负责处理写操作,从节点异步复制主节点的数据,处理读操作。
  • 优点
    • 数据冗余:从节点保存了主节点的数据副本,提高了数据的安全性。
    • 读写分离:可以将大量的读请求分发到从节点,减轻主节点的压力。
  • 缺点
    • 不具备自动故障转移:主节点宕机后,需要手动将一个从节点提升为新的主节点。
    • 写操作瓶颈:所有写操作仍然集中在主节点,无法水平扩展写能力。
    • 内存瓶颈:所有数据都存储在主节点上,无法水平扩展存储容量。

2.1.2 Redis Sentinel (哨兵)

  • 工作原理:Sentinel 是一个独立的分布式系统,用于监控 Redis 主从实例,并在主节点发生故障时自动进行故障转移 (Failover)
    • 监控 (Monitoring):Sentinel 不断检查主节点和从节点是否按预期工作。
    • 通知 (Notification):当被监控的 Redis 实例发生故障时,Sentinel 可以通过 API 向管理员或其他应用程序发送通知。
    • 自动故障转移 (Automatic Failover):当主节点失效时,Sentinel 会自动将一个健康的从节点提升为新的主节点,并配置其他从节点去复制新的主节点。
    • 配置提供者 (Configuration Provider):客户端可以通过 Sentinel 获取当前主节点的地址。
  • 优点
    • 提供了主从模式下的自动故障转移能力,大大提高了 Redis 的可用性。
    • 客户端无需手动切换主节点,由 Sentinel 负责维护主节点信息。
  • 缺点
    • 不解决容量和写性能瓶颈:所有数据仍在一主多从上,写操作仍由单主处理。
    • 部署维护相对复杂:需要独立部署 Sentinel 实例,且 Sentinel 自身也需要满足高可用(至少 3 个 Sentinel 实例)。

2.2 Redis Cluster 模式 (官方原生集群,分片+高可用)

核心特点
Redis 3.0 引入的官方原生解决方案,旨在提供高可用性数据分片。它允许将数据自动分布到多个 Redis 节点上,并提供自动的故障转移。

2.2.1 数据分片 (Sharding) - Hash Slot

  • 槽 (Slot):Redis Cluster 将所有数据划分为 16384 个哈希槽 (Hash Slots)。集群中的每个主节点负责一部分哈希槽。

  • 键到槽的映射:当客户端存储一个键值对时,Redis 会使用 CRC16 算法计算键的哈希值,然后对 16384 取模,得到该键所属的哈希槽。

    1
    slot = CRC16(key) % 16384
  • 分配与迁移

    • 集群启动时,所有 16384 个槽会均等地分配给集群中的主节点。
    • 当需要增减节点时,集群可以在不停机的情况下,通过槽迁移 (Slot Migration) 将槽从一个节点迁移到另一个节点。
  • 优点

    • 水平扩展:通过增加节点来扩展存储容量和读写性能。
    • 自动分片:客户端无需关心数据具体存在哪个节点,只需连接集群中的任意一个节点即可。

2.2.2 高可用性 - 主从复制与自动故障转移

  • 主从结构:Redis Cluster 中,每个主节点都可以拥有一个或多个从节点。从节点是主节点的精确副本。
  • 故障检测:集群中的每个节点都会通过发送 PING 包来检测其他节点的健康状态。当某个节点长时间未响应或大多数其他节点认为其宕机时,则标记为 FAIL
  • 故障转移:当一个主节点被标记为 FAIL 后,其从节点中会通过选举 (Raft 算法的简化版) 选出一个新的主节点,接替失败的主节点继续处理请求。
  • 投票机制:集群中超过半数的主节点同意,才能触发故障转移。

2.2.3 客户端与集群的交互

  • 重定向 (Redirection):客户端连接集群中的任意一个节点。当客户端请求的 key 不在该节点负责的哈希槽上时,该节点会返回一个 MOVED 重定向错误,告诉客户端该 key 位于哪个节点。
  • Smart Client (智能客户端):现代 Redis 客户端库(如 Jedis, Redisson)通常是 “Smart Client”。它们会缓存哈希槽到节点的映射关系。当收到 MOVED 重定向时,会更新本地缓存,并在后续请求中直接连接到正确的节点,避免不必要的重定向。

2.2.4 Redis Cluster 的架构

2.2.5 优点

  • 自动分片和扩容:数据自动分布,轻松增加或减少节点,实现存储和性能的水平扩展。
  • 高可用性:自动故障转移,当部分节点故障时,集群仍能保持可用。
  • 去中心化:集群中的每个节点都存储集群的元数据,无需额外的中心化组件(如 Sentinel)来管理集群状态。
  • 灵活性:支持在线动态添加和移除节点。

2.2.6 缺点

  • 哈希槽限制:16384 个哈希槽的设计在某些极端场景下可能不足。
  • 不保证强一致性:由于是异步复制,在主从切换时,可能会有少量数据丢失。
  • 不支持多数据库:Redis Cluster 只支持 DB 0,不支持切换数据库。
  • 复杂事务和操作受限:不支持跨槽的事务 (Multi/Exec) 和一些多 key 操作(如 MSET/MGET 必须操作相同哈希槽的 key)。需要通过 Hash Tag 来将相关 key 强制分配到同一个槽。
  • 部署和运维相对复杂:虽然比 Sentinel 简单,但仍需要一定的配置和管理。

三、部署 Redis Cluster

部署 Redis Cluster 通常需要至少 6 个 Redis 实例 (3 主 3 从),以确保高可用性。

基本步骤:

  1. 准备节点:在不同的服务器或一台服务器上运行多个 Redis 实例,每个实例配置独立的端口(如 7000, 7001, …, 7005)。

  2. 配置 Redis 实例:每个实例的 redis.conf 需要配置:

    1
    2
    3
    4
    5
    6
    7
    8
    port 7000 # 不同的端口
    cluster-enabled yes # 开启集群模式
    cluster-config-file nodes-7000.conf # 集群配置文件,自动生成和维护
    cluster-node-timeout 15000 # 节点超时时间
    appendonly yes # 推荐开启持久化
    daemonize yes # 后台运行
    pidfile /var/run/redis_7000.pid
    logfile "/var/log/redis_7000.log"
  3. 启动所有 Redis 实例

    1
    2
    3
    redis-server /path/to/redis_7000.conf
    redis-server /path/to/redis_7001.conf
    # ...
  4. 创建集群:使用 redis-cli --cluster create 命令。

    1
    2
    3
    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
    • --cluster-replicas 1 表示每个主节点有一个从节点。上述命令会创建 3 个主节点 (7000, 7001, 7002) 和 3 个从节点 (7003, 7004, 7005),每个主节点会分配一个从节点。
    • redis-cli 会自动将 16384 个槽分配给主节点,并配置从节点。
  5. 验证集群

    1
    2
    redis-cli -c -p 7000 cluster info
    redis-cli -c -p 7000 cluster nodes
    • -c 参数表示启用集群模式,客户端会自动处理重定向。

四、Redis 集群的最佳实践与注意事项

  1. 节点数量:为了保证高可用性,Redis Cluster 至少需要 3 个主节点,每个主节点至少配备一个从节点 (即最小 6 个节点)。

  2. 哈希标签 (Hash Tag):如果某些键之间存在逻辑关联,需要执行跨键操作(如 MSETMGET 或事务),可以使用 Hash Tag 将它们强制分配到同一个哈希槽。

    1
    2
    {user100}:profile
    {user100}:orders

    Redis 只会对 "{}" 中的内容计算哈希值,确保 user100:profileuser100:orders 会位于同一个槽。

  3. 客户端选择:务必使用支持 Redis Cluster 协议的智能客户端,它们能自动处理 MOVED 重定向。

  4. 集群扩容与缩容:Redis Cluster 支持在线扩容和缩容,通过 redis-cli --cluster add-node, del-node, reshard 等命令进行操作。

  5. 数据一致性:Redis Cluster 的主从复制是异步的,在主节点故障转移时,可能会丢失少量未同步到从节点的数据。对于数据一致性要求极高的场景,需要业务层进行补偿或使用其他更强一致的分布式方案。

  6. 网络分区 (Network Partition):当发生网络分区时,集群中的部分节点可能无法与其他节点通信。Redis Cluster 采用多数派原则 (cluster-require-full-coverage 默认为 yes,当有槽不可用时整个集群停止服务;可以设置为 no,允许部分槽可用时继续服务)。

  7. 内存与持久化

    • 每个 Redis 节点都应该独立开启持久化 (RDB / AOF),以防止节点重启时数据丢失。
    • 注意内存限制,避免单个节点内存过大导致 fork 阻塞时间过长。

五、总结

Redis 集群是解决 Redis 单点故障和扩展性瓶颈的强大方案。主从复制 + Sentinel 模式适用于解决高可用性和读写分离的场景,但不提供数据分片。Redis Cluster 模式作为官方原生方案,则提供了自动分片和故障转移,能够实现存储容量和读写性能的水平扩展,是支撑大规模、高并发业务的理想选择。

选择哪种集群模式取决于具体的业务需求:

  • 如果你的 Redis 实例数据量不大,但对高可用性有要求,可以选择 主从复制 + Sentinel 模式。
  • 如果你的 Redis 数据量巨大,或并发读写压力很高,需要数据分片和水平扩展,那么 Redis Cluster 是更合适的选择。

无论选择何种模式,深入理解其工作原理、优缺点以及配置管理,对于构建稳定、高性能的 Redis 服务至关重要。