秋招在即,大家背八股的时候,心里会不会有些疑惑。集群模式中的槽,如果遇到节点挂掉?新增节点?的时候 会触发怎样的场景?

一、Redis 集群模式与槽的关系

  • 槽的定义
    • Redis 集群将整个 key 空间(2^32)划分成 16384 个 slot。
    • 每一个 key 通过 CRC16(key) % 16384 算出它属于哪个 slot。
    • 这些 slot 分布在不同的节点上,由节点来管理。
  • 为什么要有槽
    • 槽是 逻辑分片的中间层,避免直接绑定 key 到节点。
    • 好处是:增加/减少节点时,只需迁移 slot,不用一个个迁移 key。

二、槽迁移的典型场景

  • 新增节点
    • 集群本来有 N 个节点,槽分布均匀。
    • 现在加了一个新节点,为了让它分担数据,就需要 把部分槽迁移到新节点。
  • 节点宕机 / 下线
    • 如果是从节点宕机,影响不大,可以通过重新同步。
    • 如果是主节点宕机且没有可用从节点,会导致一部分槽不可用。
    • 如果修复后恢复节点,可能需要重新迁移槽。
  • 负载均衡
    • 某些节点压力过大(存的数据多/访问频繁),需要迁移部分槽到负载较轻的节点上。

三、槽迁移的工作机制

  • 槽的状态
    • stable:槽正常工作。
    • migrating:槽正在从本节点迁移到其他节点。
    • importing:槽正在被其他节点迁入。
    • node:槽已属于该节点。
  • 迁移的核心操作
    • 标记槽迁移:源节点标记该槽为 migrating,目标节点标记该槽为 importing。
    • 迁移 key:源节点逐个将槽中的 key 用 MIGRATE 命令迁移到目标节点。
      MIGRATE 会把 key 及其 TTL 一并传输到目标节点,并从源节点删除。
    • 更新槽分配:当该槽下所有 key 都迁移完成,整个集群会更新槽映射表,槽正式属于目标节点。
  • 迁移过程中的访问
    • 如果客户端在迁移过程中访问了槽的 key:
      • 源节点会返回 ASK 重定向,提示客户端去目标节点查询。
      • 客户端收到 ASK 后,会先向目标节点发送 ASKING,再发送实际命令。
    • 因此迁移期间客户端仍然可以读写,只是有短暂的重定向。

四、槽迁移的详细步骤(以新增节点为例)

假设原来有 3 个节点(A、B、C),现在新增 D 节点:

  • 使用 redis-cli --cluster reshard 工具执行槽迁移:
    • 指定迁移的目标节点(D)。
    • 指定要迁移多少槽(比如 5000 个)。
    • 从源节点(A、B、C)平均取一些槽分配给 D。
  • 工具会自动执行:
    • 标记 A、B、C 中对应的槽为 migrating,D 中对应槽为 importing。
    • 循环迁移槽中的 key(逐个调用 MIGRATE)。
    • 完成后,更新槽映射表,让 D 正式接管这些槽。
  • 客户端视角:
    • 在迁移期间访问数据时,可能会收到 ASK 重定向。
    • 迁移完成后,D 节点接管槽,客户端路由表更新。

五、槽迁移中的异常情况

  • 源节点宕机
    • 如果源节点在迁移中宕机,部分 key 没迁完。
    • 目标节点仍然处于 importing 状态,这会导致某些 key 访问出错。
    • 修复办法:手动重新迁移剩余的 key,或者使用 redis-cli --cluster fix 工具修复槽分配。
  • 目标节点宕机
    • 如果目标节点宕机,迁移任务会中断。
    • 源节点仍然在 migrating 状态。
    • 恢复后需要重新导入。
  • 迁移失败/中断
    • 可以通过 CLUSTER SETSLOT 手动调整槽的状态。
    • 比如:CLUSTER SETSLOT <slot> NODE <node_id> 强制指定槽属于某个节点。

六、槽迁移工具

  1. redis-cli --cluster reshard
    • 官方推荐,自动化操作。
  1. 手动迁移(更灵活但麻烦):
    • CLUSTER SETSLOT <slot> MIGRATING <target_id>
    • CLUSTER SETSLOT <slot> IMPORTING <source_id>
    • MIGRATE 一个个迁移 key。
    • CLUSTER SETSLOT <slot> NODE <target_id> 完成分配。

更多推荐