ScyllaDB 节点数据卷丢失后的重建(Rebuild Node)完全指南
【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb
导读
在 AWS EC2 等云环境中使用 ScyllaDB 时,若采用 i3 / i2 等实例类型,数据存放在易失的临时 SSD(ephemeral SSD)上,节点一旦停止并重启,本地数据就会全部丢失。本文基于官方运维手册的 rebuild-node.rst 文档,完整讲解如何在数据卷丢失后通过replace_node_first_boot参数让节点从集群其他副本重新同步数据并恢复服务,同时结合源码深入剖析该机制的工作原理,让你不仅会操作,还明白它为什么安全、可靠。
为什么 i3 / i2 实例上的节点重启会丢数据
ScyllaDB 官方在 rebuild-node.rst 中明确指出:在 EC2 上运行 ScyllaDB 时,推荐使用 i3 类型实例,把数据存放在快速、易失的临时 SSD 上。这类实例的临时卷(instance store)生命周期与实例本身绑定——无论是停止(stop)、休眠(hibernate)还是终止(terminate)实例,其上承载的应用和数据都会被清除。这一特性不仅适用于 i3,i2 类型实例同样如此。
因此,只要节点被停止后再次启动,该节点上的本地数据就已全部丢失,这是云上使用临时存储的固有代价,而非故障。理解这一点是正确执行重建流程的前提。
重建的底气:高可用与副本机制
数据丢了之所以还能无损恢复,核心在于 ScyllaDB 是分布式高可用(HA)数据库:每个分区(partition)的数据都会按复制因子(Replication Factor,RF)复制到多个节点上。正因为存在副本,ScyllaDB 官方才强烈建议每个数据中心至少使用RF = 3的复制因子,例如:
- 单数据中心:1 DC,RF = 3;
- 双数据中心:2 DC,RF = 6(每个 DC 各 3 份)。
这样即使某个节点因临时卷被清空而丢失全部本地数据,其余节点仍持有完整副本,数据可以从副本流式(stream)回该节点。相关文档见 replace-dead-node.rst。
操作前必读:replace_node_first_boot参数详解
重建流程的核心是配置参数replace_node_first_boot。在仓库源码中,该参数在 db/config.cc 中定义,并在 db/config.hh 声明:
, replace_node_first_boot(this, "replace_node_first_boot", value_status::Used, "", "The Host ID of a dead node to replace. If the replacing node has already been bootstrapped successfully, this option will be ignored.")从源码注释可以提炼出三个关键事实:
- 参数值为被替换(已丢失数据)节点的 Host ID,即一个 UUID 字符串,而非 IP 地址;
- “first boot”语义:只有在节点首次启动(尚未成功完成 bootstrap)时该参数才生效;如果该节点此前已经成功完成 bootstrap,此配置会被忽略;
- 参数为空字符串(默认值)表示不执行替换/重建逻辑。
源码层面:该参数如何驱动重建逻辑
在 service/storage_service.cc 的is_replacing()方法中,启动时会读取该配置并判断当前节点是否处于“替换”模式:
bool storage_service::is_replacing() { const auto& cfg = _db.local().get_config(); if (!cfg.replace_node_first_boot().empty()) { if (_sys_ks.local().bootstrap_complete()) { slogger.info("Replace node on first boot requested; this node is already bootstrapped"); return false; } return true; } ... }逻辑非常清晰:一旦配置了replace_node_first_boot且节点尚未完成 bootstrap,即判定为替换模式;若已经 bootstrap 完成则忽略该配置并打印日志,避免误操作。
真正执行替换信息收集的是prepare_replacement_info()(service/storage_service.cc),它完成以下工作:
- 解析
replace_node_first_boot的值为 Host ID(utils::UUID); - 通过gossip shadow round与种子节点通信,根据 Host ID 反查出被替换节点的 IP 地址;
- 若在 gossip 中找不到该 Host ID,会直接抛出
Replaced node with Host ID ... not found异常,防止配错值导致集群拓扑异常; - 完成信息收集后重置 endpoint state map,开始正式的替换与数据流式传输。
此外,init.cc 中还会校验:如果被替换节点本身是种子节点(seeds 包含其广播地址),启动会被拒绝,因为此时集群中可能没有可用种子。
值得一提的是,源码中同时保留了旧的replace_address_first_boot和replace_address参数,但会打印弃用警告,提示用户迁移到新的replace_node_first_boot配置项(参见 service/storage_service.cc)。
核心操作:数据卷丢失后的节点重建流程
下面按官方文档 rebuild-node.rst 的步骤逐条展开,并补充每一步的注意事项。
第 1 步:编辑 scylla.yaml,配置 replace_node_first_boot
打开集群配置文件:
sudo vim /etc/scylla/scylla.yaml添加(若不存在)或修改(若已存在)replace_node_first_boot参数,将其值改为该节点重启前的 Host ID:
replace_node_first_boot: 675ed9f4-6564-6dbd-ca08-43fddce952de注意:值必须是 Host ID(UUID 格式),不是 IP 地址。可通过
nodetool status查看各节点的 Host ID 列(详见下文验证章节)。仓库自带配置模板位于 conf/scylla.yaml,实际生产配置为/etc/scylla/scylla.yaml。
第 2 步:停止 ScyllaDB 服务
停止节点上的 ScyllaDB 服务。根据部署方式选择对应命令(官方命令索引见 scylla-commands-stop-index.rst):
支持的操作系统(systemd 部署):
sudo systemctl stop scylla-serverDocker 部署(不停止容器本身,只停止容器内的 Scylla 进程):
docker exec -it some-scylla supervisorctl stop scylla
第 3 步:(多磁盘场景)重新配置 RAID
如果节点上有多块磁盘,需要重新执行 RAID 配置脚本,把临时卷重新组合为 ScyllaDB 可用的 RAID 阵列:
sudo /opt/scylladb/scylla-machine-image/scylla_create_devices该脚本来自 scylla-machine-image 发行包。单块磁盘的节点可跳过此步。
第 4 步:启动 ScyllaDB 服务
启动命令索引见 scylla-commands-start-index.rst:
systemd 部署:
sudo systemctl start scylla-serverDocker 部署(容器已处于运行状态时):
docker exec -it some-scylla supervisorctl start scylla
启动后,节点会以“替换者”身份加入集群,其他存活节点将把属于该 Host ID 的数据流式传输回来。由于数据量取决于集群规模与网络带宽,该过程可能持续较长时间,属正常现象。
第 5 步:还原配置(重要收尾)
数据同步完成后,必须将replace_node_first_boot恢复为原值。官方建议直接注释掉该参数,防止后续误触发替换逻辑:
# replace_node_first_boot: 675ed9f4-6564-6dbd-ca08-43fddce952de结合源码中is_replacing()的实现可以理解为什么必须还原:该参数只在“first boot”时生效,理论上重启一次后即失效,但为了保险起见、避免任何潜在误操作,官方流程仍要求显式还原或注释。
重建与“替换死节点”的关联与区别
本文的“重建(Rebuild)”流程与官方另一篇 替换死节点(Replace a Dead Node) 流程共享同一个核心机制replace_node_first_boot,但适用场景不同:
| 场景 | 处理方式 | 关键差异 |
|---|---|---|
| 本节点临时卷被清空(i3/i2 重启) | 本文的 Rebuild 流程:在原节点上配置replace_node_first_boot后重启 | 保留原节点硬件/IP,恢复原 Host ID 对应数据 |
| 节点彻底故障(如硬件损坏) | Replace 流程:准备新节点,配置replace_node_first_boot指向死节点 Host ID | 新节点接管死节点的数据与拓扑位置 |
两者共同的前置条件(见 quorum-requirement.rst):更新集群拓扑需要集群至少存在 quorum(过半数)可用节点;若 quorum 已丢失,必须先恢复 quorum 才能进行任何拓扑变更。可通过nodetool status检查集群节点状态(命令文档见 status.rst)。
替换死节点流程中还补充了一个与本文高度相关的细节:如果实例重启后公有/私有 IP 发生变化,则不能直接在原节点上重建,而应走完整的 Replace 流程(见 replace-dead-node.rst)。这是因为重建依赖原节点以相同地址重新加入集群。
验证与后续动作
重建完成后,使用nodetool status验证节点是否已恢复正常状态(UN表示 Up/Normal):
Datacenter: DC1 Status=Up/Down State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 192.168.1.201 112.82 KB 256 32.7% 8d5ed9f4-7764-4dbd-bad8-43fddce94b7c B1 UN 192.168.1.202 91.11 KB 256 32.9% 125ed9f4-7777-1dbn-mac8-43fddce9123e B1 UN 192.168.1.203 124.42 KB 256 32.6% 675ed9f4-6564-6dbd-ca08-43fddce952de B1数据流式传输完成前,替换节点不会出现在nodetool status中,此时可用nodetool gossipinfo观察其STATUS:NORMAL状态。重建(而非换新节点)的场景下,节点会以原来的 Host ID 恢复在线。
若你使用的是“替换死节点”流程(新节点接管),官方还建议在替换完成后对被替换节点执行一次nodetool repair确保数据与集群其余节点完全一致;当 Repair Based Node Operations(RBNO) 的 replace 能力启用时,则无需再手动 repair。本仓库的 RBNO 说明文档位于 repair-based-node-operation.rst。
常见问题与最佳实践小结
- 填错 Host ID 会怎样?源码会通过 gossip shadow round 校验 Host ID 是否存在,找不到时直接报错拒绝启动,不会盲目加入集群,避免数据错乱(service/storage_service.cc)。
- 为什么不建议在生产使用 RF = 1 或 2?副本数不足时,节点数据卷丢失将无法从其他副本恢复,等同于数据永久丢失。官方推荐每个 DC 至少 RF = 3。
- 重启后 IP 变了怎么办?走完整的替换死节点流程(新节点),不要直接执行本重建流程。
- 重建耗时多久?取决于需要回流的副本数据量与网络带宽,官方在替换流程中明确说明“该操作可能需要一段时间”,建议预留充足维护窗口。
- 完成后务必还原配置:注释掉或恢复
replace_node_first_boot原值,这是官方流程的最后一步,不可省略。
通过本文的流程与源码剖析,你已掌握 ScyllaDB 在临时存储(i3/i2)场景下应对数据卷丢失的完整重建方法:核心就一句话——用replace_node_first_boot告诉集群“我回来了,请把属于我这个 Host ID 的数据流回给我”,剩下的交给 gossip、流式传输与副本机制完成。
【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考