正在运行一个Hyperliquid 节点吗?通过Hyperliquid 对等连接,为区块和满内存池启用直连路径。
了解更多Solana 读取层的重构:深入解析Quicknode 的内存缓存
Quicknode 在内存中Quicknode Solana读取层。getProgramAccounts、getLargestAccounts 等操作的运行速度比原生 Agave 快 10 到 1000 倍。

2026年5月5日 — 阅读时间13分钟

Solana 在使用返回大量数据或需要扫描全部账户集的方法时遇到了障碍。 getProgramAccounts 被限速或禁用。 getLargestAccounts 永远不会返回。其根本原因在于系统架构。Agave RPC 节点是针对写入操作进行优化的系统,对耗时较长的读取方法进行限流是必要措施,而非策略选择。应用程序最终只能通过重试逻辑、缓存层和轮询间隔来弥补这一缺陷,而这些措施的存在纯粹是为了绕过区块链提供商的基础设施限制。
尽管整个生态系统现在才开始着手解决这一问题,但Quicknode 构建好了Solana 生态系统真正需要的读取层。经过两年的迭代开发,采用专为该目的设计的内存架构,其性能比 Agave 的默认设置快了 10 倍至 1000 倍以上。
如果您是Quicknode 则无需主动申请这些权益。您的endpoint 已endpoint 这些权益。
Agave RPC 节点旨在处理交易、达成共识并推进账本。它们维护的账户状态是该过程的副产品,而非针对读取优化的存储。该系统没有查询规划器,没有原生二级索引,且读写 I/O 并未分离。
硬件扩展无法解决这个问题。读取查询和共识工作在同一台机器上争夺同一块 CPU,因此增加硬件配置意味着需要承担验证者级别的成本(768 GB 内存、高速 NVMe 存储、高带宽网络),却无法消除资源竞争。
增加更多 RPC 节点会加剧这一问题:新增节点会给Solana流言网络和涡轮网络带来额外负载,从而减缓那些真正需要状态传播的验证者的状态传播速度。通过验证者架构对读取层进行扩展,实际上会降低写入层的性能。
数据分页会带来一致性风险。当新数据块出现在页面之间时,响应所基于的账户状态会在读取过程中发生变化。遍历大型结果集的应用程序在读取完成之前,收到的数据位置就已经发生了偏移。
Quicknode 很Quicknode 这个问题,将读取工作负载与验证器分离,并通过专门构建的基础设施来处理这些工作负载。目前处理流量的架构是这些努力的第三个版本。每个版本都更接近数据本身,去除了那些只会增加延迟却无实际价值抽象层,相关工作仍在持续进行中。
第 1 轮:关系型数据库
第一个版本采用了传统方法:将账户状态和账本数据导入关系型数据库,构建索引,并在此基础上进行查询。这立即解决了资源争用问题。验证者可以专注于达成共识,而读取操作则由独立的系统处理。 但关系型数据库带来的开销在Solana 这种规模下不容忽视:查询规划、行级锁定、写前日志(WAL)管理、自动清理(autovacuum),以及基于磁盘存储固有的延迟。对于每 400 毫秒生成一个区块的区块链而言,每次微秒级的读取延迟在每天数百万次请求中都会产生累积效应。随着Solana 增长,磁盘 I/O 成为了需要突破的下一个瓶颈。
第 2 轮:专用高性能数据库
The next iteration started with the schema itself. The team simplified and denormalized the data model to match Solana's actual access patterns, dropping the relational shape that no longer paid for itself. That reshape unlocked a move to a high-performance NoSQL database built for write-heavy ingestion and low-latency point reads, without the query planning, row locking, and write-ahead overhead that came with the relational approach.
吞吐量和延迟都得到了显著提升,而且在大规模运行关系型数据库时常出现的运营难题(如自动 vacuum 卡顿、锁竞争激增、WAL 膨胀)也一并消失了。
第3个迭代版本:完全内存内架构
接下来这一步的动机则有所不同。基于磁盘的系统,无论调优得多么完善,都存在一个难以逾越的瓶颈:每次读取操作最终都会涉及一种比内存慢几个数量级的存储介质。要突破这一瓶颈,读取路径本身必须摆脱对磁盘的依赖。
当前的架构完全消除了读取路径中的磁盘操作。AccountsDB 的状态存储在内存中,并由专门针对Solana 特定查询模式而设计的手工构建数据结构进行索引。这里没有查询规划器、没有 B 树遍历、也没有页面缓存未命中:只需直接访问内存中已预先索引的数据即可。
转向全内存架构是一个经过深思熟虑的决定,旨在针对一个目标进行优化:原始读取性能。
LedgerDB(用于存储每个槽位的区块、交易和元数据的历史记录)缓存遵循相同的设计理念,但采用了不同的存储策略。由于Solana账本体积过大,无法完全加载到内存中,因此采用了分层设计:链尖数据始终保存在内存中,而历史数据则由经过针对该工作负载优化的高性能分布式数据库提供。
Quicknode Solana 是一个独立的二进制文件,无需任何外部依赖即可处理所有链尖方法。只有历史账本查询会调用外部数据库。
AccountsDB(用于存储每个账户的当前状态)缓存完全驻留于内存中,而使其运行迅速的设计选择绝非偶然。四种机制协同工作,消除了读写路径上所有可避免的延迟源。
领先于链条
数据新鲜度是一种性能属性,它在任何读取请求到达之前就已经开始发挥作用。 缓存直接从shred-stream数据源摄取数据,接收账户更新比在等待完整区块的典型Agave RPC节点上显示这些更新要早200-400毫秒。这些更新通过低延迟写入路径(采用near 设计的内存写入)进行,因此这一时间优势得以在端到端过程中保持,而不会被摄取开销所抵消。
这种综合效果在峰值时可量化:在生产环境流量下,缓存中最新的可观察槽位始终比配置相似的 Agave RPC 节点领先 1-2 个槽位。对于交易系统、MEV、清算引擎和实时仪表盘等需要查询“当前状态如何”的工作负载而言,这正是基于实时状态采取行动与基于已过时数据采取行动之间的区别。
自定义数据结构
用于支持账户查询、令牌查询和程序账户过滤的索引,是基于基准测试选定的低级数据结构构建的——这并非最通用的选择,而是针对系统实际遇到的访问模式测得速度最快的方案。共享状态在尽可能的情况下采用最少的锁定机制,确保并发读取者互不干扰。
针对硬件进行优化
该系统在硬件利用率方面进行了深度优化:将数据摄取、索引构建和查询处理分配到专用 CPU 核心,以最大限度地减少上下文切换开销;并根据各组件的具体内存分配特征,为每个组件选择相应的内存分配器,从而在高负载下减少内存碎片。
预计算
在可能的情况下,系统会在读取账户状态时预先计算并维护派生视图:供应汇总数据、按顺序排序的账户列表、经过过滤的程序缓存。这将 CPU 开销从对延迟敏感的读取路径转移到了以吞吐量为导向的写入路径。查询绝不会触发计算,而是直接读取已存在的结果。17 毫秒 getSupply 基准测试中的响应体现了该机制在实际中的运作方式:当查询到达时,聚合结果已经存在。
getProgramAccounts 它执行一项听起来很简单的任务:返回该程序拥有的、符合这些筛选条件的所有账户。难点在于很难对其进行有效的索引。该程序可能是已部署的数千个程序中的任意一个,而每个程序都有其独特的账户模式。
这些过滤器通常是 memcmp 在特定字节偏移量处执行操作,这些偏移量只有在已知程序的内部数据布局时才有意义。A memcmp 在 SPL Token 中,偏移量 32 表示一种含义,而在 DEX 程序中则表示完全不同的含义。
没有一种通用的索引策略能适用于所有情况。索引 getProgramAccounts 要高效地处理,就需要了解每个程序的账户结构。Quicknode索引器通过两种协同工作的策略来解决这个问题:
原生索引程序
对于一小部分流量巨大且机制清晰的程序,Quicknode 随着账户的更新,持续Quicknode 和维护专用的原生索引。这些程序占据了Solana 导地位:SPL Token(旧版)、SPL Token-2022 以及 Stake 程序。
账户结构已知,客户使用的筛选模式也已知,Quicknode 索引Quicknode 正是直接利用了这些具体情况。无论程序拥有多少百万个账户,这些索引都能在不到一毫秒的时间内处理查询,并且它们覆盖了绝大多数的 getProgramAccounts 流量,因为最热门的查询都集中在少数几个程序上。
动态索引程序
对于其他所有情况,例如每个定制的 DeFi 协议、上周部署的每个程序、每个小众用例,索引器都会采用动态策略。 当调用者首次针对某个程序请求过滤器组合时,缓存会自动在运行时创建一个新索引。该首次请求将以未优化的方式运行。索引器必须先扫描该程序的账户并构建索引,才能做出响应,因此调用者需要承担预热缓存的一次性成本。即便如此,这种冷路径的性能也优于Agave。
此后针对同一过滤器的每次请求,均由一个实时、增量维护的缓存处理,该缓存会随着链上账户的变化而保持最新状态。更新数据flow 与原生索引程序相同的流式处理管道flow ,因此缓存视图始终与实际情况保持一致。
从那时起,无论有效载荷大小如何,也无论程序的流行程度如何,延迟实际上都保持恒定。一个返回十个账户的过滤器与一个返回一百万个账户的过滤器,其响应速度处于同一数量级,因为相关工作已经完成。响应结果直接从预先组装好的内存中流式传输,而不是针对每个请求重新计算。
New programs are supported the same day they are deployed. There is no schema integration, no manual configuration, and no waiting for an engineering team to add support. The first client to query a new program kicks off the indexing, and every client after that benefits from it.
原生索引可为绝大多数实际流量提供最佳性能。动态索引器确保没有任何程序或过滤模式不受支持。
p50
节目 | 账户 | Quicknode 预热 TTFB | Agave Direct TTFB | Quicknode Agave 对比 |
|---|---|---|---|---|
Jupiter v6 | 60 | 0.2 毫秒 | 2.0 毫秒 | 速度提升10倍 |
Marinade Finance | 1K | 2.5 毫秒 |
p99
节目 | 账户 | Quicknode 预热 TTFB | Agave Direct TTFB | Quicknode Agave 对比 |
|---|---|---|---|---|
Jupiter v6 | 60 | 0.3 毫秒 | 6 毫秒 | 速度提升20倍 |
Marinade Finance | 1K | 4 毫秒 |
getProgramAccounts 这是 AccountsDB 层面上最棘手的问题,因此它拥有专门的优化策略。其他所有操作(点查询、聚合、令牌查询、区块和槽位元数据)均从同一内存状态中处理,并遵循相同的设计原则:尽可能预先计算、读取路径上无锁,且通过单次查询而非全表扫描即可完成。
因此,在并发负载下,AccountsDB 的每个方法(而不仅仅是那些主要方法)都能以内存级速度运行。无论流量规模扩大还是账户集增长,所有受支持的方法在负载下均不会出现性能下降的情况。
以下数据来自与同一网络上一个现成的Agave验证器的基准测试。性能差异源于架构设计,而非硬件性能更优所致。
对于简单的点查询, getAccountInfo, getBalance,以及 getTokenAccountBalance,Quicknode索引器与 Agave 的性能相当,响应时间在 2-4 毫秒之间。这些方法的热点路径是单次索引读取。响应时间主要取决于网络往返时间,而非随账户集规模增长而增加的运算工作量。在需要聚合、排序视图或验证器未维护的二级索引的方法上,性能表现会有所差异。
方法 | Quicknode p50 | 龙舌兰 p50 | Delta |
|---|---|---|---|
getTokenLargestAccounts (USDC) | 4 毫秒 | 97,535 毫秒 | 快了 24,384 倍 |
getTokenLargestAccounts (BONK) | 4 毫秒 | 8,463 毫秒 | 快了 2,116 倍 |
getLargestAccounts |
有三项结果尤为突出:
getTokenLargestAccounts 对于 USDC:Agave 需要近 100 秒。每次请求都会迫使验证器遍历整个 SPL 代币程序,按铸币方进行过滤、排序,并返回排名前 20 的结果,且没有缓存结果,也没有排序索引。Quicknode索引器维护着按铸币方排序的集合,该集合会随着余额的变化进行增量更新。
getLargestAccounts 在 Agave 上无法在五分钟内完成。验证器会在每次请求时,从头开始对整个账户集重新计算一个已排序的聚合结果。Quicknode索引器将其维护为一个运行中的索引。
getTokenAccountsByDelegate 在 Agave 上不支持此功能。Quicknode索引器可在个位数毫秒内完成此操作。
延迟数据反映了单个请求的速度。并发情况则有所不同,但同样重要。当单个 Agave getTokenLargestAccounts 该查询耗时97秒,该请求占用了服务槽,并导致其后所有查询陷入停滞:一个缓慢的请求会引发连锁反应,导致所有并发调用者的延迟骤增。
Quicknode索引器不存在这种故障mode。每个查询都由预先构建的内存索引处理,因此没有任何单个请求的执行时间会长到影响并发流量。在持续负载下,AccountsDB 缓存每秒可处理数万次请求,同时将 P50 延迟控制在 10 毫秒以内,其吞吐量由硬件容量决定,而非账户集大小或查询复杂度。
并非所有方法的响应时间都低于10毫秒。针对未被原生索引集包含的程序发出的冷请求,在首次调用时需承担11至40秒的初始化成本,期间订阅关系建立并填充过滤后的缓存。此后对同一过滤器的每次请求均从内存中的热缓存中获取数据。
大规模的质押程序查询体现了中等规模的情况。Marinade 的 8.1 万个质押账户在Quicknode索引器上约一秒即可完成解析,而在 Agave 上则需 6.7 秒。索引查询速度依然很快,但在如此大的数据量下,组装和序列化响应确实需要消耗大量的 CPU 资源。
在 Raydium V4 这种规模下(约 70.5 万个账户,约 869 MB 的 JSON 数据),响应速度遇到了另一种瓶颈:首次字节传输时间为 1.5 秒,而完整交付所需时间更长,这受限于通过网络传输 869 MB 数据的物理限制。
各方面性能提升都十分显著。每种方法的运行速度都比原生 Agave 验证器快 10 到 1000 倍。在单方法负载测试中,单个实例可持续处理 350,000 getTransaction 每秒请求数,延迟低于 40 毫秒,且达到 120,000 getAccountInfo 每秒请求数,P50值低于20毫秒。
AccountsDB 和 LedgerDB 缓存合计覆盖了生产环境 RPC 流量的约 95%,以及Solana 规范的约 90%。
今天所呈现的成果是经过两年迭代的结晶。这并非最终形态。Quicknode 对Solana 读取层的投入仍在持续。该架构将不断提速,方法覆盖范围将持续扩大,而弥合开发者需求与基础设施实际交付能力之间差距的工作也不会停止。
Solana读取和写入工作负载是根本不同的问题,因此需要根本不同的架构。Quicknode 耗时两年,从零开始Quicknode Solana 生态系统真正需要的读取层,且未在性能上做出任何妥协。对这一基础设施的持续改进并非需要用户主动选择的功能,而是每个Quicknode Solana endpoint 提供的标准服务。
endpoint Quicknodeendpoint 创建一个Solana endpoint ,并开始在专为这一工作负载量身打造且持续优化的读取层上进行开发。
Quicknode 成立于 2017 年,Quicknode 为开发者和企业Quicknode 机构级区块链基础设施。凭借 99.99% 的运行时间以及对 80 多条区块链的支持,各团队能够毫无妥协地构建和扩展链上应用。
将最新的工程见解、产品更新和 Web3 资讯直接发送至您的收件箱。
通过 SOC 2 II 类认证 · ISO 27001
12 毫秒
速度提升4.8倍 |
张量 | 30K | 0.7 毫秒 | 213 毫秒 | ~304倍快 |
逆戟鲸漩涡 | 91K | ~2.0 毫秒 | 3,515 毫秒 | ~1,760倍更快 |
Phoenix DEX | 109K | ~2.6 毫秒 | 783 毫秒 | ~301倍更快 |
Drift Protocol | 273K | ~6.4 毫秒 | 3,469 毫秒 | ~542倍快 |
SPL 名称服务 | 341K | ~8.7 毫秒 | 6,764 毫秒 | ~777倍快 |
Pump.fun | 507K | 约15毫秒 | 27,958 毫秒 | 速度提升约1,864倍 |
Raydium V4 | 705K | ~18.5 毫秒 | 10,224 毫秒 | ~553倍快 |
15 毫秒
速度提升3.8倍 |
张量 | 30K | 1.2 毫秒 | 234 毫秒 | ~195x 更快 |
逆戟鲸漩涡 | 91K | ~2.3 毫秒 | 3,668 毫秒 | 速度提升约1,595倍 |
Phoenix DEX | 109K | ~2.8 毫秒 | 845 毫秒 | ~302倍更快 |
Drift Protocol | 273K | ~7.0 毫秒 | 3,720 毫秒 | ~531倍更快 |
SPL 名称服务 | 341K | ~8.9 毫秒 | 7,571 毫秒 | ~851倍更快 |
Pump.fun | 507K | ~16 毫秒 | 29,718 毫秒 | 速度提升约1,857倍 |
Raydium V4 | 705K | ~20 毫秒 | 11,120 毫秒 | ~556倍更快 |
7 毫秒
>300,000 毫秒(超时) |
>快42,857倍 |
getSupply | 17 毫秒 | 6,231 毫秒 | 快367倍 |
getTokenAccountsByDelegate | 4 毫秒 | 不支持(错误) | Agave 无法提供此服务 |
getProgramAccounts:所有者持有的 Token-2022 | 8 毫秒 | >15,000 毫秒 | 速度提升约1,875倍 |
getProgramAccounts:Orca Whirlpool(9.1万个账户)(温和) | 167 毫秒 | 3,515 毫秒 | 速度提升21倍 |
getProgramAccounts:Pump.fun(50.7万个账户)(预热中) | 795 毫秒 | 27,958 毫秒 | 快35倍 |