4 puntos por GN⁺ 2024-03-20 | 1 comentarios | Compartir por WhatsApp
  • Garnet es un almacén de caché remota creado por Microsoft Research que se basa en el protocolo wire RESP, por lo que se pueden usar clientes existentes de Redis sin modificaciones
  • Ofrece mayor rendimiento y escalabilidad que almacenes de caché open source comparables cuando hay muchas conexiones de clientes y lotes pequeños, y en Azure VM con Accelerated Networking activado, la latencia en el percentil 99.9 suele ser menor a 300 microsegundos
  • Está basado en .NET moderno, funciona en Linux y Windows, permite crear operaciones personalizadas, procedimientos almacenados y módulos en C#, y también admite scripts Lua
  • La capa de almacenamiento Tsavorite admite jerarquización entre memoria, SSD y almacenamiento en la nube, checkpoints no bloqueantes, recuperación, log de operaciones para durabilidad, transacciones multi-clave, y en modo clúster, sharding, replicación y migración dinámica de claves
  • Como funciones nuevas, se añadieron Vector Sets Preview y Range Index Preview, y el artículo de Garnet será publicado en VLDB 2026

Un almacén de caché remota que ofrece Garnet

  • Garnet es un nuevo almacén de caché remota de Microsoft Research
  • Adopta como punto de partida el protocolo wire RESP, por lo que se pueden usar sin cambios clientes existentes de Redis en varios lenguajes de programación
  • Ofrece mejor rendimiento y escalabilidad que almacenes de caché open source comparables cuando hay muchas conexiones de clientes y lotes pequeños, lo que puede traducirse en reducción de costos para apps y servicios a gran escala
  • En Azure VM típicas, al activar Accelerated Networking, la latencia del cliente en el percentil 99.9 suele ser menor a 300 microsegundos
  • Está basado en tecnología .NET moderna y apunta a una arquitectura multiplataforma, extensible y moderna
    • Fue diseñado para facilitar el desarrollo y la evolución sin sacrificar el rendimiento en los casos de uso comunes
    • Aprovecha el ecosistema de bibliotecas .NET para ampliar el alcance de la API y dejar margen para optimizaciones
    • Logra rendimiento de primer nivel tanto en Linux como en Windows
  • Si se necesita un servicio totalmente administrado, Azure Cosmos DB Garnet Cache ofrece Garnet como una solución de caché empresarial con alta disponibilidad, rendimiento garantizado y sin gestión de infraestructura

Funciones añadidas recientemente y artículo

  • Vector Sets Preview ofrece búsqueda aproximada de vecinos más cercanos
    • Está basado en el algoritmo DiskANN y en el motor de almacenamiento Tsavorite de Garnet
    • En resultados iniciales, Garnet mostró mejores métricas en QPS, latencia p99 y recall
  • Range Index Preview ofrece índices secundarios de rango e igualdad sobre claves de Garnet
  • El artículo de Garnet será publicado en VLDB 2026
    • El título del artículo es Garnet: A Next-Generation Cache-Store for Accelerating Applications and Services
    • Está disponible el PDF

API y modelo de extensión

  • Garnet implementa varias API
    • Cadenas simples: get, set, expiración de claves
    • Operaciones analíticas: HyperLogLog, Bitmap
    • Operaciones sobre objetos: sorted set, list, etc.
  • Admite transacciones multi-clave
    • Transacciones RESP del lado del cliente
    • Procedimientos almacenados y módulos del lado del servidor basados en C#
  • Los usuarios pueden crear operaciones personalizadas tanto para cadenas simples como para tipos de objetos personalizados
    • Aprovecha la comodidad y seguridad de C# para bajar la barrera de entrada al desarrollo de extensiones personalizadas
  • También admite scripts Lua

Red, seguridad y capa de almacenamiento

  • Garnet usa una capa de red rápida y conectable
    • Esto permite futuras extensiones, como el uso de stacks de kernel bypass
  • Para comunicaciones seguras, admite TLS usando la biblioteca SslStream de .NET
  • Ofrece control de acceso básico
  • La capa de almacenamiento Tsavorite fue diseñada para alto rendimiento e incluye varias funciones de base de datos
    • Escalabilidad por hilos
    • Almacenamiento jerárquico que incluye memoria, SSD y almacenamiento en la nube
    • Checkpoints rápidos no bloqueantes
    • Recuperación
    • Log de operaciones para durabilidad
    • Transacciones multi-clave
    • Mejor gestión y reutilización de memoria

