Skip to content

Redis集群模式

一、Redis集群的核心目标

  1. 水平扩展(Scale Out):通过数据分片将数据分布到多个节点,突破单节点的内存和性能限制(如支持TB级数据存储)。
  2. 高可用性(High Availability):通过复制(Replication)和故障转移(Failover),保证节点故障时服务不中断。
  3. 无中心架构(Decentralized):集群中没有固定的“主节点”,所有节点平等通信,避免单点故障。

二、Redis集群的核心原理

Redis集群的核心设计围绕数据分片节点角色集群通信故障处理四大模块展开,以下是详细拆解:

1. 数据分片:槽(Slot)机制

Redis集群通过**槽(Slot)**实现数据的分布式存储,这是水平扩展的基础。

  • 槽的数量:固定为16384个(2¹⁴),这个数值的选择基于以下考虑:

    • 足够均匀分布数据(16384个槽能覆盖大部分场景的节点数量,如100个节点时每个节点约164个槽);
    • 槽映射信息的传输效率(槽的分布状态用位图表示,16384位仅占2048字节,便于节点间通信);
    • 避免过多槽导致的管理 overhead(如槽迁移的成本)。
  • 数据分配逻辑
    每个键(Key)通过CRC16算法计算哈希值,再对16384取模,得到对应的槽号:

    plaintext
    slot = CRC16(key) % 16384

    每个主节点负责管理一部分槽(如3个主节点时,每个节点约负责5461个槽),所有槽的分布信息由集群维护。

  • 示例
    若键user:100的CRC16哈希值为0x3A98(十进制14992),则14992 % 16384 = 14992,该键属于槽14992,由负责该槽的主节点处理。

2. 节点角色:主从复制(Master-Slave)

Redis集群中的节点分为主节点(Master)从节点(Slave),二者职责明确:

  • 主节点

    • 负责处理槽的读写请求(从节点不处理写请求,仅复制主节点数据);
    • 参与故障检测投票决策(集群的一致性保证)。
  • 从节点

    • 作为主节点的副本,通过异步复制(Asynchronous Replication)同步主节点的数据;
    • 当主节点故障时,晋升为新主节点(故障转移),接管原主节点的槽和服务。
  • 主从架构的意义

    • 高可用性:主节点故障时,从节点快速补位,避免服务中断;
    • 读扩展:从节点可处理读请求(需客户端支持“读偏好”设置),分担主节点的读压力。
  • 配置建议
    集群至少需要3个主节点(保证故障转移时的投票一致性),每个主节点建议配置1-2个从节点(避免单从节点故障导致主节点无副本)。

3. 集群通信:Gossip协议

Redis集群是无中心的,节点间通过Gossip协议(流言协议)交换状态信息,维护集群的一致性视图。

  • Gossip协议的作用
    每个节点定期向随机选择的几个节点发送消息(如PINGPONGMEETFAIL),传递以下信息:

    • 节点状态(在线/离线);
    • 槽的分布情况;
    • 主从关系;
    • 故障信息。
  • 关键消息类型

    • PING:节点向其他节点发送的心跳包,包含自身状态和集群摘要;
    • PONG:收到PING后的响应,确认节点在线;
    • MEET:新增节点时,其他节点向其发送的“加入集群”消息;
    • FAIL:节点标记其他节点为故障时,传播的故障通知。
  • Gossip协议的特点

    • 去中心化:无中心节点,所有节点平等通信;
    • 容错性高:即使部分节点故障,消息仍能通过其他路径传播;
    • 最终一致性:集群状态的更新需要一定时间(取决于消息传播速度),但最终所有节点会达成一致。

4. 故障处理:检测与转移

