DFLYCLUSTER CONFIG 被拒绝并返回 “Invalid cluster configuration“ 怎么定位?

DFLYCLUSTER CONFIG 被拒绝并返回 "Invalid cluster configuration" 怎么定位?

【免费下载链接】dragonfly A modern replacement for Redis and Memcached 【免费下载链接】dragonfly 项目地址: https://gitcode.com/GitHub_Trending/dr/dragonfly

你在用集群管理器(cluster manager)向 Dragonfly 节点推送集群拓扑时,节点回复了 -ERR Invalid cluster configuration.,配置没有生效。这个错误是 DFLYCLUSTER CONFIG <json> 对一段无法通过解析或校验的集群 JSON 给出的统一拒绝信息,它本身不告诉你具体是哪条规则失败。这篇文章给出定位路径:先确认拒绝后节点处于什么状态,再读服务器日志定位到具体校验项,最后按 docs/cluster-mode.md 中的校验规则逐条核对 JSON、修复后重新推送并验证。

Dragonfly 集群拓扑:16384 个槽位被分配到多个分片,每个分片有一个 master 和若干 replica

适用前提:节点以 --cluster_mode=yes --admin_port=<p> 启动。DFLYCLUSTER 是隐藏的管理员命令,只接受 --admin_port 配置的管理监听器上的连接,客户端监听器会拒绝它。

先确认拒绝对节点意味着什么

被拒绝的配置不会破坏任何状态,这是定位时最重要的背景:

  • 校验在安装之前执行,失败时节点原样保留之前的配置docs/cluster-mode.md §4.2、§4.3)。已迁移中的 slot、已有的数据都不受影响。
  • 如果这是节点启动后收到的第一个配置,节点会继续处于未配置状态:它不拥有任何 slot,所有数据面命令(以及 CLUSTER SHARDS/SLOTS/NODES)返回 -ERR Cluster is not yet configured
  • 如果之前已经装过一个有效配置,节点继续按旧配置服务。此时集群里会出现短暂的状态不一致:这个节点上的 slot 归属还是旧视图,打到该节点上的客户端可能收到过期的 -MOVED。文档明确此时集群管理器必须观察到拒绝并推送修正后的配置(docs/cluster-mode.md §7.4)。

注意区分错误串的精确形态:完整回复是 -ERR Invalid cluster configuration.(末尾带句点,见 src/server/cluster/cluster_family.cc)。它和另外两个容易混淆的错误不同:

  • -ERR Cluster is disabled. Use --cluster_mode=yes to enable. —— 节点没有以真实集群模式运行(未设 --cluster_mode=yes,或处于 emulated 模式),此时 DFLYCLUSTER 整个命令都不可用,不是配置内容的问题。
  • -ERR Cluster is not yet configured —— 数据面命令在首个配置安装前的回复。

准备:拿到定位所需的两个输入

  1. 节点 ID。在任意监听器上执行 CLUSTER MYID 获取本节点身份。配置 JSON 中本节点对应 shard 的 master.id 必须与此一致(它是集群管理器写入 master.idreplicas[].idmigrations[].node_id 的依据)。
  2. 被推送的 JSON 原文。定位问题需要的是集群管理器实际发出的那段 JSON,而不是"应该发"的版本。

定位第一步:用 CLUSTER INFO 判断节点当前状态

在被拒绝的节点上执行:

CLUSTER INFO

根据输出判断节点属于哪种情况(字段取值参考 src/server/cluster/cluster_family_test.cc 中的断言,以下为文档测试示例):

  • 首次配置就失败(节点从未有配置):

    cluster_state:fail
    cluster_slots_assigned:0
    cluster_slots_ok:0
    cluster_known_nodes:0
    cluster_size:0
    

    此时 CLUSTER SHARDSCLUSTER SLOTSCLUSTER NODES 会返回 -ERR Cluster is not yet configured

  • 拒绝的是一次更新CLUSTER INFO 仍显示旧配置的状态(cluster_state:okcluster_slots_assigned:16384 等),说明旧配置仍在服务。这种情况要额外警惕集群内其他节点已应用新配置,拓扑出现分歧。

定位第二步:读服务器日志,锁定具体失败的校验项

校验逻辑集中在 src/server/cluster/cluster_config.ccIsConfigValid 与 JSON 解析函数中。每类失败都会向日志打出一条对应的 ERROR 记录(命令处理侧另有一条 Can't set cluster configWARNING,见 src/server/cluster/cluster_family.cc),日志行直接指明规则。在 Dragonfly 的日志输出中查找与推送时刻对应的行,按下表对照:

日志内容(摘录)含义
Can't parse JSON for ClusterConfig ...整段输入不是合法 JSON
Invalid JSON cluster config: not an array ...顶层必须是 shard 对象组成的 JSON 数组(空数组 [] 也在此之后被拒,因为没有任何 slot 被分配)
Invalid JSON cluster config: slot_ranges is not an array ...字段缺失或类型不符(同类日志还有 invalid id for nodeinvalid ip for nodereplicas is not an arrayinvalid health status for node: ... 等)
Invalid cluster config: some slots were missing.[0, 16383] 中有 slot 没有被任何 shard 覆盖
Invalid cluster config: slot=N was already configured by another slot range.某个 slot 被两个 shard 同时声明
Invalid cluster config: start=X is larger than end=Y某个 slot range 不满足 start <= end
Master <id> appears more than once / Replica <id> appears more than once节点 ID 重复:同一 id 作为 master 出现两次,或作为同一 master 的 replica 出现两次
Invalid cluster config: migration target equals source master=...migrations[] 条目指向源 shard 自己
Invalid cluster config: migration target <id> is not a shard master in the configmigration 目标 id 不是本配置中的某个 master
Invalid cluster config: duplicate migration target <id> in shard master=...同一源 shard 对同一目标有两条 migration(每个节点对至多一条 migration)
Invalid cluster config: empty migration slot_ranges to target ...migration 的 slot_ranges 为空
Invalid cluster config: bad migration slot range ...migration 的 slot range 不合法
Invalid cluster config: migration range ... is not owned by shard master=...migration 的 slot 范围没有完全落在源 shard 的 slot_ranges
Invalid cluster config: overlapping migration ranges ... and ... in shard master=...同一源 shard 上两条 migration 的 slot 范围重叠

完整消息集合以 src/server/cluster/cluster_config.cc 源码为准。日志定位到规则后,回到被推送的 JSON 中找到对应的 shard 或 migration 条目即可。

定位第三步:按校验规则逐条核对 JSON

如果日志不方便查看,可以直接对照 docs/cluster-mode.md §4.1–§4.2 的规则人工核对。一份配置的 JSON 顶层是 shard 数组,每个 shard 包含:

  • slot_ranges:闭区间列表,start <= end,取值 0..16383,所有 shard 的 range 必须恰好覆盖 [0, 16383] 且不重叠。这是最常见的失败原因——少覆盖一段(some slots were missing)或多覆盖一段(was already configured)。
  • masterid(字符串,须与目标节点的 CLUSTER MYID 一致)、ipport(uint16,向客户端通告并嵌入 -MOVED 回复)、可选的 healthonline | loading | fail | hidden,大小写不敏感,缺省 online,见 docs/cluster-node-health.md)。
  • replicas:数组,可为空;字段与 master 相同。注意它只是描述性信息——复制关系要靠 REPLICAOF 单独建立,replicas[] 本身不会让任何节点开始复制。
  • migrations(可选):本 master 向外发起的 slot 迁移,每条含目标 master 的 node_id/ip/port(目标的 admin port)和非空 slot_ranges

规则核对清单(docs/cluster-mode.md §4.2 原文):

  1. 任何 slot 不能被 0 个或多个 shard 拥有;
  2. 节点 id 不能作为两个 master 出现,也不能作为同一 master 的两个 replica 出现;
  3. migration 不能指向自己的源 shard;
  4. migration 目标 id 必须是同一配置中的某个 master;
  5. 同一源 shard 不能有两条目标相同的 migration;
  6. migration 的 slot_ranges 非空、合法、完全包含在源 shard 的 slot_ranges 内、且同一源上不与其他 migration 重叠。

一个最小可验证的单机集群配置形态(结构参考 src/server/cluster/cluster_family_test.cc 中的测试模板,id 替换为本节点 CLUSTER MYID 的实际值,ip/port 替换为实际地址):

[
  {
    "slot_ranges": [
      { "start": 0, "end": 16383 }
    ],
    "master": {
      "id": "<本节点 CLUSTER MYID 的输出>",
      "ip": "10.0.0.1",
      "port": 7000,
      "health": "online"
    },
    "replicas": []
  }
]

修复后重新推送并验证

修正 JSON 后,在管理监听器上重新执行 DFLYCLUSTER CONFIG <json>。成功时回复 +OK(如果新配置与当前配置完全相同,也直接回复 +OK)。然后验证:

CLUSTER INFO

期望看到(单 shard 集群的文档测试示例):

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_known_nodes:1
cluster_size:1

再执行 CLUSTER SHARDSCLUSTER SLOTSCLUSTER NODES,确认返回的拓扑(slot 区间、节点 id、ip、port、health)与配置一致。此前返回 -ERR Cluster is not yet configured 的数据面命令应当恢复正常。

最后确认集群管理器侧的动作闭环(docs/cluster-mode.md §2.2、§7.4):

  • 配置必须推送到所有节点——master 和 replica 都要收到,replica 需要用它来计算 -MOVED 目标。
  • 如果这次拒绝只发生在单个节点上,管理器需要观察到拒绝并对修正后的配置重新推送该节点;在该节点修好之前,集群对 slot 归属的视图是不一致的。
  • 节点重启后不保留集群配置,需要重新推送当前 JSON。

边界与限制

  • DFLYCLUSTER 是隐藏命令,客户端监听器不接受;如果客户端库意外发出该命令,看到的不是本节讨论的拒绝。
  • 如果节点实际没有以 --cluster_mode=yes 启动,收到的会是 -ERR Cluster is disabled. Use --cluster_mode=yes to enable.,那是模式配置问题而非 JSON 问题,先修正启动参数再继续本文流程。
  • 被拒绝的配置不产生任何副作用:旧配置保留、无数据删除动作。slot 删除清扫只在一个有效的新配置把 slot 从节点移除后才发生。

【免费下载链接】dragonfly A modern replacement for Redis and Memcached 【免费下载链接】dragonfly 项目地址: https://gitcode.com/GitHub_Trending/dr/dragonfly

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值