---
title: "Como a Alchemy construiu os métodos de arquivamento mais rápidos na Solana"
description: "Descubra a arquitetura que torna nossos métodos de arquivamento a solução mais rápida do mercado atualmente."
---

# Como a Alchemy construiu os métodos de arquivamento mais rápidos na Solana

<ImageBlock
  src="https://media.alchemy.com/1771818629-blog-archival-methods-solana.png"
  alt="Um gráfico mostrando dados de arquivamento no Solana"
  width={5760}
  height={2700}
  priority
/>

No final do ano passado, [anunciamos nossa nova oferta de produto](https://www.alchemy.com/blog/solana-infrastructure) para Solana, e um dos principais recursos desse produto é a performance dos nossos métodos de arquivamento: até 20x mais rápidos do que qualquer outra solução no mercado.

Com nossa oferta para Solana, desenvolvedores podem consultar transações, blocos e assinaturas históricas em velocidade sem precedentes via uma interface JSON RPC padrão. Isso não foi fácil de construir, e neste post vamos detalhar como fizemos.

## O que são métodos de arquivamento em Solana?

Em Solana, métodos de arquivamento se referem a chamadas RPC que recuperam dados históricos da blockchain, como `getTransaction`, `getBlock` e `getSignaturesForAddress`.

Esses endpoints de arquivamento são a base de aplicações onchain. Wallets, indexadores, provedores de analytics, exploradores, e muito mais dependem desses dados históricos para fornecer dados mais ricos aos usuários e construir experiências coerentes.

No entanto, o acesso a dados arquivados é notoriamente difícil de obter em Solana. O conjunto de dados é enorme, profundamente interconectado, e computacionalmente pesado de consultar. Para a maioria dos desenvolvedores, esses endpoints são onde problemas de latência e inconsistência aparecem primeiro e de forma mais acentuada.

## O problema de performance dos métodos de arquivamento da Solana

A maior parte da infraestrutura de Solana hoje roda sobre Google Bigtable combinado com nós RPC baseados em validadores.

Essa stack é fácil de implantar \(por isso muitas equipes a escolhem\), mas não foi construída para escala. É intensiva em CPU, consome muita memória, e tem dificuldades com requisições em lote grandes. Ao consultar em escala, esses métodos podem limitar o throughput e deixar seu app extremamente lento, ou pior, até descartar dados na resposta.

É por isso que mesmo provedores respeitáveis frequentemente retornam respostas incompletas ou atrasadas quando você consulta dados históricos. Para devs, esses blocos ausentes e chamadas lentas rapidamente se transformam em experiências quebradas dentro do app.

Queríamos resolver isso. Não simplesmente com mais hardware \(embora tenhamos adicionado mais disso também\), mas com uma arquitetura melhor para toda nossa infra.

## Nossos desafios de otimização com o Google Bigtable
Como muitos provedores de infra para Solana, começamos com o Google Bigtable, e com o tempo descobrimos os problemas de performance mencionados acima. Esses problemas foram agravados por dois fatores.

Primeiro, o tamanho grande dos blocos de Solana. O Bigtable tem melhor performance quando as linhas têm ~1KB. Dados de transação ou estados de conta em Solana costumam ser muito maiores. Buscar um objeto binário grande exige mais I/O do armazenamento subjacente do Google \(Colossus\).

Segundo, havia uma questão de preço. Bancos de dados na nuvem são caros. Muitos dados em Solana \(como transações de votação\) não são particularmente valiosos, e não é economicamente viável manter esses dados na nuvem. Além disso, o Google Bigtable é precificado por uso, o que adiciona ainda mais pressão e menos flexibilidade para oferecer um RPS maior.

Apesar dessas limitações, ainda tentamos aplicar algumas otimizações a essa configuração. Por exemplo, otimizamos a busca de transações. Na configuração padrão do Google Bigtable, quando você solicita uma transação com `getTransaction`, ele dispara uma consulta a uma tabela `tx` para o ID do bloco pela assinatura. Depois busca todos os blocos para retornar uma única transação. Isso é muito trabalho para retornar uma quantidade pequena de dados de um banco de dados remoto na nuvem.

Para tornar essa requisição comum mais eficiente, introduzimos uma tabela adicional chamada `tx-full` onde armazenamos não apenas uma referência aos blocos, mas a transação inteira. Isso fez uma grande diferença nos tempos de resposta, mas ainda sofríamos com latência aumentada devido à localização geográfica remota do data center.

Mesmo tendo nos esforçado para nos adaptarmos à stack padrão, o desenvolvimento era muito lento. Uma simples escrita feita a partir de um nó RPC completo/validador já era um grande incômodo: cada mudança exigia reinicializações completas dos nós. Esse processo podia levar de 30 minutos a algumas horas. Não ter o banco de dados geograficamente mais próximo, nem a capacidade de controlar alguns de seus parâmetros, também tornava tudo muito mais difícil e caro. Depois de algum esforço, decidimos que seria melhor reescrever toda a stack, desde a ingestão de dados até o próprio servidor RPC.

## Nossa solução? Uma stack reescrita

Nosso principal objetivo ao assumir esse trabalho era reduzir o tempo de desenvolvimento. Isso significava eliminar nós RPC pesados que escrevem e servem dados. Em vez disso, separamos a escrita e a entrega de dados em pequenos serviços separados e migramos para um banco de dados open source auto-hospedado.

Esse novo sistema oferece:

- **Co-otimização de hardware e software:** Cada camada da stack, do layout do disco ao acesso à memória, é ajustada para maximizar o throughput e minimizar overhead de computação.
- **Distribuição de dados multi-região:** Os dados de arquivamento são distribuídos globalmente, garantindo acesso de baixa latência independente de onde as requisições se originam.
- **Ingestão com tripla verificação:** Cada registro é escrito duas vezes, validado programaticamente quanto à precisão, e continuamente varrido quanto à completude.
- **Pipelines autorregenerativas:** Se discrepâncias são detectadas, reingerimos automaticamente as entradas ausentes, checando de forma cruzada até 30–50 endereços relacionados por bloco para garantir a integridade dos dados.

Vamos passar por cada parte da solução, que também [tornamos open source](https://github.com/dexterlaboss/archival-rpc) \(esse código está no repositório do [DexterLab](https://www.alchemy.com/dapps/dexterlab), que foi [adquirido pela Alchemy no ano passado](https://www.theblock.co/post/354709/alchemy-acquires-solana-infrastructure-provider-dexterlab-as-it-continues-expansion-beyond-ethereum)\).

## ArchivalRPC

Reconstruímos nosso serviço de arquivamento do zero, tornando-o um serviço muito mais performático, que pode ser iniciado ou reiniciado em poucos segundos. Uma melhoria drástica em relação aos 30 minutos a várias horas de tempo de inicialização que enfrentávamos ao trabalhar com um nó RPC completo.

Ainda usamos as mesmas bibliotecas oficiais da Solana para serializar e desserializar dados, então esse serviço sempre será compatível com mudanças contínuas. Isso significa que mesmo com nossa nova stack customizada, não estamos alterando os dados de forma alguma, garantindo que os dados que servimos não sejam corrompidos durante o processamento.

E sendo um serviço leve que depende de um banco de dados, é muito fácil escalar sob demanda \(em apenas alguns segundos\) e acomodar um volume massivo de tráfego. Isso é particularmente útil para aplicações com picos de uso, e com uma única instância de banco de dados, esse serviço pode atingir números de até 100-200k RPS dependendo da configuração do banco de dados.

## Ingestor do ArchivalRPC

Essa parte da stack é responsável por extrair dados de Solana de múltiplas fontes e escrevê-los em nossa camada de banco de dados. Ela lida tanto com importações em lote \(como arquivos raw gzip de blocos usados ao inicializar novas instâncias\) quanto com streams em tempo real de sistemas como Kafka.

Também construímos controles granulares diretamente no ingestor, que nos permitem escolher exatamente quais tipos de dados uma instância deve armazenar \(por exemplo, apenas blocos, apenas assinaturas, apenas transações, ou qualquer combinação\). Esse modelo de ingestão seletiva reduz pontos únicos de falha, melhora a confiabilidade, e nos dá alavancas significativas para otimizar custos de armazenamento dependendo do caso de uso.

## Hbase

Depois de melhorar a performance de leitura e escrita, voltamos nossa atenção para o próximo desafio: a latência do banco de dados na nuvem. O ArchivalRPC foi projetado desde o início para suportar múltiplos backends de armazenamento, o que facilitou explorar alternativas.

Por fim escolhemos o HBase, um substituto open source e auto-hospedado para o BigTable, porque ele nos permitiu colocar o banco de dados ao lado de nossos servidores RPC e reduzir a latência de armazenamento efetivamente a zero. Essa implementação também nos permitiu usar nossos modelos de dados e princípios de implementação já existentes, nos dando os benefícios de performance sem introduzir riscos arquiteturais.

Mas mesmo com os pontos fortes do HBase, ainda enfrentamos alguns problemas. Por exemplo, para lidar com o grande tamanho dos blocos de Solana, originalmente tentamos usar `BucketCache` no Hbase, que pode ser configurado para usar memória off-heap ou SSDs rápidos como uma camada de cache secundária e manter mais dados em um estado "warm".

No entanto, acabamos descobrindo que `BucketCache` não era confiável. Por causa da aleatoriedade dos dados e da rapidez com que mudavam, isso deixava nosso sistema lento. Em vez disso, por fim recorremos a uma solução diferente para lidar com dados grandes: mudamos a forma como os blocos são armazenados. Em vez de armazenar blobs completos em nosso banco de dados \(que não foi projetado para lidar com essas estruturas de dados grandes\), armazenamos apenas os metadados no banco de dados, que apontam para arquivos CAR que podem residir em qualquer armazenamento e são muito escaláveis.

### Otimizações de serviço e distribuição multi-região

Construir uma solução que pudesse escalar para milhões, e até bilhões de requisições, exigiu otimizações em toda a stack: apenas trocar uma arquitetura de banco de dados por outra não era suficiente para conseguir a performance que buscávamos. Isso exigiu que testássemos muitas implantações diferentes em hardwares diferentes e experimentássemos arquiteturas diferentes. Com o tempo, melhoramos nossos serviços de ingestão e entrega e obtivemos os resultados desejados.

Otimizar nosso hardware e software para lidar com altos volumes de requisições foi um desafio que precisamos resolver. Outro foi combater a latência. Para chamadas de arquivamento pesadas, descobrimos que controlar a latência exigia expandir nosso hardware para múltiplas regiões para garantir respostas rápidas e consistentes em todo o mundo.

Essa configuração multi-região também melhora nossa disponibilidade e nos ajuda a manter padrões de confiabilidade mais altos. Interrupções são inevitáveis, e ter opções de fallback distribuídas por regiões geográficas garante que, mesmo se uma região cair, possamos continuar atendendo nossos clientes. Essa mesma configuração multi-região também nos ajuda a escalar e distribuir tráfego: se uma região está atingindo sua capacidade, podemos rotear o tráfego para outra região à medida que escalamos a implantação.

### Ingestão com tripla verificação

Boa parte do trabalho para esse produto foi melhorar a performance, mas isso é só metade da batalha. Um problema recorrente com os métodos de arquivamento de Solana é que os dados frequentemente são descartados por completo. Precisávamos melhorar a confiabilidade do sistema.

Muitos provedores baseados em Bigtable perdem silenciosamente blocos, assinaturas ou transações à medida que seus pipelines de ingestão escalam. Essas perdas acontecem por causa de como a ingestão de dados padrão funciona a partir de um validador: cada reinicialização pode causar lacunas nas escritas de dados.

E se você está preso a manter múltiplos validadores escrevendo os mesmos dados, isso ainda não garante consistência de dados, porque não há verificações secundárias de que os dados estão sendo escritos corretamente. E como builder usando essa infra, você não tem ideia de que dados estão faltando até que algo quebre mais adiante.

Nossa infraestrutura previne esse problema por design. Depois de escrever os dados, rodamos pipelines secundárias para ler cada registro e validar continuamente esses dados, corrigindo-os automaticamente caso apareçam inconsistências. Também fazemos verificações completas de nossos bancos de dados após a inicialização, e continuamos fazendo verificações em escritas ao vivo em tempo quase real.

Não construímos apenas dados mais rápidos. Construímos dados confiáveis.

### Pipelines autorregenerativas

Para alguns dados complexos, como `signatures`, métodos de fallback não podem ser confiáveis. Isso significa que o processo de tripla verificação acima às vezes ainda não é suficiente.

Para combater isso, usamos validação programática para verificar de forma cruzada transações em até 30-50 endereços por bloco. Se nosso sistema detecta uma discrepância, nosso processo de backup e recuperação corrige automaticamente as entradas ausentes.

Esse processo envolve buscar um bloco que serve como fonte da verdade e extrair todas as relações endereço-assinatura dele. Para otimizar o custo de varrer o HBase aqui, acumulamos esses mapeamentos por endereço em um grande intervalo de slots consecutivos e realizamos uma consulta de varredura em vez de consultas individuais baseadas em chave. Os resultados são então comparados, o que nos permite identificar lacunas no cluster SIGS.

Uma vez identificadas essas lacunas, republicamos esse bloco no pipeline de indexação \(para um tópico kafka adequado para esse tipo de dado\) e o reindexamos. Também adicionamos um processo de verificador de consistência que repetirá essa operação se a lacuna não for preenchida, e eventualmente alertará nossa equipe se o estado de falha persistir.

Essa redundância e autorregeneração garantem que você pode confiar em nossos métodos como a fonte mais completa e consistente de dados históricos em Solana.

## Traduzindo o trabalho em throughput

Todo esse trabalho se traduziu em capacidade significativa:

- 100.000 RPS por região para `getTransaction`
- 50.000 RPS por região para `getSignaturesForAddress`
- 2.000 RPS por região para `getBlock`

Continuamos investindo em nossa oferta para Solana e em breve expandiremos para mais regiões, para ainda mais confiabilidade e latência. Isso é apenas o começo.

## Experimente você mesmo
Se você quiser testar nossos métodos de arquivamento em Solana, pode começar gratuitamente [criando uma conta no dashboard](https://dashboard.alchemy.com/) para gerar sua API key. Depois, você pode explorar nossos endpoints de Solana [em nossa documentação](https://www.alchemy.com/docs/reference/solana-api-quickstart).

## Perguntas frequentes

### O que são métodos de arquivamento em Solana?

Métodos de arquivamento são chamadas RPC que recuperam dados históricos da blockchain, como `getTransaction`, `getBlock` e `getSignaturesForAddress`. Esses endpoints permitem que desenvolvedores acessem transações, blocos e assinaturas passadas através de uma interface JSON RPC padrão.

### Por que os métodos de arquivamento de Solana costumam ser lentos?

A maior parte da infraestrutura de Solana roda sobre o Google Bigtable, que é intensivo em CPU, consome muita memória, e tem dificuldades com requisições em lote grandes. Essa stack não foi construída para escala e pode limitar o throughput, reduzir a performance, ou até descartar dados nas respostas.

### Quão rápidos são os métodos de arquivamento da Alchemy em Solana?

Os métodos de arquivamento da Alchemy são até 20x mais rápidos do que outras soluções, com capacidade de 100.000 RPS por região para `getTransaction`, 50.000 RPS para `getSignaturesForAddress` e 2.000 RPS para `getBlock`.

### Como a Alchemy garante a completude e confiabilidade dos dados?

Usamos ingestão com tripla verificação, onde cada registro é escrito duas vezes, validado programaticamente quanto à precisão, e continuamente varrido quanto à completude. Pipelines autorregenerativas reingerem automaticamente entradas ausentes ao checar de forma cruzada até 30-50 endereços relacionados por bloco.

### Qual banco de dados a Alchemy usa para dados de arquivamento de Solana?

Usamos o HBase, um banco de dados open source e auto-hospedado que permite que os dados fiquem co-localizados junto aos servidores RPC para reduzir a latência de armazenamento efetivamente a zero. Isso substituiu o Google Bigtable para melhorar a performance e reduzir custos.

### Como a Alchemy lida com o grande tamanho dos blocos de Solana?

Em vez de armazenar blocos completos no banco de dados, a Alchemy armazena apenas metadados que apontam para arquivos CAR, que podem residir em qualquer armazenamento e são altamente escaláveis. Essa abordagem lida melhor com o grande tamanho dos blocos de Solana.

### Por que a Alchemy reconstruiu toda a stack de arquivamento do zero?

A stack padrão usando nós RPC completos exigia de 30 minutos a várias horas para reinicializações, tornando o desenvolvimento lento e caro. A Alchemy separou a escrita e a entrega de dados em pequenos serviços que podem reiniciar em segundos e escalar sob demanda.

### Como a Alchemy mantém baixa latência globalmente?

Os dados de arquivamento são distribuídos por múltiplas regiões globalmente, garantindo acesso de baixa latência independente da origem da requisição. Essa configuração multi-região também melhora a disponibilidade e ajuda a distribuir tráfego durante períodos de alta demanda.