Redis集群的高可用性依赖故障检测自动故障转移机制,确保主节点故障时快速恢复服务。

  • 故障检测(Fault Detection)
    节点通过心跳机制检测其他节点的状态:

    1. 节点A向节点B发送PING消息;
    2. 若超过cluster-node-timeout(默认15秒)未收到PONG响应,节点A标记节点B为疑似故障(PFail)
    3. 节点A通过Gossip协议将“节点B疑似故障”的信息传播给其他节点;
    4. 大多数主节点(超过半数)都标记节点B为PFail时,节点B被确认为故障(Fail)
  • 故障转移(Failover)
    当主节点故障时,其从节点会自动竞争晋升为新主节点,步骤如下:

    1. 发现故障:从节点定期检查主节点的状态,发现主节点故障后,进入“候选状态”;
    2. 请求投票:候选从节点向集群中的所有主节点发送Vote Request(投票请求),申请晋升为主节点;
    3. 投票决策:主节点收到请求后,若未投过票且候选从节点是合法的(如复制进度足够),则投赞成票;
    4. 晋升主节点:候选从节点获得超过半数主节点的投票(如3个主节点时需2票),则晋升为新主节点;
    5. 接管槽:新主节点更新集群状态,接管原主节点的所有槽,并通过Gossip协议通知其他节点;
    6. 清理旧节点:故障主节点恢复后,会自动成为新主节点的从节点(若未被手动移除)。
  • 故障转移的关键

    • 投票机制:保证故障转移的一致性(避免多个从节点同时晋升);
    • 复制进度检查:候选从节点需同步主节点的大部分数据(避免数据丢失),才能获得投票;
    • 快速恢复:故障转移的时间取决于cluster-node-timeout(默认15秒),通常在20秒内完成。

5. 客户端路由:智能转发

Redis集群的客户端需要知道键对应的槽槽对应的节点,才能正确发送请求。客户端的路由方式分为智能客户端(推荐)和非智能客户端

  • 智能客户端(Smart Client)
    客户端本地维护槽映射表(Slot Map)(如Java的JedisCluster、Python的redis-py-cluster),流程如下:

    1. 客户端启动时,从集群节点获取槽-节点映射表;
    2. 当需要访问键时,计算槽号,查询本地映射表,直接向对应的节点发送请求;
    3. 若槽映射表过时(如槽迁移),节点返回MOVEDASK错误,客户端更新映射表后重新请求。
  • 非智能客户端
    客户端连接任意节点,若该节点负责请求的槽,则处理请求;否则返回MOVED错误,客户端根据错误信息中的节点地址,重新连接正确节点。这种方式效率低(需多次跳转),不推荐。

  • 关键错误类型

    • MOVED永久错误,说明槽已迁移到新节点,客户端需更新本地槽映射表;
    • ASK临时错误,说明槽正在迁移中(如源节点向目标节点复制数据),客户端需向目标节点发送ASKING命令(告知目标节点处理该请求),然后再发送请求(不更新映射表)。

三、Redis集群的局限性

  1. 多键操作限制
    不支持跨槽的多键操作(如MGETMSETDEL key1 key2),因为这些操作需要访问多个节点,无法保证原子性。
  2. 事务限制
    事务(MULTI/EXEC)只能在同一个槽内的键上执行,跨槽事务会失败。
  3. 发布订阅(Pub/Sub)
    消息会发送到所有节点,可能导致重复消费(Redis 5.0+的Stream解决了这个问题)。
  4. 配置复杂度
    集群的搭建、节点添加/删除、槽迁移需要手动或通过工具(如redis-cli --cluster)完成,管理成本高于单节点。

四、Redis集群的搭建流程(简化)

  1. 配置节点:修改每个节点的redis.conf
    ini
    cluster-enabled yes              # 开启集群模式
    cluster-config-file nodes.conf   # 集群配置文件(自动生成)
    cluster-node-timeout 15000       # 节点超时时间(ms)
    port 6379                        # 客户端端口
    bind 0.0.0.0                     # 允许所有IP访问
  2. 启动节点:启动所有配置好的Redis节点。
  3. 创建集群:使用redis-cli --cluster create命令创建集群(指定主节点和从节点比例):
    bash
    redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 \
    --cluster-replicas 1  # 每个主节点对应1个从节点
  4. 验证集群:使用redis-cli -c-c表示集群模式)连接集群,执行cluster info(查看集群状态)、cluster nodes(查看节点信息)。

五、总结:Redis集群的核心逻辑

Redis集群通过槽机制实现数据分片(水平扩展),通过主从复制保证数据冗余(高可用),通过Gossip协议维护集群状态(无中心),通过故障转移实现自动恢复(高可用)。其设计目标是在性能可用性扩展性之间取得平衡,适用于需要大规模存储和高可用的场景(如电商、社交、游戏等)。

关键结论

  • Redis集群是分布式缓存的首选方案(优于Sentinel模式,因为Sentinel仅解决高可用,不解决水平扩展);
  • 集群的水平扩展依赖槽迁移(在线迁移,不影响服务);
  • 集群的高可用性依赖主从复制和故障转移(默认15秒内恢复);
  • 客户端需使用智能客户端(如JedisCluster)以提高性能。