ScyllaDB 拓扑变更的 Quorum(多数派)要求:原理、节点状态检查与故障恢复
【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb
ScyllaDB 基于 Raft 共识算法管理集群拓扑与 Schema,任何拓扑变更(添加、移除、替换节点,新增数据中心等)都要求集群中至少有"多数派(quorum)"节点在线可用;一旦失去 quorum,必须先恢复才能继续操作。本文以官方文档中的 quorum 要求为骨架,结合仓库内 Raft 架构文档、nodetool status参考页与故障处理指南,讲清 quorum 的底层原理、如何用nodetool status检查节点状态、不同集群规模下的故障场景,以及失去 quorum 后的恢复路径。
一、核心规则:拓扑变更必须满足 Quorum
在 docs/operating-scylla/procedures/cluster-management/_common/quorum-requirement.rst 中,官方给出了两条核心规则:
- 更新集群拓扑(Updating the cluster topology)要求集群中至少有 quorum 数量的节点在线可用;
- 如果 quorum 已经丢失,必须先恢复 quorum,才能执行拓扑变更。
这段文字并非孤立的注意事项,而是被多个拓扑操作流程文档以.. include::方式共同引用的"公共前置条件"(common prerequisite),包括:
- 添加节点到现有集群(扩容)
- 从集群中移除节点(缩容)
- 替换故障节点
- 替换运行中的节点
- 向现有集群新增数据中心
- 替换多个故障节点
也就是说,无论是扩容、缩容、替换还是跨数据中心扩展,quorum 是否满足都是执行任何拓扑操作之前必须核查的第一道门槛。
二、为什么要 Quorum:Raft 共识与一致拓扑管理
要理解这条规则的来源,需要看 docs/architecture/raft.rst 中对 ScyllaDB 使用 Raft 的说明。
ScyllaDB 早期沿袭 Apache Cassandra 的设计,使用 gossip 协议传播拓扑与 Schema 变更、使用 Paxos 提供强一致(LWT)。为了在不牺牲性能的前提下获得更强的确定性一致性,ScyllaDB 引入了Raft 共识算法。Raft 通过先选举出唯一的 leader,再由 leader 负责管理复制日志(replicated log)来实现共识:leader 接受客户端写入的日志条目、将其复制到其他节点,并决定何时可以安全地将条目应用到状态机。
在 ScyllaDB 中,Raft 承担两类关键职责:
- Schema 更新管理:任何 DDL(CREATE / ALTER / DROP TABLE)都先作为条目提交到 Raft 复制日志,一旦存储到大多数副本上,就以完全相同的顺序应用到所有节点,即使发生节点或网络故障也不受影响。这消除了旧 gossip 方案下并发 Schema 更新可能导致的冲突。
- 集群拓扑管理:所有拓扑操作被一致地排序(consistently sequenced),使拓扑更新既快又安全。管理员可以并发触发多个拓扑操作(例如并发 bootstrap 多个节点),由集中协调过程保证拓扑元数据在每一步都在节点间同步。
Raft 共识的本质决定了它天然依赖多数派:docs/architecture/raft.rst中专门有Quorum Requirement一节,明确指出:
Raft requires at least a quorum of nodes in a cluster to be available. If multiple nodes fail and the quorum is lost, the cluster is unavailable for schema updates or topology changes.
因此,quorum-requirement.rst中的规则并不是人为设定的限制,而是Raft 共识算法的直接推论:拓扑变更必须先在复制日志上形成多数派提交,而多数派天然要求"超过一半的成员在线"。
从文档还可得知,一致拓扑变更(consistent topology changes)在 2025.2 及以后版本中是强制启用的(docs/architecture/raft.rst 中的相关说明)。这意味着在新版本中,所有拓扑操作都走 Raft 协调路径,quorum 要求适用于所有集群。可通过两种方式验证一致拓扑变更是否已启用:
- 查询
system.topology表:cqlsh> SELECT upgrade_state FROM system.topology;返回
done表示升级完成;空结果或not_upgraded表示尚未开始升级。 - 通过 HTTP 接口查询:
curl -X GET "http://127.0.0.1:10000/storage_service/raft_topology/upgrade"
三、Quorum 丢失的影响边界:读写在,拓扑变更停
值得注意的是,失去 quorum 并不会让集群完全停止服务。docs/troubleshooting/handling-node-failures.rst 开篇即说明:
ScyllaDB relies on the Raft consensus algorithm, which requires at least a quorum of nodes in a cluster to be available. If one or more nodes are down, but the quorum is live, reads, writes, schema updates, and topology changes proceed unaffected. When the node that was down is up again, it first contacts the cluster to fetch the latest schema and then starts serving queries.
这句话拆分出两层含义:
- quorum 仍在:即使有节点宕机,只要多数派在线,读、写、Schema 更新、拓扑变更全部不受影响;
- quorum 已丢失:数据读写(受数据复制策略影响)仍可能继续,但Schema 变更与拓扑变更不可用;节点恢复上线后,会先联系集群拉取最新 Schema,再开始服务查询。
这一点在 docs/architecture/raft.rst 的网络分区示例中也有呼应:Raft 下发生网络分裂后,集群的多数派一侧可以继续执行 Schema 变更,少数派一侧需要等待重新加入多数派;少数派上的数据操作语句在满足 quorum 要求的前提下可以不受影响地继续。
多数据中心部署的特殊风险
docs/architecture/raft.rst特别提醒了一个容易踩坑的部署形态:
When you have a two-DC cluster with the same number of nodes in each DC, the cluster will lose the quorum if one of the DCs is down.
即两个数据中心、节点数相同的集群,任何一个 DC 整体宕机就会导致整个集群失去 quorum。官方给出的建议是:
- 集群配置三个 DC,保证任一 DC 宕机时集群仍可用;
- 若现有集群是两个同规模 DC,第三个 DC 只需包含一个节点即可恢复多数派优势;
- 这个节点可以配置
join_ring=false并运行在较弱机器上(该选项的说明见 参考文档 目录下的配置参数说明)。
四、用 nodetool status 检查节点状态
quorum-requirement.rst明确指出,检查集群节点状态使用nodetool status命令。该命令的完整说明位于 docs/operating-scylla/nodetool-commands/status.rst。
基本用法
nodetool status若要计算有效的持有量(Owns列),需要传入 keyspace 参数;对于 tablet keyspace,还需传入表名:
nodetool status my_keyspace输出示例与字段解读
Datacenter: datacenter1 ======================= Status=Up/Down/eXcluded |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 127.0.0.1 394.97 MB 256 33.4% 292a6c7f-2063-484c-b54d-9015216f1750 rack1 UN 127.0.0.2 151.07 MB 256 34.3% 102b6ecd-2081-4073-8172-bf818c35e27b rack1 UN 127.0.0.3 249.07 MB 256 32.3% 20db6ecd-2981-447s-l172-jf118c17o27y rack1 XN 127.0.0.4 149.07 MB 256 32.3% dd961642-c7c6-4962-9f5a-ea774dbaed77 rack1表格中的核心字段含义(依据status.rst的参数表):
| 字段 | 含义 |
|---|---|
| Status | U= 节点在线(Up);D= 节点宕机(Down);X= 节点已被排除(excluded) |
| State | N= 正常(Normal);L= 离开(Leaving);J= 加入(Joining);M= 移动(Moving) |
| Address | 节点的 IP 地址 |
| Load | 节点上 ScyllaDB 数据占用的磁盘大小 |
| Tokens | 节点拥有的 token 数量 |
| Owns (effective) | 节点有效持有的数据范围比例 |
| Host ID | 节点的唯一主机标识(拓扑操作中频繁用到) |
| Rack | 节点所在的机架 |
第一列两个字母组合即为"状态+状态",例如:
- UN(Up Normal):节点在线且状态正常——拓扑操作的基本前提;
- UJ(Up Joining):节点正在加入集群(如新节点 bootstrap 期间,其他节点正在向其流式传输数据),见 添加节点文档 中的示例;
- DN(Down Normal):节点宕机但仍是集群成员;
- XN(excluded + Normal):节点已被标记为排除。
在添加节点的操作流程中,官方还给出了典型观察窗口:添加节点文档 要求执行nodetool status确认新节点先处于UJ(Up Joining),流式传输完成后变为UN(Up Normal),随后再对其他节点执行nodetool cleanup清理已迁移出的键。
判定 Quorum 的实操要点
结合 quorum 规则,运维人员的检查套路是:
- 执行
nodetool status,确认输出中所有节点均为UN; - 若存在DN节点,先数一数在线节点数是否仍占多数(quorum);
- 若 quorum 仍在,拓扑变更可安全执行;若 quorum 已丢失,必须先恢复节点再变更拓扑。
五、不同集群规模下的 Quorum 故障场景
docs/troubleshooting/handling-node-failures.rst 用三张表系统性地给出了不同规模集群在节点/DC 故障时的后果与应对动作,这也是判断"是否还有 quorum"的最直接参考:
场景 A:单数据中心 3 节点
| 故障 | 后果 | 应对动作 |
|---|---|---|
| 1 个节点宕机 | Schema 与拓扑更新仍可能且安全 | 尝试重启;若节点已死,替换为新节点 |
| 2 个节点宕机 | 读写可用;Schema 与拓扑变更不可用(quorum 丢失) | 至少重启 1 个宕机节点以恢复 quorum;无法恢复则走手动恢复流程 |
3 节点集群中 quorum 为 2,因此 2 个节点同时宕机即丢失 quorum。
场景 B:双数据中心共 6 节点(每 DC 3 节点)
| 故障 | 后果 | 应对动作 |
|---|---|---|
| 1–2 个节点宕机 | Schema 与拓扑更新仍可能且安全 | 尝试重启;节点已死则替换 |
| 3 个节点宕机 | 读写可用;Schema 与拓扑变更不可用 | 重启 3 个宕机节点中的至少 1 个以恢复 quorum |
| 1 个 DC 整体宕机 | 读写可用;Schema 与拓扑变更不可用 | DC 恢复上线后重启节点;无法恢复则走手动恢复流程 |
注意双 DC 同规模时任一 DC 整体宕机即丢失 quorum,与 Raft 架构文档 的提醒完全一致。
场景 C:三数据中心共 9 节点(每 DC 3 节点)
| 故障 | 后果 | 应对动作 |
|---|---|---|
| 1–4 个节点宕机 | Schema 与拓扑更新仍可能且安全 | 尝试重启;节点已死则替换 |
| 1 个 DC 宕机 | Schema 与拓扑更新仍可能且安全 | DC 恢复后重启节点;节点已死则新增 3 个新节点到新区域 |
| 2 个 DC 宕机 | 读写可用;Schema 与拓扑变更不可用 | DC 恢复后重启节点;无法恢复则走手动恢复流程 |
9 节点集群 quorum 为 5,因此最多允许 4 个节点(不足半个 DC)离线;三 DC 结构天然保证了单 DC 故障不至于突破多数派。
六、Quorum 丢失后的恢复路径
常规恢复:先把节点拉回来
根据handling-node-failures.rst,quorum 丢失后的第一选择永远是恢复宕机节点——重启或修复节点使其重新上线,quorum 即自动恢复,随后才能继续执行拓扑变更。对于确认已永久死亡的节点,使用标准的节点替换流程(或将多个故障节点一起处理,见替换多个故障节点)。
手动恢复流程(多数派永久不可恢复时)
当多数派节点永久故障且无法恢复(例如 3 节点集群中 2 个节点报废)时,文档提供了手动恢复流程(Manual Recovery Procedure,见 docs/troubleshooting/handling-node-failures.rst 的recovery-procedure一节)。其思路是让幸存节点以特殊恢复模式重新初始化 Raft,使故障节点不再参与共识,之后再替换所有故障节点。要点包括:
- 前提:确认"死节点"确实死亡而非被网络分区临时隔离,必要时用防火墙隔离幸存节点与死节点的通信,防止死节点复活干扰恢复过程;
- 对幸存节点执行滚动重启;
- 用
cqlsh查询system.scylla_local中的raft_group0_id与system.raft表中的commit_idx,选出 commit 索引最大的节点作为recovery leader; - 在每个节点重启前,于
scylla.yaml中加入recovery_leader属性并指向 recovery leader 的 host ID,日志中出现Performing Raft-based recovery procedure with recovery leader ...即表示该节点已参与恢复; - 替换所有故障节点后,从各节点
scylla.yaml移除recovery_leader属性,并向 ScyllaDB 进程发送SIGHUP使改动生效; - 最后清理
system.raft、system.raft_snapshots、system.raft_snapshot_config中残留的旧 group 0 数据。
该流程还提醒:若死节点数量大于等于某个 keyspace 的 RF,说明已有数据丢失,恢复完成后需从备份恢复数据。
七、拓扑操作文档中的 Quorum 相关细节
removenode 的 Quorum 与忽略死节点选项
docs/operating-scylla/nodetool-commands/removenode.rst 将 quorum 列为使用该命令的明确前置条件,与quorum-requirement.rst完全一致:
Using
removenoderequires at least a quorum of nodes in a cluster to be available. If the quorum is lost, it must be restored before you change the cluster topology.
同时它给出一个非常实用的补充约束:移除节点后,DC 中剩余节点数必须不低于该 DC 内 keyspace 配置的复制因子(RF),否则请求可能失败,此时应改用节点替换流程。
由于removenode需要集群中所有节点参与数据同步,只要有一个节点不可用操作就会失败。官方提供的配套选项是--ignore-dead-nodes,用逗号分隔的 Host ID 列表显式声明不可用节点:
nodetool removenode --ignore-dead-nodes 8d5ed9f4-7764-4dbd-bad8-43fddce94b7c,125ed9f4-7777-1db0-aac8-43fddce9123e 675ed9f4-6564-6dbd-ca08-43fddce952de注意:removenode只用于永久宕机且无法恢复的节点,运行中的节点必须使用nodetool decommission(见移除节点文档)。
数据迁移与一致性提醒
移除节点文档 还强调,由于removenode依赖流式传输重新分布数据,若数据源不是最新版本,不保证重平衡后数据一致。因此官方要求:执行removenode前确认集群中其他节点全部为 UN、并先执行一次全集群 repair,使所有副本持有最新数据;若操作中途出现节点故障,需重跑 repair 后再执行(启用 Repair Based Node Operations(RBNO) 时除外)。
八、实践小结
围绕"拓扑变更必须满足 quorum"这条规则,可总结出以下可直接落地的运维清单:
- 变更前必查:任何拓扑操作前先执行
nodetool status,确认所有节点为 UN;存在 DN 节点时先计算在线节点是否仍构成多数派; - 丢失即停:quorum 丢失时立即停止一切拓扑变更与 Schema 变更,优先恢复宕机节点(重启、修复、替换);
- 部署形态:优先采用三数据中心部署;双 DC 同规模集群要意识到"任一 DC 宕机即丢 quorum",第三个 DC 可用
join_ring=false的单节点兜底; - 数据安全:
removenode前做全集群 repair,移除后剩余节点数不低于 RF;多数派永久不可恢复时,按手动恢复流程初始化 Raft 并替换故障节点; - 版本意识:2025.2 及以后版本一致拓扑变更为强制启用,可通过
system.topology的upgrade_state或 HTTP 接口确认其状态。
【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考