摘要
Sui indexer 将原始的 Sui checkpoint 和交易数据转化为可查询的状态,供仪表盘、分析和应用后端使用。难点很少在于查询层——而在于保持可靠、低延迟的 Sui 数据流持续流入其中。本文介绍了开发者在 Sui 上实际使用的索引架构、为其提供数据的 RPC 和 gRPC 访问模式,以及如何在自托管和托管基础设施之间做出选择。它还解释了 OnFinality 提供的可靠 Sui RPC 和专用节点设置如何融入该管道。
Sui indexer 是将 Sui 原始链上输出转化为应用程序可以快速查询的组件:余额、对象历史、事件流和聚合指标。如果你正在构建钱包、浏览器、DeFi 仪表盘或需要不止单个对象查询的后端,你最终会需要一个。
问题在于,索引是一个数据工程问题,而不仅仅是 RPC 问题。你需要一个可靠的 Sui 数据源、一种在不落后的情况下处理数据的方法,以及一个能快速回答查询的存储层。本文介绍了该管道是如何构建的、通常在哪里出问题,以及如何决定是自行运行还是依赖托管基础设施。
Sui indexer 实际做什么
Sui 以几种不同的形式产生数据,一个好的 indexer 理解其中的区别:
- Checkpoint — 有序的交易批次。Checkpoint 是任何 Sui indexer 的骨干,因为它们为你提供了一个确定性的、无间隙的序列进行处理。
- 交易和效果 — 输入和产生的状态变化(对象变更、创建和删除的对象、余额变化)。
- 事件 — 由 Move 包发出的结构化消息。事件是应用特定索引最简单的钩子,因为你可以按包和事件类型进行过滤。
- 对象 — 拥有和共享对象的当前状态。对象状态是大多数读取路径实际需要的。
典型的 Sui indexer 按顺序读取 checkpoint,提取它关心的交易和事件,将它们转换为适合你查询的模式,并将结果写入数据库。然后查询层(REST、GraphQL 或 SQL)为你的应用程序提供服务。
重要的设计选择是你是索引所有内容还是只索引你需要的内容。全历史索引成本高昂且回填缓慢。针对性索引——特定包、一组事件类型或对象子集——通常是生产应用实际需要的。
自建 vs 购买:真正的成本在哪里
在编写任何索引代码之前,决定谁运行管道。权衡很少在于查询层;而在于数据源和运营负载。
| 方法 | 你拥有什么 | 痛点 | 适合场景 |
|---|---|---|---|
| 完全自托管 | 数据源、处理、存储、查询 API | 回填时间、重组/间隙处理、管道延迟的待命 | 你需要自定义模式且有平台工程师可用 |
| 托管 RPC + 自己的 indexer | 仅处理和存储 | 你仍然需要调整吞吐量和存储,但不需要节点正常运行时间 | 你想控制模式而不运行节点 |
| 托管 indexer / 数据 API | 仅查询层 | 对模式和保留的控制较少 | 你需要快速获得标准数据,模式灵活性是次要的 |
大多数团队处于中间位置:他们运行自己的转换和存储,但依赖托管提供商提供 Sui 数据源。这就是可靠的 RPC 和专用节点设置重要的地方,因为无论你的处理代码有多好,延迟或限速的数据源都会使整个管道停滞。
选择你的 Sui 数据源
你的 indexer 的新鲜度取决于为其提供数据的端点。Sui 上有三种常见的访问模式,它们适合管道的不同阶段。
用于对象和交易读取的 JSON-RPC。 适用于针对性查找、交易提交和轻量级轮询。它是最简单的集成,适用于低容量或请求驱动的索引。
用于持续摄入的 gRPC 流。 当你需要跟随 checkpoint 或订阅更新流时,流式接口比轮询高效得多。这是大多数生产 indexer 趋同的模式,因为它让你接近链头而不会冲击请求/响应端点。
用于回填的批量历史访问。 通过请求/响应端点回填数月历史很慢。如果你的提供商提供批量或归档访问,请将其用于初始加载,并保留流式用于保持最新。
一个实用的拆分如下:从支持归档的源回填,然后切换到流式处理实时尾部,并使用 JSON-RPC 进行应用程序在请求时进行的临时读取。
一个最小的摄入循环
Sui indexer 的形状通常是一个 checkpoint 游标加上一个转换步骤。下面的示例使用 JSON-RPC 调用获取 checkpoint 并推进游标。将其视为草图,而不是完整的 indexer——重点是控制流。
curl -s https://sui.api.onfinality.io/public \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getCheckpoint",
"params": ["1000000"]
}'
在真实的管道中,你会将其包装在一个循环中,该循环持久化最后处理的 checkpoint、处理间隙,并批量写入转换后的行。有两个细节比请求本身更重要:
- 在写入之后持久化游标,而不是之前。 如果你推进游标然后在写入之前崩溃,你会静默地跳过数据。
- 使转换幂等。 重新处理一个 checkpoint 应该覆盖相同的行,而不是重复它们。在
(checkpoint, tx_digest, event_index)上设置唯一键是通常的修复方法。
对于持续摄入,用流式订阅替换轮询循环,并保持相同的游标和幂等规则。
生产就绪检查清单
一旦管道在本地运行,问题就转向可靠性。在将真实流量指向它之前,请完成以下工作:
- 延迟监控。 跟踪链头与你最后处理的 checkpoint 之间的差距。对持续延迟发出警报,而不是对单个峰值。
- 间隙和重组处理。 决定如何检测遗漏的 checkpoint 以及如何重新获取它。Sui 的 checkpoint 模型是有序的,这使得间隙检测变得可行——利用它。
- 回填策略。 了解完整回填需要多长时间,以及你是否可以在实时摄入的同时并行运行它。
- 端点故障转移。 单个端点就是单点故障。有一个备用方案和一种检测降级源的方法。
- 存储增长。 事件和交易表增长迅速。在数据库成为瓶颈之前规划保留和分区。
- 查询延迟预算。 如果你的应用程序查询需要亚秒级响应,请分离写优化和读优化路径。
如果其中任何一项无人负责,那就是首先要弥补的差距。
RPC 基础设施适合在哪里
Indexer 是你的代码;数据源是基础设施。将两者分开是让你可以扩展其中一个而不重写另一个的关键。
托管的 Sui RPC 端点处理节点侧——同步、升级和可用性——因此你的管道只需处理数据。对于更高容量的摄入,专用 Sui 节点为你提供隔离的容量,而不是共享公共池,当你的摄入循环是恒定的而不是突发的时候,这一点很重要。你可以查看 Sui 网络页面了解支持的传输和连接细节,如果你正在为持续吞吐量做规划,可以比较 RPC 定价。
实用规则:如果你的 indexer 持续运行,并且数据源停滞意味着用户数据过时,请将数据源视为生产基础设施,而不是免费端点。
常见故障模式
大多数 Sui indexer 事件都属于少数几种模式。识别它们可以大大缩短调试时间。
| 症状 | 可能原因 | 首先检查什么 |
|---|---|---|
| Indexer 稳步落后 | 源吞吐量或速率限制 | 请求速率 vs. 提供商限制;切换到流式 |
| 重启后出现重复行 | 非幂等转换 | 在 checkpoint/tx/事件标识符上设置唯一键 |
| 缺少 checkpoint | 游标在写入之前推进 | 游标持久化顺序 |
| 随着数据增长查询变慢 | 未分区的表 | 热列上的索引和分区 |
| 间歇性摄入停滞 | 单端点,无故障转移 | 添加备用源和健康检查 |
这些都不是奇异的。它们是运行数据管道的正常成本,当数据源稳定时,它们都更容易处理。
关键要点
- Sui indexer 读取 checkpoint、交易、事件和对象,然后将它们重塑为可查询的模式。
- 针对性索引(特定包或事件类型)通常比全历史索引更便宜、更快速。
- 流式是实时尾部的正确模式;批量或归档访问是回填的正确模式。
- 在写入之后持久化游标并使转换幂等——这两条规则可以防止大多数数据完整性错误。
- 数据源是生产基础设施。托管的 Sui RPC 或专用节点将节点操作从你的关键路径中移除。
- 监控延迟、规划保留,并始终有一个故障转移端点。
常见问题
如果我已经有 RPC 端点,还需要单独的 indexer 吗?
通常需要,对于任何超出单对象查找的内容。RPC 很好地回答点查询,但它不维护仪表盘和分析所需的聚合、历史或过滤事件视图。Indexer 构建并存储这些;RPC 是它获取数据的地方。
我应该索引每个 checkpoint 还是只索引我需要的?
从你需要的开始。按包和事件类型过滤可以保持存储和回填时间可控。你以后总是可以扩大范围,但在事后缩小全历史索引是很痛苦的。
如何防止 Sui indexer 落后?
使用流式接口处理实时尾部而不是轮询,监控链头与游标之间的差距,并确保你的数据源有足够的容量进行持续摄入。如果延迟稳步增长而不是峰值,源通常是约束。
我可以针对公共端点运行 indexer 吗?
对于开发和低容量测试,可以。对于持续生产摄入,公共端点通常是错误的工具,因为共享容量和速率限制最终会限制你。专用节点为你的管道提供可预测的容量。
Indexer 和 RPC 提供商有什么区别?
RPC 提供商运行节点并暴露链访问。Indexer 是消费该访问并产生可查询数据集的应用程序逻辑。它们是互补的:提供商提供数据,indexer 塑造并存储它。
下一步
如果你正在启动 Sui indexer,从狭窄的范围开始——一个包或一小组事件类型——并在扩展之前正确处理游标和幂等规则。然后决定你的数据源是否能维持持续摄入。如果不能,请考虑托管的 Sui RPC 或专用节点,这样你的管道就不会争夺共享容量。你可以查看支持的 RPC 网络了解 Sui 在 OnFinality 运行的其他基础设施中的位置,并在准备连接时从 Sui 网络页面开始。