
De ClickHouse a RocksDB: cómo reconstruimos la capa de archivo de Solana
Tabla de contenido
- Qué es el archivo de Solana y por qué importa
- ClickHouse: la primera apuesta pragmática
- Dónde dejó de funcionar ClickHouse
- RocksDB: no es una base de datos
- Cómo resuelve RocksDB las limitaciones de ClickHouse
- Lo que construimos encima
- Optimización de RocksDB a escala
- Ajusta por índice, no por base de datos
- Decide si realmente necesitas WAL
- Adapta los filtros de Bloom a tu proporción de aciertos y fallos
- Comprime lo que pueda comprimirse, no lo que tenga mucho tráfico
- Considera la E/S directa
- Elige una caché que resista la contención
- Paraleliza las búsquedas de varias claves en lugar de serializarlas
- Hacia dónde avanzamos
Cuando le contamos a la gente que migramos más de 300 terabytes de datos históricos de Solana de ClickHouse a RocksDB, la reacción casi siempre es la misma: ¿Por qué harían algo así?
ClickHouse es la opción obvia para cargas de trabajo analíticas a escala de petabytes, mientras que RocksDB no lo es.
Algunos de los mayores consumidores de datos del mundo confían en ClickHouse.
Por ejemplo, Cloudflare lo ejecuta en más de mil réplicas para procesar cientos de millones de inserciones por segundo.
Anthropic ejecuta una implementación personalizada y aislada de ClickHouse para sustentar la observabilidad de Claude. Uber, eBay y Bloomberg también lo han usado en producción durante años.
RocksDB, por otro lado, es un almacén clave-valor integrado con poca documentación. Se usa principalmente como motor dentro de otras bases de datos (por ejemplo, CockroachDB, TiKV y MyRocks), en lugar de servir como base directa de un servicio de datos históricos orientado al cliente.
Sin embargo, la migración redujo nuestro almacenamiento comprimido de ~330 TB a ~190 TB, solucionó la larga cola de nuestras consultas más lentas (por ejemplo, la latencia p95 de las llamadas a getTransactionsForAddress bajó de 350 ms a 30 ms) y nos permitió innovar en la capa de lectura de Solana. Esto no habría sido posible con ClickHouse dado el rendimiento y la escala que exige Helius.
Este artículo explica por qué migramos desde ClickHouse, qué aprendimos sobre la carga de trabajo durante el proceso y cómo usamos RocksDB en producción a gran escala.
Qué es el archivo de Solana y por qué importa
En esencia, Solana es una red de nodos que se comunican para acordar información nueva sin tener que confiar unos en otros.
Un nodo es una computadora de Solana que ejecuta un cliente (por ejemplo, Agave o Firedancer) y sigue un conjunto específico de reglas para ayudar a alcanzar un acuerdo sobre información nueva.
Un validador es un nodo de Solana que protege la red produciendo bloques (es decir, agregando grupos de transacciones al libro mayor de Solana) y votando sobre la validez de otros bloques.
Los nodos RPC son validadores que no participan en la producción de bloques ni en las votaciones. En cambio, observan la red y rastrean toda la información nueva que produce. Los RPC permiten consultar datos específicos de la red mediante la especificación JSON-RPC.
Sin embargo, estos nodos no conservan los datos para siempre.
Para cumplir con los requisitos de hardware de Solana, se eliminan los bloques, las transacciones y los estados de cuenta más antiguos. Así, los nodos solo conservan la vista más reciente del historial de Solana.
Esto causa problemas al intentar buscar una firma de transacción de hace un año, obtener todas las firmas que alguna vez interactuaron con una cartera durante toda su existencia o examinar el historial completo de ejecución de un programa.
En términos generales, el archivo se refiere a toda la capa que almacena los datos de Solana desde el bloque génesis. Registra e indexa todo lo que produce la cadena —cada bloque, transacción, interacción con cuentas, invocación entre programas (CPI) y registro de transacción— y permite consultarlo más allá de la ventana estándar de almacenamiento a corto plazo de ~2 días (es decir, 1 época).
El archivo hace posibles las consultas históricas.
El enfoque predeterminado para almacenar datos históricos en Solana ha sido Google BigTable. Anza mantiene una instancia de BigTable a la que los proveedores de RPC pueden acceder bajo demanda para responder consultas históricas.
Funciona, pero BigTable es costoso, los costos de transferencia hacen que ejecutar tu propia copia sea complicado y casi no puedes hacer trabajo de ingeniería por tu cuenta para acelerarlo. Estás a merced del almacenamiento de Google, con toda su estructura de costos y sin ningún control.
Old Faithful es un conjunto de herramientas mantenido por Triton One que puede producir archivos direccionables por contenido (CAR) a partir de archivos RocksDB del libro mayor y servirlos mediante las interfaces RPC y gRPC estándar de Solana. Es un avance importante hacia la descentralización de la capa de archivo de Solana y ofrece una valiosa fuente de historial redundante y verificable.
Sin embargo, sus desventajas en cuanto a experiencia del desarrollador y rendimiento (por ejemplo, para comenzar se necesitan herramientas personalizadas en lugar de interfaces sobre las que los equipos puedan desarrollar, y está optimizado para el archivo duradero, no para el rendimiento y la escala) impiden que sea una alternativa viable para cargas de trabajo sensibles a la latencia.
El problema central del archivo es que tienes N petabytes de datos sin procesar. Con más de 500 mil millones de transacciones, ~1,3 billones de filas en índices de cuenta a transacción y patrones de acceso aleatorio, ¿cómo se logran búsquedas en menos de 10 ms? ¿Cómo son las consultas completas de menos de 50 ms? Ni Google BigTable ni Old Faithful ofrecen una solución para esto.
Además, si quisieras crear opciones personalizadas de filtrado y ordenamiento, o mejorar la experiencia del desarrollador ofreciendo algo más completo que los métodos JSON-RPC estándar, necesitarías tu propio índice histórico.
Así que construimos uno.
ClickHouse: la primera apuesta pragmática
ClickHouse era el punto de partida más pragmático para desarrollar nuestro nuevo sistema de archivo. Era la vía más rápida para lanzar un producto que ya fuera mejor que uno construido sobre BigTable.
ClickHouse es una base de datos columnar madura, con excelentes herramientas y documentación. Comprime bien los datos de series temporales, algo especialmente útil para Solana porque los datos de sus bloques están ordenados temporalmente por naturaleza.
Es sencillo crear una base de datos, escribir SQL, iterar sobre los esquemas y optimizar el tiempo de comercialización. Así, los clientes pueden tener un producto frente a ellos con relativa rapidez.
ClickHouse no gestionaba el tráfico por sí solo. Era el nivel inferior de nuestra pila de almacenamiento, organizada según la antigüedad de los datos.
Los datos más recientes (aproximadamente el último minuto o dos, o unos cientos de slots) estaban en un almacén en memoria. Aproximadamente las últimas dos semanas de datos estaban en Postgres. ClickHouse almacenaba el resto del historial de Solana.
Un router inteligente se ubicaba frente a las tres fuentes. Enviaba las búsquedas puntuales al nivel más reciente que contenía los datos, mientras dividía las consultas de rango entre niveles y luego unía todo en un solo resultado.
ClickHouse funcionaba relativamente bien para las cargas de trabajo que debía procesar. Por ejemplo, «dame todos los bloques de este rango de slots» o «examina la actividad de esta cuenta a lo largo del tiempo».
Las consultas de series temporales funcionaban bien. Podíamos completar datos históricos, ejecutar análisis ad hoc y responder la mayoría de las preguntas que tradicionalmente han necesitado los proveedores de RPC. La ingesta nunca tuvo dificultades: solo escribíamos ~10 MB/s en nuestro índice mediante LaserStream.
El error al elegir ClickHouse no fue haber elegido ClickHouse. Fue asumir que nuestra carga de trabajo conservaría una forma que ClickHouse pudiera procesar a escala.
Dónde dejó de funcionar ClickHouse
No todos los métodos históricos de Solana que nos importan son de series temporales. Una firma en Solana (es decir, el identificador universal de una transacción) es, en esencia, un conjunto de 64 bytes de datos aleatorios.
Cuando alguien llama a getTransaction para una firma determinada, se trata de una búsqueda puntual uniformemente aleatoria. No hay ningún slot, rango temporal ni otro tipo de localidad que se pueda aprovechar.
Lo mismo ocurre con otras consultas, como «obtén todas las firmas que interactuaron con esta cuenta», porque la clave de la cuenta también es, en la práctica, aleatoria. Este problema aparece siempre que una clave primaria es un UUID, un hash u otro identificador de alta entropía.
Los motores columnares no están diseñados para resolver este problema.
ClickHouse almacena los datos en partes ordenadas y usa índices primarios dispersos. Esto significa que no hay mucho que descartar al buscar una clave aleatoria. En algún momento, terminarás leyendo más gránulos de los deseados. Una sola búsqueda de firma podía tocar 20 gránulos —alrededor de 10 000 filas y ~60 operaciones de E/S en disco— antes de cualquier búsqueda binaria o sobrecarga de CPU.
Solo por las operaciones de E/S, eso representa aproximadamente 5 ms por búsqueda. Como el almacén es columnar, leer una transacción implica leer ~15 columnas como operaciones de E/S independientes en un gránulo de 512 filas.
Esto significa que una llamada a getTransactionsForAddress que solicita los detalles completos de las transacciones, por ejemplo, se expande hasta realizar 100 de esas búsquedas. Esto eleva el límite mínimo de latencia a cerca de 100 ms antes de serializar un solo byte.
Un lote grande de getTransaction (es decir, de hasta 1000) elevaba ese límite mínimo a casi un segundo completo.
Las abstracciones que aceleran los escaneos (por ejemplo, la ejecución vectorizada y la materialización tardía) no resuelven el problema por completo. Las búsquedas ya estaban tan optimizadas como era posible. No nos faltaba un índice. No había ninguna proyección que pudiéramos agregar.
En pocas palabras, la disposición fundamental de los datos era incorrecta para lo que le pedíamos hacer.
Los métodos más costosos que habíamos agregado (por ejemplo, getTransactionsForAddress y getTransfersByAddress) seguían los patrones de claves aleatorias que ClickHouse procesaba peor.
Algunas de estas consultas tardaban entre 2 y 3 segundos, aunque deberían haber tardado apenas milisegundos. Recibíamos alertas por la degradación del rendimiento en cargas de trabajo que no podíamos solucionar de raíz.
Dado que instituciones y clientes empresariales usan Helius a escala, esto es completamente inaceptable a largo plazo.
Escalar ClickHouse para esta carga de trabajo implicaba aumentar la cantidad de servidores y, a nuestra escala, multiplicar varias veces la carga de trabajo. Invertir más dinero únicamente en hardware no resolvería el problema.
La pila RPC de Solana está madurando. El ecosistema llegó a un punto de inflexión en el que los métodos JSON-RPC estándar ya no bastan. Los clientes exigen consultas históricas avanzadas y nadie más iba a construirlas sobre BigTable.
Si queríamos ampliar esa frontera, teníamos que cambiar la capa de almacenamiento.
RocksDB: no es una base de datos
A pesar de su nombre, RocksDB no es una base de datos. Es una biblioteca.
No tiene lenguaje de consultas, protocolo cliente/servidor, motor SQL, uniones ni índices en el sentido tradicional de una base de datos. Es una interfaz que dice: «Aquí tienes una clave (algunos bytes) y un valor (también algunos bytes); guárdalos en el disco y, más adelante, devuélveme el valor de esta clave». Eso es todo.
Es una primitiva. Podría decirse que es la primitiva para construir motores de almacenamiento.
Todo lo que se espera de una base de datos tradicional (por ejemplo, un planificador de consultas, un protocolo de red, replicación y observabilidad) debe construirse.
Esto parece una desventaja hasta que entiendes lo que te ofrece. Un almacén clave-valor puro, respaldado por un árbol de fusión estructurado por registros (LSM) en disco, tiene exactamente la forma adecuada para realizar búsquedas de claves uniformemente aleatorias con alto rendimiento. No hay un planificador de consultas que agregue sobrecarga, supuestos de una disposición columnar que deban conciliarse ni una interfaz SQL cuyo costo haya que contemplar.
Guardas bytes, los vuelves a leer y colocas filtros de Bloom y cachés en los lugares adecuados para que las lecturas aleatorias sean económicas.
Aquí es exactamente donde se desmorona la idea de que se trata de un antipatrón.
No reemplazamos ClickHouse con RocksDB; reemplazamos ClickHouse con una base de datos personalizada cuyo motor de almacenamiento es RocksDB. Es algo significativamente distinto.
También es el mismo patrón que usa internamente la mayoría de las bases de datos de producción. Por ejemplo, CockroachDB, TiKV, MyRocks y los almacenes de estado de Kafka Streams están construidos sobre RocksDB.
La diferencia es que primero lo envuelven en otra base de datos, mientras que nosotros construimos la base de datos a su alrededor y la ajustamos para los patrones de acceso exactos que exige el archivo.
Cómo resuelve RocksDB las limitaciones de ClickHouse
Entonces, ¿cómo resuelve exactamente un almacén clave-valor el problema de las claves aleatorias que un motor columnar no pudo resolver? Todo depende de cómo se almacenan los bytes en el disco.
RocksDB usa compactación por niveles. Las escrituras nuevas llegan al nivel 0, un depósito sin ordenar —en la práctica, la misma situación que ClickHouse— donde las partes de una partición no están ordenadas globalmente.
Sin embargo, los niveles del 1 al N son secuencias completamente ordenadas. Una vez compactados los datos, los metadatos mínimos/máximos sí descartan partes de la búsqueda, incluso para claves uniformemente aleatorias, porque el nivel está ordenado globalmente. En cierto sentido, todo en ClickHouse se comporta como el nivel 0 de RocksDB.
Aprovechamos esto para completar nuestros datos históricos.
Cuando construimos el índice de firmas, ordenamos todo el historial de antemano y lo cargamos directamente en el nivel inferior. A partir de ahí, solo los datos nuevos llegan al nivel 0 y se fusionan rápidamente con los niveles inferiores.
El resultado es que casi todas las búsquedas leen una sola secuencia ordenada. En la práctica, ordenamos datos aleatorios con RocksDB.
Lo que construimos encima
ClickHouse incluye muchas funciones listas para usar: un motor de consultas, un protocolo de red, un cliente y una forma de servir datos. RocksDB no incluye ninguna de estas opciones; simplemente conserva bytes. Tuvimos que construir todo lo demás.
Así que construimos nuestra propia base de datos sobre RocksDB, especializada en los patrones de acceso al archivo de Solana.
Hoy existen dos índices en RocksDB:
- Firma -> Ubicación (es decir, el índice de firmas, que asigna la firma de 64 bytes de una transacción al slot y la posición donde se encuentra dentro del bloque).
- Slot -> Bloque (es decir, el índice de slot a bloque, que asigna la ubicación anterior a los datos de la transacción).
Es importante destacar que no hay una ruta directa desde una firma hasta los datos de su transacción. Resolver esa limitación es precisamente la razón por la que existen estos dos índices.
Una firma es, en esencia, un identificador aleatorio de 64 bytes. Lo que realmente indica dónde está una transacción es su slot y su índice dentro de ese bloque. Por eso, obtener una transacción requiere dos saltos (uno para resolver la firma a una ubicación determinada y otro para recuperar los detalles de la transacción desde esa ubicación), mientras que obtener un bloque solo requiere un salto porque quien llama ya proporciona el slot.
Juntos, estos índices sustentan algunos de los métodos más pesados que sirve Helius (por ejemplo, getBlock, getTransaction y getTransactionsForAddress, especialmente cuando details se establece en full).
La ruta de lectura se parece mucho a la de ClickHouse. Llega una solicitud, nuestro cliente interno realiza una llamada a la base de datos y se devuelve el resultado. Lo que cambia es el motor subyacente. Cada método sigue una ruta codificada de forma explícita y ajustada manualmente. Cuando un usuario consulta una transacción, una ruta getTransaction diseñada específicamente conduce directamente a los bytes.
Esta ruta es rápida porque controlamos cada una de sus capas. Usamos io_uring para la E/S de archivos y red al transmitir datos desde RocksDB. Cuando los datos están sin comprimir en el disco, los copiamos directamente del disco a la tarjeta de red, sin desviarlos por el espacio de usuario.
Los métodos están codificados de forma explícita, la E/S está ajustada de extremo a extremo y no hay componentes innecesarios en medio.
Los beneficios son evidentes en producción.
Hace poco mantuvimos 150 Gbit/s de tráfico de getBlock durante cinco o seis horas seguidas, mientras saturábamos la mayoría de nuestras tarjetas de red. Cero problemas, cero alertas y el mismo rendimiento bruto.
En términos generales:
- El almacenamiento comprimido se redujo casi a la mitad, de ~330 TB a ~190 TB
- La latencia P95 de las llamadas a
getTransactionbajó de 7 ms a 1 ms - La latencia P95 de las llamadas a
getTransactionsForAddressbajó de 350 ms a 30 ms - La latencia P95 de las llamadas a
getBlockbajó de 50 ms a 35 ms
Como esperábamos, las llamadas a getBlock fueron las que menos mejoraron. ClickHouse ya almacena las transacciones en fragmentos de 512 filas, lo que distribuye la penalización columnar en lecturas del tamaño de un bloque. Gran parte del tiempo de extremo a extremo de getBlock se dedica a la codificación Base58 y JSON, y a reconstruir el bloque. Por eso, cambiar el motor de almacenamiento no acelerará ese proceso.
La historia más profunda —cómo logramos que io_uring, Rust asíncrono y una biblioteca síncrona como RocksDB cooperaran bajo una carga de red de alto rendimiento— merece su propia publicación futura.
Sin embargo, la siguiente sección analiza algunas optimizaciones que nos han resultado útiles al trabajar con RocksDB.
Optimización de RocksDB a escala
No existe una única configuración «rápida» de RocksDB. Los ajustes correctos dependen por completo del patrón de acceso del índice que se esté optimizando.
Nuestro índice de firma -> ubicación y nuestro índice de slot -> bloque se ejecutan en el mismo proceso y hardware, pero requieren ajustes casi diametralmente opuestos.
Por eso, en lugar de entregar un archivo de configuración con ajustes que quizá no funcionen para tu carga de trabajo, esta sección explica cómo razonamos sobre las concesiones que sí se pueden aplicar a otros casos.
Ajusta por índice, no por base de datos
Cada uno de nuestros índices es su propia familia de columnas con sus propias opciones. Uno realiza búsquedas puntuales uniformemente aleatorias; el otro obtiene en orden valores grandes y comprimibles. Tratarlos de la misma manera habría desaprovechado muchas optimizaciones de rendimiento. Casi todas las decisiones descritas a continuación deben interpretarse así: «para este patrón de acceso, haz X».
Decide si realmente necesitas WAL
Los datos históricos pueden reconstruirse. Es decir, llegan mediante streaming desde LaserStream y se derivan de la propia cadena.
Escribimos con el registro de escritura anticipada (WAL) desactivado, por lo que no pagamos el costo de una durabilidad de escritura anticipada que no necesitamos.
El detalle es que desactivar WAL también deshabilita la consistencia predeterminada de RocksDB ante fallos entre familias de columnas, por lo que se debe restaurar la consistencia de otra manera. La lección es que los ajustes de durabilidad deben corresponder con la capacidad de recuperación de tus datos. Los datos que pueden reconstruirse desde una fuente ascendente tienen requisitos muy distintos a los de un sistema de registro.
Adapta los filtros de Bloom a tu proporción de aciertos y fallos
Los filtros de Bloom justifican su uso de memoria al determinar de forma económica si una clave no está presente en una búsqueda. Esto significa que solo ayudan cuando hay fallos.
Una búsqueda de firma casi siempre es un acierto porque quien llama tiene una firma y quiere los datos de la transacción correspondiente.
El nivel inferior del LSM contiene la inmensa mayoría de nuestros datos. Cuando casi todos tus datos están en un solo nivel y tu carga de trabajo está dominada por aciertos, los filtros de ese nivel consumen la mayor cantidad de memoria y hacen la menor cantidad de trabajo. En esa situación, conviene preguntarte si realmente los necesitas allí.
Comprime lo que pueda comprimirse, no lo que tenga mucho tráfico
La compresión es una decisión específica de cada índice. Los datos de alta entropía, como una firma de 64 bytes, no se comprimen por debajo de una proporción de 1,0. Esto significa que la compresión solo agregaría el costo de descompresión a la ruta crítica de cada búsqueda. Por eso establecemos la compresión en None.
En cambio, los datos de bloques se comprimen bien porque son más voluminosos y repetitivos. Por eso, nuestro índice de slot -> bloque usa zstd. Observa que ambos índices usan la misma base de datos, pero se benefician de decisiones diferentes. Todo depende de si los bytes pueden comprimirse y de si el índice está limitado por la latencia o por el almacenamiento.
Esta división por índice explica en gran medida por qué pudimos reducir nuestro uso de ~330 TB a ~190 TB sin perjudicar la latencia de las búsquedas puntuales.
Considera la E/S directa
Leemos con E/S directa y también la usamos para el vaciado y la compactación. A esta escala, la caché de páginas del sistema operativo compite con nuestra propia caché de bloques por la misma RAM. Para las búsquedas puntuales aleatorias, ese almacenamiento doble en caché suele ser un desperdicio. Preferimos tener una sola caché de bloques grande que podamos controlar y que ofrezca una latencia predecible.
Ten en cuenta que esto depende de la carga de trabajo:
La E/S directa puede perjudicar las configuraciones centradas en escaneos o con pocos recursos. Por eso conviene realizar pruebas A/B en lugar de adoptarla a ciegas.
Elige una caché que resista la contención
Bajo una carga concurrente intensa sobre claves con mucho tráfico, la caché LRU compartida estándar se convierte en un cuello de botella por la contención de bloqueos. Usamos HyperClockCache de RocksDB para los índices con mucho tráfico, ya que funciona mucho mejor cuando numerosos hilos acceden simultáneamente a las mismas entradas populares.
Paraleliza las búsquedas de varias claves en lugar de serializarlas
En lugar de serializar N lecturas, RocksDB puede emitir muchas operaciones de E/S simultáneamente mediante io_uring y permitir que se completen en paralelo. Para un método como getTransactionsForAddress, que se expande en muchas búsquedas puntuales subyacentes, esta es la diferencia entre una latencia que aumenta con el número de claves y una que permanece casi igual.
RocksDB ofrece todas las opciones, pero no hace suposiciones sobre tus datos. Nuestras mejoras provienen de comprender nuestros patrones de acceso y ajustar cada índice a sus propias características, en lugar de buscar una única configuración global que sea buena para todo.
Hacia dónde avanzamos
Hoy, el archivo funciona desde nuestras regiones más grandes, como EWR, FRA y Tokio. Ahora que el motor de almacenamiento devuelve búsquedas en microsegundos y satura nuestras tarjetas de red, la base de datos ya no es lo que nos quita el sueño. Resolver un cuello de botella suele revelar el siguiente.
Cuando una búsqueda es prácticamente gratuita, el costo dominante pasa del software a la distancia entre el usuario y la máquina. Una solicitud aún debe viajar desde la ubicación del usuario hasta nuestro backend y regresar. En ese punto, estás luchando contra la física.
Ese es el problema que resuelve Gatekeeper.
Gatekeeper es nuestro gateway perimetral interno, escrito en Rust sobre Hyper, que finaliza conexiones cerca de los usuarios y enruta cada solicitud a nuestro backend por la ruta disponible más corta. Ahí se libra ahora la guerra contra la latencia: agrupación de conexiones, ajuste de TLS y sockets, enrutamiento basado en proximidad y estado, e implementaciones sin tiempo de inactividad en toda nuestra infraestructura global. Todo para recortar milisegundos de la ruta hacia bytes que el archivo ya sirve en microsegundos.
Acelerar una sola solicitud es un problema de base de datos. Acelerar todas las solicitudes desde cualquier lugar del mundo, sin ventanas de mantenimiento ni conexiones interrumpidas, es un problema completamente distinto. También es nuestro próximo objetivo.
A esto nos referimos con innovar en la capa de lectura de Solana: optimizar cada capa, desde el motor de almacenamiento que responde las búsquedas hasta el gateway perimetral que determina con qué rapidez llega esa respuesta al usuario final.
En última instancia, el archivo consiste en búsquedas puntuales de claves aleatorias. Es el patrón de acceso que rompe un motor columnar por razones estructurales. No es una cuestión de ajustes, fragmentación ni de cómo se ordenan las vistas. Las limitaciones que encontramos con ClickHouse son inherentes a esta elección y no un efecto incidental de la configuración. La carga de trabajo histórica de Solana se define por su patrón de acceso más difícil, no por el más sencillo.
A la escala de una red que busca convertirse en la capa de liquidación de las finanzas globales, la capa de lectura no puede limitarse a ser una versión mejor ajustada de la que ya superamos. Las instituciones y aplicaciones que dependen de consultas históricas avanzadas necesitan métodos, cobertura y latencias que la pila predeterminada no puede ofrecer. La capa de lectura de Solana debe construirse desde el principio sobre una base adecuada para el caso difícil. Esa fue nuestra apuesta con RocksDB y es el estándar que aplicamos a todo lo demás.
Si te interesa construir el futuro de las finanzas a escala, ven a construirlo con nosotros. Solana avanza rápidamente para convertirse en la capa de liquidación de las finanzas globales, y el archivo es solo una pieza de un rompecabezas mucho más grande. Si te interesan la compactación LSM y los ajustes por índice, o resolver problemas complejos de sistemas en algunos de los mejores equipos que el dinero puede comprar, te sentirás como en casa.
Estamos contratando para distintos puestos de nuestro equipo de ingeniería. Consulta todas nuestras vacantes en helius.dev/careers.
Artículos relacionados
Suscríbete a Helius
Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos


