新节点是怎么加入集群的?你只对一个节点说了一句 CLUSTER MEET,其它节点怎么知道它?这篇把三个空节点从「互不认识」到「集群 ok」的全过程,按毫秒采样打印出来:握手的几个状态、gossip 的传播延迟、cluster_state 什么时候变 ok,以及握手一个不存在的节点会发生什么。
7380: 已知节点 1 个,cluster_state = fail,current_epoch = 0 7381: 已知节点 1 个,cluster_state = fail,current_epoch = 0 7382: 已知节点 1 个,cluster_state = fail,current_epoch = 0
启动后各自只认识自己:known_nodes = 1,没有槽位所以 cluster_state = fail,current_epoch = 0。
> CLUSTER MEET 127.0.0.1 7381
"OK"
+ 0 ms 7380 眼中的其它节点: {7381: 'handshake/disconnected'}
+ 1 ms 7381 眼中的其它节点: {}
+ 44 ms 7380 眼中的其它节点: {7381: 'handshake/connected'}
+ 45 ms 7381 眼中的其它节点: {7380: 'handshake/disconnected'}
+ 61 ms 7380 眼中的其它节点: {7381: 'master/connected'}
+ 111 ms 7381 眼中的其它节点: {7380: 'master/connected'}0 ms 时 7380 的节点表里出现 handshake/disconnected——还不知道对方的 ID,用一个临时的随机 ID 占位;连上之后是 handshake/connected(44 ms);对方回应后拿到真实 ID 与角色,变成 master/connected(61 ms)。另一端(7381)比 7380 晚一点才认出 7380(111 ms)。整个过程约 111 ms。
> CLUSTER MEET 127.0.0.1 7382 "OK" + 1 ms 7380 认识的节点端口: [7381] + 2 ms 7381 认识的节点端口: [7380, 7382] + 2 ms 7382 认识的节点端口: [] + 18 ms 7382 认识的节点端口: [7381] + 911 ms 7382 认识的节点端口: [7380, 7381] + 1799 ms 7380 认识的节点端口: [7381, 7382] 三个节点互相认识(每个都知道另外两个)用了 1800 ms
只让 7381 去 MEET 7382:7381 立刻认识了两个邻居,7382 认识了 7381(+18 ms);而 7380 与 7382 互相不知道对方。它们通过 gossip(节点之间的心跳消息里附带的「我认识的其它节点」)传播:7382 在 +911 ms 学到了 7380,7380 在 +1799 ms 才学到 7382——比直接握手慢一个数量级(约每秒一轮心跳)。所以新节点只要 MEET 集群里任何一个节点,不需要逐个 MEET;但完全互相认识需要 1–2 秒。这个延迟是这台实验机上的一次测量,不同规模的集群会不同。
7380: known_nodes = 3,cluster_state = fail(还没分槽位),current_epoch = 2
7381: known_nodes = 3,cluster_state = fail(还没分槽位),current_epoch = 2
7382: known_nodes = 3,cluster_state = fail(还没分槽位),current_epoch = 2
7380 的 CLUSTER NODES:
39f34c33 127.0.0.1:7380 myself,master link=connected
cf302e20 127.0.0.1:7382 master link=connected
d0c21949 127.0.0.1:7381 master link=connectedADDSLOTS 后 3031 ms,三个节点 cluster_state 都是 ok;current_epoch = ['2', '2', '2']
三个节点都知道另外两个之后 known_nodes = 3,但 cluster_state 仍是 fail——因为 16384 个槽都没有主库负责。分配槽位后大约 3.0 秒三个节点才都变成 ok(状态更新不是立即的,我没有拆开这 3.0 秒各是什么等待)。
> CLUSTER MEET 127.0.0.1 9 10009 "OK" + 0 ms 出现 handshake 节点:127.0.0.1:9 flags=['handshake'] + 3038 ms handshake 节点消失(被丢弃) 已知节点数: 3
CLUSTER MEET 127.0.0.1 9 10009 之后,节点表里立刻出现一个 handshake 节点,0.0 秒后被丢弃,known_nodes 仍是 3。握手不会永远挂着;这里的时长与 cluster-node-timeout(3000 ms)吻合,我没有改这个配置验证它们的关系。
39f34c330165b63e499c55814be36723f8501706 127.0.0.1:7380@17380,,tls-port=0,shard-id=d52dba1e4e882f599bff8f4a4c556ddd382467dd myself,master - 0 0 1 connected 0-5460 cf302e202014f28a97259c60b48c68c44d78e177 127.0.0.1:7382@17382,,tls-port=0,shard-id=b19ec5df512c0bcc591ba292bb5858cd0044b544 master - 0 1790696844241 2 connected 10923-16383 d0c21949948fdcab4196c6c33845aaa24ff8d60e 127.0.0.1:7381@17381,,tls-port=0,shard-id=6794455ca22c5ba0f936d16e1c1001d5e8de4c6b master - 0 1790696843628 0 connected 5461-10922 vars currentEpoch 2 lastVoteEpoch 0
节点关系写在 nodes.conf:每行 ID 地址@总线端口 角色 主ID ping 时间 pong 时间 configEpoch 链路状态 槽位,最后一行 vars currentEpoch … lastVoteEpoch …。按端口排序三个主库的 configEpoch 是 1、0、2——互不相同(第 77 篇讨论它们怎么分开)。