Sui 数据库快照是节点存储在纪元结束时的时间点视图,因此每个快照工件都按纪元寻址,而非任意区块高度。RocksDB 快照保留完整的数据库存储,包括索引和未修剪数据,因此体积更大,但适合提供历史查询的 RPC 节点。正式快照与数据库无关,仅包含纪元结束时的活跃对象集,体积更小、恢复更快,并且可对照委员会签名的纪元承诺进行加密验证,但它们不包含索引,因此不适合历史 RPC。恢复全节点意味着要么将 RocksDB 纪元目录放置在 <db_path>/live,要么使用正确的创世块、网络和存储桶标志运行 sui-tool download-formal-snapshot,然后在路由流量之前确认节点赶上预期纪元和检查点高度。
按纪元分区的快照心智模型
Sui 数据库快照是节点存储在纪元结束时捕获的时间点视图。Sui 是按纪元分区的:纪元是协议中验证者集合变更和重新配置的单位,因此每个快照工件都按纪元寻址,而从不按任意区块高度。这是与 EVM 风格快照和恢复工具最重要的区别,后者操作员通常以区块号思考并回滚到某个高度。在 Sui 上,问题始终是你恢复到哪个纪元,以及你持有的工件是否是委员会为该纪元承诺的那个。
Sui 数据库快照文档是两种工件类型及其恢复流程的权威来源。全节点文档涵盖节点配置、监控和更新,快照生产设置就在那里。数据管理文档解释了修剪和归档存储,并说明了为什么正式快照不适合历史 RPC 节点。请结合本文阅读这三页;此处描述的平台行为在那里有文档记录,而操作建议是我们的。
由于快照按纪元寻址,恢复也是一次链身份检查。你必须知道正在恢复哪个网络(主网、测试网或其他)、该网络使用哪个创世块,以及你打算落在哪个纪元。来自错误网络或过时纪元的快照要么验证失败,要么使节点远远落后于当前纪元,而这两种结果仅从文件列表中都看不出来。
- 快照单位:纪元结束视图,按纪元编号寻址。
- 链身份:网络加创世块必须与快照匹配。
- 恢复目标:达到快照纪元,然后赶上实时网络头部。
正式快照与 RocksDB 快照及其权衡
RocksDB 快照是数据库存储的时间点视图,包括未修剪数据、附加索引以及节点维护的其他数据。它是一个更大的工件,但保留了 RPC 节点回答历史和索引查询所需的索引。正式快照与数据库无关:它仅包含纪元结束时的活跃对象集,即所有有资格作为未来交易输入对象的对象版本集合。它的存储占用小得多,恢复更快,并且由 Sui 协议原生支持,可对照正在恢复的纪元的委员会签名承诺进行加密验证。
生产中最关键的限制已有明确文档:正式快照不适合进行历史数据查找的 RPC 节点,因为它们不包含索引。因此,两种类型之间的选择由任务决定,而不是由工件大小决定。验证者和状态同步全节点可以从正式快照启动。必须提供历史读取和索引查询的节点则不能;它需要 RocksDB 工件或自行重建索引的完整同步。
这与Sui 归档节点和历史 RPC中描述的操作划分相同:归档和历史服务角色依赖于保留的数据和索引,而状态同步参与者只需要活跃对象集来向前验证。如果你仍在决定节点应暴露哪个接口,Sui 全节点 RPC 端点设置指南涵盖绑定和配置,Sui gRPC 指南涵盖较新的查询接口。
- RocksDB 快照:完整存储视图,包含索引和未修剪数据,体积更大,历史 RPC 需要。
- 正式快照:仅活跃对象集,与数据库无关,更小更快,可对照纪元承诺验证,无索引。
- 决策规则:根据节点必须回答的查询选择,而不是根据下载大小。
从 RocksDB 快照恢复全节点
RocksDB 恢复路径刻意简单:你将目录放置在节点期望其活跃存储的位置。使用云对象存储工具从托管快照存储桶拉取纪元目录到临时目录,然后将其放置在 <db_path>/live,修复所有权以便 sui-node 进程可以读写,并启动 sui-node。托管的 Mysten Labs DB 快照存储桶是请求者付费(Requester Pays),意味着操作员支付出口流量费用,因此需要 RocksDB 快照的读者必须为此传输做预算。
两个细节导致大多数失败。第一,目录布局:节点期望纪元内容位于 <db_path>/live 下,而不是存储桶路径的嵌套副本,因此在启动节点前验证结构。第二,所有权和权限:以 root 身份复制然后由非特权服务账户读取的存储将在启动时失败,看起来像损坏。在首次启动前修复所有权,并将临时下载目录放在有足够可用空间的卷上,以容纳归档和解压后的存储。
由于 RocksDB 工件是存储视图而非协议可验证对象,你的完整性检查是结构性和操作性的:确认纪元目录完整,确认节点启动无存储错误,并确认它推进超过快照纪元。加密验证的故事属于正式快照,接下来描述。
- 使用云对象存储 CLI 将纪元目录下载到临时路径。
- 将内容放置在 <db_path>/live 并在首次启动前更正所有权。
- 为托管 DB 快照存储桶的请求者付费出口流量做预算。
- 通过干净启动和推进超过快照纪元来验证。
使用 sui-tool 从正式快照恢复全节点
正式快照使用 sui-tool download-formal-snapshot 恢复。使用 --latest 或显式 --epoch,将 --genesis 指向网络的 genesis.blob,设置 --network,并将 --path 设置到目标数据库目录。对于免费的无权限存储桶,使用 --no-sign-request;对于显式存储桶,传递 --snapshot-bucket 和 --snapshot-bucket-type 以及文档记录的云环境变量用于凭证。保持检查点和交易修剪配置可见,以便节点以你预期的保留策略启动,而不是默认值。
正式恢复默认对纪元承诺执行验证,如果验证失败则回滚节点。这一行为是正式快照成为状态同步参与者更安全入门路径的原因:工具对照正在恢复的纪元的委员会签名承诺检查工件,因此损坏或错误纪元的下载不会静默成为你的节点状态。工具完成后,启动 sui-node 并观察它赶上。
# Restore the latest formal snapshot for mainnet into a target db path.
# Run from the sui-tool binary matching your sui-node release.
sui-tool download-formal-snapshot \
--latest \
--genesis /opt/sui/config/genesis.blob \
--network mainnet \
--path /opt/sui/db \
--no-sign-request
# Pin a specific epoch instead of --latest:
# --epoch 742
#
# Use an explicit bucket instead of the free permissionless bucket:
# --snapshot-bucket <bucket-name> \
# --snapshot-bucket-type <gcs|s3> \
# (plus the documented cloud credential environment variables)
#
# Then start the node with your intended pruning configuration:
# sui-node --config-path /opt/sui/config/fullnode.yaml快照存储桶的成本和访问模型
Mysten Labs 托管的 DB 快照存储桶是请求者付费:下载的操作员支付出口流量费用。免费的无权限存储桶仅用于正式快照,并通过 Cloudflare R2 提供,这就是为什么 --no-sign-request 标志出现在正式恢复示例中。这种不对称是工件类型的实际后果:正式快照足够小且协议可验证,可以无权限提供,而 RocksDB 快照是大型存储视图,其传输成本由请求者承担。
对于规划,将此视为预算问题而非技术问题。需要 RocksDB 快照的读者必须为托管存储桶的出口流量做预算。仅需要作为状态同步全节点或验证者加入的读者可以使用免费正式路径。如果你选择托管提供商而不是运行自己的节点,Sui 网络页面列出了网络选项,RPC 定价和 API 服务描述了自托管的托管替代方案。
- 托管 DB 快照存储桶:请求者付费,操作员支付出口流量。
- 免费无权限存储桶:仅正式快照,通过 Cloudflare R2 提供。
- 正式恢复示例对免费存储桶使用 --no-sign-request。
从你自己的全节点生成快照
全节点默认不生成快照。要生成它们,在 fullnode.yaml 中启用 db-checkpoint-config 并设置 perform-db-checkpoints-at-epoch-end 加上 object-store-config 块,或启用 state-snapshot-write-config 加上 object-store-config 和 object-store-connection-limit,然后重启节点。第一个生成 RocksDB 风格的数据库检查点;第二个写入正式状态快照。将这些块中的存储桶凭证视为写入范围的机密,并仅将其范围限定到快照前缀。
Sui 明确鼓励社区托管额外快照以提供数据可用性,因此生成它们是合法贡献,而不仅仅是内部便利。操作纪律与消费它们相同:知道你在哪个纪元写入,保持工件按纪元可寻址,并发布你所拥有的。Sui 检查点流和账本服务文章涵盖相邻的检查点流机制,如果你正在围绕快照构建数据可用性基础设施。
- db-checkpoint-config:perform-db-checkpoints-at-epoch-end 加上 object-store-config。
- state-snapshot-write-config:object-store-config 加上 object-store-connection-limit。
- 编辑 fullnode.yaml 后重启;使用写入范围的存储桶凭证。
- 记录写入的纪元并发布存储桶名称和保留策略。
对照预期链和头部验证恢复
诚实的恢复检查有两部分。第一,确认正式快照验证已运行:工具默认对照纪元承诺验证并在失败时回滚,因此完成恢复且无回滚是承诺检查通过的证据。第二,确认重启的节点在预期链上,并且其检查点头部正在推进。在两者都为真之前,不要路由流量。
下面的脚本查询节点的 JSON-RPC 端点以获取链标识符和最新检查点序列号,采样两次,并报告头部是否推进。它仅使用标准 JSON-RPC 方法和 Node 内置的 fetch,因此可在任何安装了 Node 18 或更高版本的地方运行。在验证恢复时,将其指向你自己的节点端点,而不是公共端点。
// verify-restore.mjs — confirm chain identity and advancing checkpoint head.
// Usage: node verify-restore.mjs http://127.0.0.1:9000 <expected-chain-id>
const endpoint = process.argv[2] || "http://127.0.0.1:9000";
const expectedChainId = process.argv[3];
async function rpc(method, params = []) {
const res = await fetch(endpoint, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
});
const body = await res.json();
if (body.error) throw new Error(`${method}: ${body.error.message}`);
return body.result;
}
const chain = await rpc("sui_getChainIdentifier");
console.log("chain identifier:", chain);
if (expectedChainId && chain !== expectedChainId) {
console.error(`MISMATCH: expected ${expectedChainId}`);
process.exit(1);
}
const first = await rpc("sui_getLatestCheckpointSequenceNumber");
console.log("checkpoint head (sample 1):", first);
await new Promise((r) => setTimeout(r, 15000));
const second = await rpc("sui_getLatestCheckpointSequenceNumber");
console.log("checkpoint head (sample 2):", second);
if (BigInt(second) > BigInt(first)) {
console.log("OK: checkpoint head is advancing");
} else {
console.error("WARN: head did not advance in the sample window");
process.exit(2);
}用于你自己测量的结果表
快照大小、下载时间和恢复持续时间因环境而异,不得断言为固定事实。在你自己的基础设施上测量它们并记录结果。下表是每个工件和每次运行的填写模板;在每一行中保留纪元、工件类型和网络,以便比较保持诚实。
在相同主机类别和网络路径上至少运行每个测量两次,并注明来源是免费正式存储桶还是请求者付费托管存储桶。如果你发布数字,请同时发布方法。
- 列:日期、网络、纪元、工件类型、源存储桶、工件大小、下载持续时间、恢复持续时间、验证结果、最终检查点头部。
- 记录主机类别、区域和出口路径,以便数字可重现。
- 在重复之前,将任何单次运行视为轶事。
限制、权衡和故障模式
核心限制是索引缺口:正式快照恢复的节点可以向前验证,但无法回答历史索引查询,因为它不包含索引。如果你的服务合同包括历史读取,无论正式路径快多少,它都是错误的工具。RocksDB 路径保留索引但成本更高的存储和出口流量,并且不能以相同方式加密验证,因此你的完整性检查是结构性的。
纪元寻址是第二个限制。快照仅在其拍摄的纪元有效,过时的工件会使节点远远落后。没有回滚到高度的便利。第三,访问模型是不对称的:免费正式存储桶与请求者付费 DB 存储桶意味着更便宜的路径也是更受限的路径。最后,生成快照需要配置更改和重启,配置错误的存储桶凭证是静默不生产的常见原因。
- 正式快照无法提供历史索引查询。
- RocksDB 快照成本更高的存储和出口流量,且缺乏协议级验证。
- 快照受纪元约束;过时工件意味着长时间追赶。
- 免费存储桶仅涵盖正式快照。
- 快照生成是选择加入的,需要重启。
排查常见恢复失败
当正式恢复验证失败时,工具会回滚节点。常见原因是来自错误网络的创世块、存储桶中不存在的纪元或下载截断。首先重新检查 --network 和 --genesis,然后重试同一纪元;如果再次失败,尝试 --latest 以区分坏工件和坏本地配置。
当 RocksDB 恢复启动但节点在存储上出错时,检查 <db_path>/live 下的目录布局和文件所有权。嵌套目录或 root 拥有的文件是最常见的原因。当节点启动但检查点头部不推进时,检查对等连接以及节点是否仍在从快照纪元追赶;恢复后立即缓慢推进的头部是正常的,而冻结的头部则不是。对于节点健康后的接口级问题,Sui gRPC 指南和 Sui 全节点 RPC 端点设置文章涵盖端点配置。
- 验证失败:检查网络、创世块、纪元存在性、下载完整性。
- 存储启动错误:检查 <db_path>/live 布局和所有权。
- 头部冻结:在假设损坏之前检查对等节点和追赶状态。
建议其他操作员和后续步骤
由于 Sui 鼓励社区托管快照,操作员能做的最有用的事情是清晰发布:哪个层级(请求者付费托管 vs 免费 R2)、存储桶名称、可用纪元范围和保留策略。消费者需要知道他们是否可以使用 --no-sign-request 或必须预算出口流量,并且他们需要知道纪元可追溯到多远,然后才能计划恢复。
对于你自己的后续步骤,首先决定节点的任务,然后选择工件类型,然后使用上面的结果表测量你的恢复。如果你正在比较自托管与托管端点,请从 Sui 网络页面开始,查看 RPC 定价和 API 服务,并浏览 OnFinality Learn 中心获取相邻的操作指南。对于历史服务节点,Sui 归档节点和历史 RPC文章和 Base 归档节点历史 RPC文章展示了相同的保留逻辑如何在另一条链上发挥作用。
- 为你的快照发布层级、存储桶名称、纪元范围和保留策略。
- 根据节点必须回答的查询选择工件类型。
- 测量并发布你自己的恢复数字,并附上方法。