Skip to main content
链提交的是区块。而应用问的是这个账户上周成交了什么、订单簿现在长什么样——以区块为形态的记录很难回答这类问题。索引器就是把前者变成后者的那一层。 在大多数链上,索引器都是基础设施里的关键一环:链发出的是不透明的事件,由第三方从中重建含义,于是你的应用信什么,取决于它信哪个索引器。在这里,重建这一步根本不存在。内核发出的是带类型、带归属的输出——每一次状态变更都已经绑定到引起它的那笔交易——所以索引器只是把数据重新塑形,不去推断。 这改变了索引器的定位:它是查询服务层,不是事实来源。它报出来的任何东西都可以对着链核验,一旦出现分歧,那就是索引器的缺陷,不是悬而未决的问题。

路径

按新旧分开
全节点已提交区块,以带类型的记录流出
缓存近期 — 从内存提供
文件存储历史 — 持久化
数据服务把两者呈现为一条流
网关 → REST · WebSocket访问控制、配额与路由
为什么要拆开跟随链头对延迟敏感、数据量小;历史查询对吞吐敏感、数据量大。共用一条路径,一次回填就能把实时那条拖住。
查询服务层,不是事实来源内核发出的是带类型、带归属的输出,所以索引器只是重新塑形,不去推断。与链不一致,那就是索引器的缺陷。
全节点是起点。交易记录从这里以带类型的数据流出,不是还需要再解释一遍的原始交易。 缓存与文件存储按数据新旧把这条流分开。近期数据从内存提供,因为多数消费者要的就是它,而且延迟很重要。历史数据写进持久化的文件存储,因为把一切都留在内存里算不上一种策略。来取旧数据的消费者和跟随链头的消费者,实际由不同的地方服务,而两边谁也感觉不到。 数据服务把两者呈现为一条流。客户端可以请求从任意位置开始的区间;这个区间由缓存提供、由文件提供,还是两者共同提供,不是客户端要操心的事。 网关处理介于服务与公网之间的那些事:访问控制、配额和路由。 REST 与 WebSocket 接口才是应用实际使用的东西——行情数据、订单与成交历史、仓位、账户状态、资金费支付,以及实时订阅。端点级别的细节见 API 参考。

为什么要拆开

一个服务既要跟随链头,又要回答历史查询,两件事都做不好。跟随链头对延迟敏感,数据量小;历史查询对吞吐敏感,数据量大,一次大规模回填就能把实时路径拖住。 分开之后,给一个新消费者回填几个月前的数据,不会拖慢正跟着链头的做市商那条流;两者还能各自独立扩容——也确实需要,因为它们的负载特征毫无共同之处。

什么可以放心依赖

可以依赖:索引器提供的、由已提交区块派生出来的一切——成交、订单、仓位、资金费支付、转账、行情数据。这些都是链上输出重新塑形的结果。 不是一回事:任何尚未提交的东西。订单被内存池接受了,还没有被排序,索引器对它无话可说。在索引器里查不到,意思是“还没有被提交”,不是“被拒绝了”。 可核验:如果某个答案足够重要——一次结算争议、一次审计、一次账务对账——那就直接对着链核验,不必从索引器里取。自己跑一个全节点是这件事最彻底的形式,也是那些承担不起出错代价的参与者应该做的。见运行节点。
两个消费者读同一段已提交区间,应该得到同样的答案。如果不一样,差异出在服务链路上,是应当上报的缺陷——不是“透过索引器读链”这件事的固有属性。

后续阅读

状态模型

索引器读的是什么,以及哪一种表示是权威的。

开发者

REST 与 WebSocket 接口、SDK 与工具。

运行节点

自己对着链核验,以及这个集合为什么是封闭的。

计划服务

谁在消费这条流来计算派生的账户状态。