Estructura de diseño

  • El diseño de Garnet replantea toda la pila del almacén de caché, desde la recepción de paquetes de red hasta el parseo y procesamiento de operaciones de base de datos y la interacción con el almacenamiento
  • La capa de red se basa en un diseño de memoria compartida
    • El procesamiento TLS y la interacción con el almacenamiento se realizan en el hilo de finalización de IO de red
    • En los casos comunes, evita el overhead del cambio de hilos
    • En lugar de mover los datos al shard adecuado del servidor como en diseños de red tradicionales basados en shuffle, la coherencia de caché de CPU hace que los datos lleguen hacia la lógica de procesamiento
  • El diseño de almacenamiento está compuesto por dos almacenes clave-valor Tsavorite unidos por un log de operaciones integrado
    • El main store está optimizado para operaciones con cadenas simples y administra cuidadosamente la memoria para evitar garbage collection
    • El object store opcional está optimizado para objetos complejos y tipos de datos personalizados
    • El object store incluye tipos como Sorted Set, Set, Hash, List y Geo
    • Los tipos de datos del object store aprovechan actualmente el ecosistema de bibliotecas .NET
    • Los objetos se almacenan en el heap de memoria en una forma eficiente para actualizaciones y en disco en forma serializada
  • En el futuro, planean evaluar el uso de índices y logs unificados para facilitar el mantenimiento
  • Un diferenciador de Garnet es la API de almacenamiento Tsavorite de cintura estrecha
    • Sobre esta API implementa una superficie RESP amplia, rica y extensible
    • Está compuesta por operaciones de lectura, upsert, eliminación y read-modify-write atómico
    • Mediante callbacks asíncronos, la lógica de Garnet puede intervenir en varios puntos de cada operación
    • Separa las preocupaciones de parseo y procesamiento de consultas de los detalles de almacenamiento, como concurrencia, jerarquización del almacenamiento y checkpoints
  • Para las transacciones multi-clave usa bloqueo en dos fases

Modo clúster y limitaciones operativas

  • Además de ejecutarse en un solo nodo, Garnet admite modo clúster
    • Se pueden crear y administrar despliegues con sharding y replicación
    • Admite un método eficiente y dinámico de migración de claves para rebalanceo de shards
  • Los usuarios pueden crear y administrar clústeres de Garnet con comandos estándar de clúster de Redis
  • Los nodos hacen gossip para compartir y evolucionar el estado del clúster
  • El diseño del modo clúster de Garnet es actualmente pasivo
    • No implementa elección de líder
    • Responde a comandos de clúster emitidos por un control plane provisto por el usuario
    • Hay más información en la documentación del control plane

Documentación y licencia

