
Dragonfly 2.0 contra Redis 8 y Valkey 9: con 2 CPU gana por mucho, con 4 depende de cómo configures a los otros
Medí Dragonfly 2.0, Redis 8.10 y Valkey 9.1 en contenedores con 2 y 4 CPU. Con io-threads activados, Redis y Valkey alcanzan a Dragonfly sin pipeline y lo superan con pipeline 16; con 2 CPU y sin pipeline, Dragonfly gana entre 59 % y 99 % sobre Redis por defecto. Usa 8 a 15 % menos memoria por clave.
El 18 de septiembre, heise anunciaba Dragonfly 2.0 con el titular “Redis und Valkey im Visier”. No encontré ninguna mención de esa versión en Hacker News ni en los foros que reviso. Las notas de la release v2.0.0, del 16 de septiembre, dicen que no trae funciones mayores nuevas y que marca un hito de madurez. Así que no había novedad que probar: había una promesa vieja que verificar.
La promesa es que un almacén en memoria con un hilo por núcleo rinde mucho más que Redis. Redis 8 y Valkey 9 ya tienen hilos de E/S, así que la pregunta correcta es con el mismo presupuesto de CPU: ¿cuánto le saca Dragonfly a Redis y a Valkey cuando ellos también usan los núcleos que les das?
Con 4 CPU y sin pipeline los tres superan las 480.000 operaciones por segundo y el banco no los ordena. Con pipeline 16, Redis y Valkey con io-threads ganan (4,21 y 4,04 millones contra 2,73). Con 2 CPU y sin pipeline, Dragonfly gana entre 59 % y 99 % sobre Redis por defecto. Y en memoria ahorra entre 8 y 15 % por clave.
Qué es Dragonfly
Es un almacén en memoria compatible con el protocolo de Redis y de Memcached, escrito en C++ y con licencia BSL 1.1 que pasa a Apache 2.0 el 1 de noviembre de 2030. Lo que lo distingue es la arquitectura: un hilo por núcleo, cada uno dueño de una parte de las claves, sin compartir estado. Redis atiende los comandos en un solo hilo y desde la versión 6 puede repartir la lectura y escritura de sockets en hilos de E/S. Valkey, la bifurcación de Redis, hizo lo mismo.
Medí tres servidores, cada uno solo dentro de su contenedor: Dragonfly v2.0.0, Redis 8.10.1 y Valkey 9.1.2. Redis 8.10.2 salió el 17 de septiembre, pero la imagen redis:8 de Docker todavía traía la 8.10.1 cuando medí, y no existía la etiqueta 8.10.2.
Mismo cliente, mismo espacio de claves (1 M de claves), mismos límites. Lo que cambia es el motor, su ajuste de hilos y, en Dragonfly, el backend de E/S.
El banco y sus tropiezos
Todo corrió en fedora, con un Ryzen 7 7800X3D. Cada servidor va en un contenedor con --cpuset-cpus y --cpus iguales (4 o 2 núcleos), 2 GB y sin persistencia. El cliente es memtier_benchmark 2.5.1, en otro contenedor con sus propios núcleos, por una red bridge. Un millón de claves, valores de 256 bytes, claves al azar, 20 segundos por corrida y 5 corridas por celda. En cada configuración de Redis y Valkey medí dos variantes: por defecto (un hilo) y con --io-threads igual al número de CPU.
Cuatro cosas que salieron mal o que conviene saber:
- Dragonfly cayó a epoll sin que yo lo pidiera. El perfil seccomp por defecto de Docker bloquea
io_uring. El log lo dice: “Check if io_uring is disabled via /proc/sys/kernel/io_uring_disabled. Switching to epoll.” El sysctl del host estaba en 0, y conseccomp=unconfinedel mismo binario abrió el anillo de io_uring. Medí las dos variantes:dragonfly-epollen un Docker normal ydragonfly-uringcon--security-opt seccomp=unconfinedsolo en ese contenedor. - La imagen de Redis 8 trae módulos cargados (ReJSON y búsqueda). Es lo que descarga quien hace
docker run redis:8, y no los desactivé. - Mi primera carga de 4 KiB era inválida. Un millón de valores de 4 KiB son 4 GB y el contenedor tiene 2. El cliente se cayó con Redis y Valkey, y con Dragonfly salió un número sobre un conjunto incompleto. Aparté esas corridas y repetí con 200.000 claves.
- La primera medida de snapshot de Dragonfly no existió. Lo arranqué con el nombre de archivo vacío y respondió
ERR filename is not specified, así que mi guion midió un guardado que nunca ocurrió. Lo rehice con el archivo configurado y con 2 millones de claves.
El host tenía solo unos 5 GB de RAM libres y swap en uso por otro proceso ajeno al banco, y el governor de CPU estaba en powersave. Ninguno de los tres servidores se acercó a esos límites, pero lo digo porque son condiciones de la medida.
Con 4 CPU: sin pipeline hay un techo, con pipeline no
Lecturas y escrituras 10 a 1, 200 conexiones (4 hilos de 50), sin pipeline. Redis y Valkey por defecto, con un hilo, rindieron unas 170.000 operaciones por segundo. Con --io-threads 4, Redis 490.555 y Valkey 481.269. Dragonfly, 491.375 con epoll y 489.604 con io_uring. La latencia p99 de los tres con hilos fue de 0,6 ms, contra 2,3 ms de los servidores de un solo hilo.
Con pipeline 16 el orden cambia: Redis con io-threads llegó a 4.214.020 operaciones por segundo, Valkey a 4.037.297 y Dragonfly a 2.727.721 con epoll y 2.738.973 con io_uring. Es decir, en esa carga Redis fue 1,54 veces más rápido que Dragonfly.
Tiempo real. Los tres con hilos llegan juntos: es el techo del banco, más abajo se explica.
A cuatro veces el tiempo real. Redis y Valkey con hilos ganan.
Tiempo real. Aquí Dragonfly se separa, sobre todo con io_uring.
A cuatro veces el tiempo real. Los tres con hilos empatan.
Tiempo real, 200.000 claves, sin pipeline.
Cada carril se llena en el tiempo que tardó ese servidor en atender un millón de peticiones con la mediana de sus 5 corridas. Cambia de escenario con los botones.
El límite del banco: cuatro servidores, la misma cifra
Que Redis, Valkey y Dragonfly den casi lo mismo sin pipeline con 4 CPU me hizo sospechar del banco antes que de los servidores. memtier mantiene 200 peticiones en vuelo: la siguiente sale cuando llega una respuesta. En un banco así, las operaciones por segundo son las peticiones en vuelo divididas por la latencia media. No son dos medidas: es la misma vista desde dos lados.
- Redis por defecto200 en vuelo ÷ 1,154 ms = 173.310/smemtier reporta 173.194/s
- Valkey por defecto200 en vuelo ÷ 1,202 ms = 166.389/smemtier reporta 166.312/s
- Redis con io-threads 4200 en vuelo ÷ 0,407 ms = 491.400/smemtier reporta 490.555/s
- Valkey con io-threads 4200 en vuelo ÷ 0,415 ms = 481.928/smemtier reporta 481.269/s
- Dragonfly, epoll200 en vuelo ÷ 0,407 ms = 491.400/smemtier reporta 491.375/s
- Dragonfly, io_uring200 en vuelo ÷ 0,408 ms = 490.196/smemtier reporta 489.604/s
Los cuatro servidores con hilos se quedan en 0,41 ms de latencia media. El cliente usó unos 3 núcleos, con un 70 % de su tiempo en el kernel, y los servidores entre 2,4 y 3,0 de 4 (medido en una repetición de 3 corridas, con la cgroup). Ningún componente que yo mida estaba saturado, así que lo que limita es la latencia del camino completo (cliente, red bridge de Docker y servidor), que no puedo separar.
Por eso trato los 490.000 como “al menos” y no como igualdad de capacidad. Lo único que dice la medida es que, con 4 CPU y sin pipeline, los tres pasan de 480.000 y el banco no llega más arriba.
Con esto en mente, el resultado con pipeline 16 sí separa: ahí Redis y Valkey con hilos hicieron unos 4 millones y Dragonfly 2,7, así que el banco tenía margen para ver la diferencia.
Con 2 CPU: aquí Dragonfly sí gana
Para quitarle protagonismo al cliente reduje el servidor a 2 núcleos y le di 6 al cliente (6 hilos de 34 conexiones: 204). Sin pipeline:
- Redis por defecto, 172.081 operaciones por segundo. Con
--io-threads 2, 174.196 (+1,2 %). - Valkey por defecto, 171.208. Con
--io-threads 2, 169.653 (−0,9 %). - Dragonfly con epoll, 273.104 (+58,7 % sobre Redis por defecto). Con io_uring, 342.601 (+99,1 %).
Las io-threads con 2 CPU no movieron el throughput sin pipeline, aunque sí el consumo: Valkey pasó de 0,66 a 1,64 núcleos usados para dar lo mismo. Con pipeline 16 los tres servidores multihilo empataron: 1.475.365 con Redis, 1.443.686 con Valkey y 1.459.164 con Dragonfly, alrededor de 20 % más que los servidores de un hilo (1,21 millones). Ese empate no lo sé explicar con la CPU: los servidores usaron entre 0,93 y 1,6 de 2 núcleos.
Valores de 4 KiB
Con valores de 4 KiB, 200.000 claves y 4 CPU, sin pipeline: Redis con io-threads 343.776, Valkey 335.449, Dragonfly con epoll 340.113 y con io_uring 403.036. Es la única carga donde Dragonfly con io_uring se separa de los otros dos con hilos: unos 17 % por encima de Redis. Con epoll se queda igual que ellos.
Memoria
Con 1 millón de claves de 256 bytes, la cgroup del contenedor creció 326,5 bytes por clave con Dragonfly, contra 378,2 con Redis por defecto y 384,1 con Valkey. Con 2 millones de claves, cargados, Dragonfly ocupó 635 a 667 MiB y Redis y Valkey 727 a 738 MiB (tres cargas por servidor; la de 667 MiB fue de Dragonfly con epoll). Es un ahorro de 8 a 15 % según el tamaño del conjunto. Con 1 millón de claves fue una sola carga por servidor: lo tomo como orden de magnitud, no como cifra exacta.
- Dragonfly 2.0.0326 BIgual con epoll y con io_uring.
- Redis 8.10.1378 B383 B con io-threads 4.
- Valkey 9.1.2384 B384 B con io-threads 4.
Crecimiento de memory.current del contenedor tras cargar las claves. Una carga por servidor.
Snapshot bajo carga
Con 2 millones de claves y carga 1 a 1, lancé BGSAVE a los 12 s de una corrida de 40 s y comparé contra la misma corrida sin snapshot. Tres repeticiones por servidor, 4 CPU.
Redis y Valkey por defecto no cambiaron nada: su p99.9 ya estaba en 2,4 a 2,5 ms sin snapshot y siguió igual con él. Con --io-threads 4 sí se nota. El p99.9 de Redis subió de 0,97 a 2,11 ms (2,2 veces) y el de Valkey de 1,20 a 3,49 ms (2,9 veces). Dragonfly pasó de 0,81 a 1,00 ms con epoll y de 0,84 a 1,06 con io_uring.
La memoria cuenta lo mismo. Sobre lo que ocupaba el conjunto cargado, el pico del contenedor fue de +33 a +83 MiB en Redis con hilos y de +91 a +125 MiB en Valkey con hilos. En Dragonfly, como máximo +13 a +26 MiB: el pico de la cgroup es un máximo acumulado y no separa el guardado de las escrituras de la carga. Redis guarda con fork y su propio INFO reporta la copia en escritura (current_cow_size); en Dragonfly no vi ese costo y no verifiqué por qué.
- Dragonfly, epoll1,00 msSin snapshot, 0,81 ms.
- Dragonfly, io_uring1,06 msSin snapshot, 0,84 ms.
- Redis con io-threads 42,11 msSin snapshot, 0,97 ms.
- Valkey con io-threads 43,49 msSin snapshot, 1,20 ms.
2 millones de claves, lecturas y escrituras 1 a 1, BGSAVE a los 12 s de una corrida de 40 s. Sin snapshot: 0,97 Redis, 1,20 Valkey, 0,81 y 0,84 Dragonfly.
Lo que tarda el guardado bajo carga es parecido en todos: de 2,5 a 10 s. En reposo, con los mismos 2 millones de claves, Dragonfly con epoll tardó 16 y 17 s, y con io_uring 2 y 3 s (dos corridas de cada uno, según su propio last_success_save_duration_sec). No sé por qué en reposo con epoll es unas cuatro veces más lento que bajo carga y unas seis más que con io_uring.
Lo que no puedo afirmar
- Que Redis por defecto esté limitado por su único hilo. Usó 0,65 núcleos de los que tenía. Dragonfly rindió 2,8 veces más que Redis por defecto con 4 CPU, pero mis datos no muestran por qué el servidor de un hilo se queda en 173.000, solo que se queda.
- Cuál es más rápido con 4 CPU y sin pipeline. Ahí manda el techo del banco.
- Los números de latencia como latencia de producción. El banco es de lazo cerrado: cada latencia es la de un servidor sometido a 200 peticiones concurrentes.
- Que io_uring sea siempre mejor. Aportó mucho con 2 CPU y con valores de 4 KiB, y nada con 4 CPU, 256 bytes y sin pipeline.
- Nada sobre persistencia, clúster, réplicas ni comandos que no sean GET y SET. Medí un caso.
Es el mismo cuidado con el que medí Wild contra mold y CUDA en Rust. En el segundo, el 3,2 % a favor de Rust dejó de valer al comprobar que los dos programas no calculaban lo mismo.
Mi opinión
Me sorprendió que la ventaja “varias veces más rápido” de Dragonfly sea en buena parte la diferencia entre un servidor con un hilo y uno con varios. Con las io-threads activadas, Redis 8 y Valkey 9 se acercan mucho, y en pipeline 16 con 4 CPU ganan. Si ya tienes Redis o Valkey, activar --io-threads y medir con tu carga vale más que migrar.
Donde Dragonfly gana con claridad en mis medidas es con pocos núcleos, sin pipeline y con io_uring, y en memoria por clave. Si tu servidor tiene 2 vCPU y tu tráfico es de peticiones sueltas, es una razón concreta. Y el snapshot le costó poco: 0,2 ms de p99.9, contra 1,1 a 2,3 ms de Redis y Valkey con hilos.
Cuándo lo usaría
- Sí: un servidor chico, de 2 a 4 CPU, con muchas conexiones y peticiones sueltas; datos que ocupan mucha memoria y donde 8 a 15 % por clave cuentan.
- Sí, con cuidado: si vas a usar io_uring en Docker. Hay que abrir seccomp para ese contenedor y decidir si lo aceptas.
- Todavía no: si dependes de comandos o módulos que no probé, o si tu carga es de pipeline grande sobre 4 o más núcleos: ahí Redis y Valkey con io-threads dieron más.
Fuentes
- Dragonfly 2.0 ist da, heise online, 18 de septiembre de 2026 (alemán). Fuente de la noticia.
- Dragonfly v2.0.0, notas de la release del 16 de septiembre de 2026.
- Redis 8.10.1, del 17 de agosto de 2026. La 8.10.2 salió el 17 de septiembre.
- Valkey 9.1.2, del 1 de septiembre de 2026.
- memtier_benchmark 2.5.1, del 16 de julio de 2026.
- Ley de Little, para leer un banco de lazo cerrado.
Comentarios
Todavía no hay comentarios. El primero es tuyo.