滚动升级Cassandra集群时出现异DC及非Cassandra节点异常问题
Cassandra跨集群合并与虚假节点问题排查与修复
问题背景
对6节点Cassandra集群(DC1)执行滚动升级时,nodetool status出现异常:
- 显示来自另一个数据中心(DC2)的UN状态节点
- 显示来自不存在的DC3的DN状态非Cassandra节点
DC1与DC2初始部署正常,此前nodetool status无异常,可正常存储数据。集群配置细节:
- DC1使用3个奇数编号节点作为种子,DC2种子节点与DC1完全不同
- DC1与DC2的
cluster_name完全相同,推测这是问题根源
核心疑问
- DC2为何会加入DC1?开发环境如何复现该问题?曾尝试相同
cluster_name的双集群场景,但未触发该问题。 - 为何会显示来自虚假DC的非Cassandra节点?
- 为何问题在滚动升级后才显现,初始部署时无异常?
- 最佳修复方案是什么?
实际命令输出
nodetool status输出
# nodetool status Datacenter: DC1 ========================================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns Host ID Rack UN IP_1_DC_1 4.87 GiB 256 ? aaaaaaaa-ffff-ffff-ffff-gggggggggggg RAC2 UN IP_2_DC_1 6.66 GiB 256 ? bbbbbbbb-ffff-ffff-ffff-gggggggggggg RAC3 UN IP_3_DC_1 5.28 GiB 256 ? cccccccc-ffff-ffff-ffff-gggggggggggg RAC1 UN IP_4_DC_1 9.55 GiB 256 ? dddddddd-ffff-ffff-ffff-gggggggggggg RAC2 UN IP_5_DC_1 6.32 GiB 256 ? eeeeeeee-ffff-ffff-ffff-gggggggggggg RAC1 UN IP_6_DC_1 6.47 GiB 256 ? ffffffff-ffff-ffff-ffff-gggggggggggg RAC3 Datacenter: DC3 ========================================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns Host ID Rack DN IP_1_DC_3 11.99 GiB 256 ? gggggggg-ffff-ffff-ffff-gggggggggggg RAC3 DN IP_2_DC_3 12.66 GiB 256 ? hhhhhhhh-ffff-ffff-ffff-gggggggggggg RAC1 DN IP_3_DC_3 12.57 GiB 256 ? iiiiiiii-ffff-ffff-ffff-gggggggggggg RAC2 DN IP_4_DC_3 12.63 GiB 256 ? jjjjjjjj-ffff-ffff-ffff-gggggggggggg RAC2 DN IP_5_DC_3 13.1 GiB 256 ? kkkkkkkk-ffff-ffff-ffff-gggggggggggg RAC3 Datacenter: DC2 ========================================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns Host ID Rack UN IP_1_DC_2 14.92 GiB 256 ? llllllll-ffff-ffff-ffff-gggggggggggg RAC1 UN IP_2_DC_2 9.08 GiB 256 ? mmmmmmmm-ffff-ffff-ffff-gggggggggggg RAC2 UN IP_3_DC_2 8.8 GiB 256 ? nnnnnnnn-ffff-ffff-ffff-gggggggggggg RAC2 UN IP_4_DC_2 10.26 GiB 256 ? oooooooo-ffff-ffff-ffff-gggggggggggg RAC3 UN IP_5_DC_2 9.59 GiB 256 ? pppppppp-ffff-ffff-ffff-gggggggggggg RAC1 UN IP_6_DC_2 10.75 GiB 256 ? qqqqqqqq-ffff-ffff-ffff-gggggggggggg RAC3 Note: Non-system keyspaces don't have the same replication settings, effective ownership information is meaningless
nodetool describecluster输出
# nodetool describecluster Cluster Information: Name: DSE-Cassandra-same-name Snitch: org.apache.cassandra.locator.GossipingPropertyFileSnitch DynamicEndPointSnitch: enabled Partitioner: org.apache.cassandra.dht.Murmur3Partitioner Schema versions: aaaaaaaa-cccc-cccc-cccc-bbbbbbbbbbbb: [IP_1_DC_1, IP_2_DC_1, IP_3_DC_1, IP_4_DC_1, IP_5_DC_1, IP_6_DC_1, IP_1_DC_2, IP_2_DC_2, IP_3_DC_2, IP_4_DC_2, IP_5_DC_2, IP_6_DC_2] UNREACHABLE: [IP_1_DC_3, IP_2_DC_3, IP_3_DC_3, IP_4_DC_3, IP_5_DC_3]
预期输出
# nodetool status Datacenter: DC1 ========================================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns Host ID Rack UN IP_1_DC_1 4.87 GiB 256 ? aaaaaaaa-ffff-ffff-ffff-gggggggggggg RAC2 UN IP_2_DC_1 6.66 GiB 256 ? bbbbbbbb-ffff-ffff-ffff-gggggggggggg RAC3 UN IP_3_DC_1 5.28 GiB 256 ? cccccccc-ffff-ffff-ffff-gggggggggggg RAC1 UN IP_4_DC_1 9.55 GiB 256 ? dddddddd-ffff-ffff-ffff-gggggggggggg RAC2 UN IP_5_DC_1 6.32 GiB 256 ? eeeeeeee-ffff-ffff-ffff-gggggggggggg RAC1 UN IP_6_DC_1 6.47 GiB 256 ? ffffffff-ffff-ffff-ffff-gggggggggggg RAC3
问题解答
1. DC2为何加入DC1?如何复现?
Cassandra集群的核心识别标识是cluster_name,当两个集群cluster_name相同时,Gossip协议会认为它们属于同一集群。初始部署时未触发,可能是因为两个集群的网络隔离(比如防火墙限制Gossip端口7000/7001),或者种子节点未交叉指向,但滚动升级过程中,可能出现节点重启后临时的网络连通性变化,或者节点启动时意外发现了对方集群的节点,通过Gossip同步后合并。
复现步骤:
- 搭建两个独立集群,设置相同
cluster_name,使用GossipingPropertyFileSnitch - 确保两个集群网络互通(开放7000/7001端口)
- 对其中一个集群执行滚动升级,逐个重启节点,观察
nodetool status是否出现对方集群节点
2. 为何显示虚假DC3的非Cassandra节点?
这些节点是之前某个集群残留的Gossip元数据。可能是DC1曾与某个已销毁的集群(使用DC3标识)有过Gossip交互,元数据保存在本地系统表中。滚动升级时节点重启,加载了旧的Gossip数据,而由于这些节点已不可达,所以显示为DN状态。
3. 为何滚动升级后才显现?
初始部署时,两个集群的Gossip网络可能未连通(比如防火墙规则、节点启动顺序导致未发现对方)。滚动升级过程中,节点重启会重新发起Gossip探测,若此时网络连通性允许(比如临时开放了端口,或者路由变化),就会发现对方集群节点,触发合并。另外,升级过程中Cassandra版本变化可能导致Gossip协议行为调整,更容易发现跨集群节点。
4. 最佳修复方案
方案步骤:
- 立即隔离两个集群:关闭DC1和DC2之间的Gossip端口(7000/7001),防止进一步的元数据同步
- 修改其中一个集群的
cluster_name:- 停止目标集群的所有节点
- 修改
cassandra.yaml中的cluster_name为新值 - 启动节点时,添加参数
-Dcassandra.allow_cluster_name_change=true(仅在启动时生效,用于覆盖系统表中存储的旧集群名称) - 验证
nodetool describecluster显示新的集群名称
- 清理虚假DC3节点:
- 在DC1的所有节点上执行
nodetool removenode <host_id>,移除DC3的所有节点ID - 或者重启节点时使用
-Dcassandra.reset_gossip=true,重置Gossip元数据(会暂时影响集群稳定性,需在维护窗口执行)
- 在DC1的所有节点上执行
- 验证集群状态:执行
nodetool status确认仅显示DC1节点,nodetool describecluster无异常节点
注意:修改cluster_name需要停机维护,需提前做好备份,选择业务低峰期执行。
内容的提问来源于stack exchange,提问作者FaresDZ
相关产品推荐
相关产品推荐