1 comentarios

 
GN⁺ 2024-03-20
Comentarios de Hacker News
  • Al ver la gráfica de rendimiento de benchmarking(https://microsoft.github.io/garnet/docs/benchmarking/results...), el throughput de GET es más de 10 veces mayor que el de Dragonfly
    La latencia al percentil 50 es un poco más alta que en Dragonfly, pero el percentil 99 es un poco más bajo
    Tanto Garnet como Dragonfly tienen mucho mejor throughput y latencia que Redis, así que parece que Redis necesita una optimización de rendimiento considerable

    • Redis es single-threaded, así que es simple y efectivo
      No sé si realmente necesite optimización, y aquí ya hay 3 alternativas
      Aun así, impresiona que Garnet sea la primera alternativa que supera a Redis tanto con baja concurrencia como con alta concurrencia, y quiero probarlo pronto
    • Lo más sorprendente es que este proyecto fue desarrollado en C#
      Dragonfly está escrito en C++ y Redis en C
    • Sorprende que Garnet, hecho en C#, un lenguaje con recolección de basura, haya superado a Redis/Dragonfly
  • Tsavorite, la capa de almacenamiento de Garnet, se derivó del FASTER de código abierto e incluye funciones sólidas de base de datos como escalabilidad de hilos, almacenamiento por niveles (memoria, SSD, almacenamiento en la nube), checkpoints rápidos sin bloqueo, recuperación, logs de trabajo para durabilidad, transacciones multi-clave, y mejor administración y reutilización de memoria
    https://www.microsoft.com/en-us/research/blog/introducing-ga...

    • Hace tiempo seguí la implementación de FASTER
      En ese momento me pareció bastante prometedor como librería de persistencia para un proyecto de prueba de concepto con requisitos de alto rendimiento en el que estaba trabajando
      Por cierto, parece que la misma persona lidera ambos proyectos [1]
      [1]: https://github.com/badrishc
    • Otro proyecto open source hecho por Microsoft
  • Son bastante impresionantes los proyectos que Microsoft y el equipo de .NET construyen directamente, casi como si estuvieran hackeando infraestructura
    Yarp es una herramienta para reverse proxy/API gateway/cualquier otra cosa que se necesite, y ahora Garnet es para caché en memoria
    Se nota que tienen una demanda interna enorme y también voluntad de compartirlo

  • Ojalá algo así viniera integrado en Azure App Service
    Para que no sea obligatorio usar un servicio remoto solo por el caché
    Antes era común tener un almacenamiento de estado de sesión fuera del proceso para apps ASP.NET en IIS
    La idea era que, aunque el proceso de la app web se reiniciara, el usuario no perdiera la sesión ni tuviera que volver a iniciar sesión desde cero
    Claro, también se puede poner en un almacenamiento central como SQL Server, pero entonces cada request de la página web tiene que esperar a que se cargue el estado de sesión antes de procesarse
    El estado de sesión normalmente se bloquea de una forma u otra, así que también hay muchos problemas de rendimiento
    La solución habitual hoy es usar Redis para caché y estado de sesión, y en general funciona más o menos bien
    El throughput es alto, pero Redis es un recurso separado en Azure y es ridículamente caro
    No quiero pagar precios de Oracle DB por algo tan simple, y además configurar la conexión es bastante engorroso
    El artículo habla de tiempos de respuesta de 300 microsegundos, pero en un diseño con redundancia entre zonas eso no significa mucho, porque todos los balanceadores de carga de Azure usan selección aleatoria de zona
    Se elige un servidor web de una zona aleatoria, y luego este se conecta a un servidor de caché de otra zona aleatoria
    Si ese servidor no tiene la clave, quizá tenga que ir a otra zona aleatoria más para traer los datos del caché
    El tráfico termina rebotando entre datacenters, y eso mete una latencia de 1 a 3 ms, hasta 10 veces más lenta que las cifras que publicita Garnet
    El escenario ideal sería algo como las reliable collections de Microsoft Service Fabric[1]
    Corre localmente en cada nodo host y se replica a otros dos nodos
    La app web siempre puede leer el valor del caché desde el mismo host físico
    En algunos casos la latencia baja a microsegundos de un solo dígito, y hasta el mejor servicio externo optimizado sería miles de veces más lento con un balanceo de carga simple
    No quiero algo 30% más rápido que Redis, quiero algo 3,000 veces más rápido
    [1] https://learn.microsoft.com/en-us/azure/service-fabric/servi...

    • Por eso me gusta Kubernetes con Cilium
      Puedes hacer que un servicio siempre vaya al servicio local, o configurarlo con otra topología de enrutamiento
      Es muy bueno para DNS o caché de aplicación
  • Es un reemplazo de Redis con cifras de benchmarking bastante impresionantes en latencia y throughput
    Me da curiosidad cómo se verá en producción real sobre un stack que no sea Azure

    • No estoy seguro de que de verdad sea un drop-in replacement
      No veo ninguna indicación de soporte para xstream
  • Garnet being multi-threaded, MSET is not atomic. For an atomic version of MSET, you would need to express it as a transaction (stored procedure).
    Esta parte no me queda muy clara
    ¿Por qué no envolver internamente eso en una transacción para que el comando sea atómico?
    También me pregunto qué otras trampas de atomicidad podría haber

    • Si hicieran eso, incluso quienes no necesitan la atomicidad de MSET pagarían un costo de rendimiento, y no habría forma de desactivar esa transacción
      Por otro lado, si el objetivo es ser un reemplazo drop-in de Redis, entonces esto sí es un problema porque Redis garantiza atomicidad
      Al menos, si la compatibilidad drop-in es un objetivo de diseño, parecería razonable ofrecer una opción de configuración para elegir entre compatibilidad y rendimiento
  • Definitivamente es impresionante
    Microsoft Research a veces saca proyectos tremendos, y debe ser divertido que te paguen por hacer I+D
    Ojalá las grandes empresas hicieran más proyectos de investigación y desarrollo que beneficien a toda la industria
    Si Hashicorp está en venta, ojalá la compre una buena empresa

  • Es una excelente noticia para quienes necesitan correr directamente un servidor compatible con Redis en Microsoft Windows Server sin depender de WSL2
    Antes existía un port de Redis[1], pero ahora está archivado, tenía problemas de uso de memoria (hasta donde sé, principalmente por archivos memory-mapped), y ya no tiene soporte
    El hecho de que esté escrito en C# también me resulta bastante interesante a nivel personal
    Como C# es mi lenguaje principal, me gustaría hacer tiempo para revisar el código
    [1]: https://github.com/microsoftarchive/redis

  • Me gustaría ver dónde se está usando esto en producción real
    Hay una parte que dice: “After thousands of unit tests and several years of running Garnet in production deployments with Microsoft's 1st-party teams, we felt it was time to make it public”
    https://microsoft.github.io/garnet/blog

  • Viendo los comentarios aquí, parece que ya nadie usa memcached

    • La última vez que lo usé habrá sido por 2016, y configurarlo no era precisamente fácil
      Quería un caché LRU, pero había varias opciones y la explicación no era muy clara, así que no entendía por qué seguía expulsando elementos
      Cuando cambié a Redis, la configuración fue más fácil y funcionó como esperaba