ZFS tiene fama de «mágico», dicho a menudo con el mismo tono que la gente usa para hablar de máquinas de espresso. Los aciertos en ARC son rápidos, las sumas de comprobación reconfortan y los snapshots te hacen parecer competente bajo presión. Luego tu carga crece, la RAM deja de ser barata (o al menos deja de estar disponible) y alguien sugiere: «Simplemente añade L2ARC en NVMe».
A veces esa es exactamente la decisión correcta. Otras veces es una forma más cara de obtener el mismo rendimiento que podrías lograr simplemente dando más memoria al ARC, corrigiendo el recordsize, o evitando que tu aplicación lea los mismos 4 KB en un patrón de 1 MB. L2ARC no es un botón general de «hacer ZFS más rápido»; es una palanca muy específica con aristas afiladas.
Qué es L2ARC (y qué no es)
ARC (Adaptive Replacement Cache) es la caché primaria de ZFS, que vive en RAM. Cachea datos (y metadatos) y es agresivamente eficaz porque la latencia de la RAM es mínima y ARC está estrechamente integrado con la tubería de I/O de ZFS.
L2ARC es una caché secundaria que típicamente reside en un dispositivo rápido como NVMe. Almacena copias de bloques de datos que previamente estaban en ARC y que se consideran lo bastante valiosos para conservar cuando ARC necesita espacio. L2ARC no reemplaza a ARC; lo extiende.
Qué no es L2ARC:
- No es una caché de escritura. Las escrituras en ZFS se gestionan por grupos de transacción, el ZIL, y (si está presente) un dispositivo SLOG. L2ARC ayuda lecturas.
- No es una garantía. Es una caché con comportamiento de expulsión y calentamiento, y puede estar fría después del arranque.
- No es gratis. Consume CPU y memoria para cabeceras/índices, genera lecturas/escrituras adicionales en el dispositivo de caché, y puede robar ancho de banda a tu pool si está mal dimensionada o mal utilizada.
Dos frases de humor, como prometí, y volvemos a lo profesional: Añadir L2ARC para arreglar la latencia de lectura aleatoria es como añadir una segunda nevera para arreglar la cocina: a veces ayuda, pero solo si realmente tienes comida que almacenar. Además, «caché» es la única palabra en informática que significa «más rápido» y «más complicado» al mismo tiempo.
Hechos interesantes y contexto histórico
- ARC no es solo LRU. Mezcla recencia y frecuencia usando un algoritmo adaptativo, lo que importa cuando las cargas mezclan escaneos y conjuntos calientes.
- L2ARC llegó temprano en la vida de ZFS. Fue diseñado cuando los SSD eran más pequeños y la resistencia era una preocupación mayor, por eso su comportamiento de escritura y sus ajustables importan.
- Los primeros L2ARC no persistían tras reinicios. Muchas implementaciones aprendieron por las malas que un reinicio podía «borrar» el rendimiento hasta que la caché se calentara de nuevo.
- OpenZFS moderno puede persistir L2ARC. L2ARC persistente reduce el patrón de «los lunes por la mañana son lentos tras parches», si lo configuras y soportas correctamente.
- La caché no es solo datos. Los metadatos de ZFS (dnode, bloques indirectos) suelen dar ganancias de rendimiento desproporcionadas cuando están en caché, especialmente para árboles de directorios grandes e imágenes de VM.
- NVMe cambió la economía. Hizo que «lo suficientemente rápido para actuar como caché» fuera mucho más barato y compacto, pero también facilitó saturar carriles PCIe o que los dispositivos se termalen bajo escrituras sostenidas.
- Las escrituras a L2ARC pueden ser implacables. L2ARC se puebla escribiendo datos desde los flujos de expulsión del ARC; bajo presión puede generar desgaste constante del dispositivo y uso de ancho de banda.
- La compresión cambia las cuentas de la caché. ARC/L2ARC almacenan bloques comprimidos (cuando la compresión está activada), incrementando efectivamente la «capacidad» de la caché de una forma que muchas hojas de cálculo de dimensionamiento olvidan.
Por qué ARC gana por defecto
ARC es donde ZFS desea que aterricen tus lecturas calientes. Es más rápido que cualquier NVMe y permite a ZFS tomar decisiones de caché con la mínima sobrecarga. También cachea metadatos agresivamente, lo que a menudo es más importante que cachear datos a granel.
En producción, he visto más ganancias de rendimiento de:
- Añadir RAM (o evitar que sea robada por ballooning/otros servicios)
- Corregir recordsize (y volblocksize para zvols)
- Habilitar compresión (especialmente lz4) para reducir I/O
- Corregir ajustes de sync y usar SLOG adecuadamente (para problemas de latencia de escritura)
- Separar metadatos en un vdev especial cuando la carga es intensiva en metadatos
Se debe considerar L2ARC cuando tengas un conjunto caliente de lecturas conocido que sea más grande que la RAM pero aún lo bastante pequeño para caber en un dispositivo NVMe realista, y cuando la brecha de latencia entre NVMe y tu pool sea material.
Cuándo L2ARC en NVMe merece la pena
1) Tienes un «conjunto tibio» mayor que la RAM pero menor que NVMe
Ejemplo clásico: un host de virtualización con docenas de VMs donde los bloques «calientes» de cada VM no son enormes, pero el conjunto total caliente son decenas a cientos de GB. ARC no puede sostenerlo todo, y el pool está en HDDs o SSDs saturados. L2ARC en un buen NVMe puede elevar las IOPS de lectura y reducir la latencia de cola.
2) Tu pool es lento en lecturas aleatorias
Si tu pool principal es espejos HDD/RAIDZ, las lecturas aleatorias te cuestan seeks. L2ARC puede convertir la «penalización por lectura aleatoria» en «latencia de lectura NVMe», que es una mejora real de calidad de vida para arranques de VM, instalaciones de paquetes y builds de CI con muchas dependencias.
3) Tienes CPU libre y sensibilidad a la latencia
L2ARC no es gratis: añade ciclos de CPU para checksum, manejo de compresión y gestión de caché. Si el host tiene CPU sobrante y la carga castiga la latencia de cola (importan p95/p99), L2ARC puede ser un buen intercambio.
4) Puedes tolerar el comportamiento de calentamiento o tienes L2ARC persistente
Si tu flota se reinicia con regularidad (actualizaciones de kernel, firmware, eventos de energía), un L2ARC no persistente puede hacer que el rendimiento sea inconsistente. L2ARC persistente puede ayudar, pero añade consideraciones operativas: fiabilidad del dispositivo, tiempos de importación y validación.
5) Tu aplicación hace lecturas repetidas, no sólo streaming
L2ARC ama la reutilización. Si tu carga es «leer una vez» (backups, escaneos secuenciales grandes), L2ARC puede convertirse en un generador elegante de escrituras que mayormente cachea las noticias de ayer.
Cuándo ARC es suficiente (y L2ARC es una distracción)
1) Tu pool ya es NVMe/SSD y no es el cuello de botella
Si tu pool es SSD rápido y tu aplicación está limitada por CPU o bloqueos, L2ARC no lo arreglará. Solo añadirás otra capa de piezas móviles.
2) No tienes margen de memoria
L2ARC consume memoria para sus estructuras de índice. Si ya estás justo de RAM, añadir L2ARC puede empeorar las cosas al reducir el ARC efectivo y empujar el sistema a presión de reclaim. El resultado puede ser peor latencia y más I/O de disco.
3) Tu problema son escrituras, no lecturas
Si el problema es latencia de escritura sync (bases de datos, NFS con sync, tormentas de flush de VM), estás en territorio de SLOG. Si el problema es rendimiento de escritura a granel, estás en configuración de vdev, recordsize y ancho de banda del dispositivo. L2ARC no hará mucho más aparte de llenar dashboards.
4) Tu conjunto activo es «demasiado grande para cachear» en la práctica
Si el conjunto activo son varios terabytes y tu L2ARC propuesto es 400 GB, puede que no cambie significativamente las tasas de acierto. L2ARC ayuda cuando puede mantener una fracción significativa del conjunto re-leído.
Elegir el dispositivo NVMe: detalles aburridos que importan
Para L2ARC quieres un dispositivo que pueda sostener lecturas aleatorias mezcladas y un flujo constante de escrituras sin venirse abajo cuando su caché SLC se agota. NVMe de consumo puede lucir brillante en benchmarks y luego desacelerar o colapsar bajo escrituras sostenidas—exactamente el patrón que L2ARC puede generar cuando ARC está en churn.
Notas prácticas de selección:
- La resistencia (TBW/DWPD) importa. L2ARC puede escribir constantemente. Si lo añades para «ahorrar dinero», no elijas un dispositivo que se convierta en consumible.
- La protección contra pérdida de energía es conveniente. L2ARC no es un diario de escrituras, pero una pérdida repentina de energía puede aún crear sorpresas desagradables en el comportamiento del dispositivo, y la L2ARC persistente se beneficia de integridad media predecible.
- Los térmicos son reales. Los dispositivos NVMe pueden reducir rendimiento bajo escrituras sostenidas por throttling térmico. Si tu servidor tiene flujo de aire justo, L2ARC puede convertirse en un calentador accidental con penalización de rendimiento.
- No compartas el dispositivo con I/O pesado. Un NVMe «de caché» que también aloja logs, contenedores y una base de datos te enseñará sobre la contención.
Dimensionar L2ARC: capacidad, margen y expectativas
Dimensionar L2ARC es menos «más grande es mejor» y más «más grande = más metadatos y más tiempo de calentamiento». L2ARC necesita RAM para su registro. Si añades un L2ARC enorme a un sistema con memoria modesta, puedes asfixiar el ARC y perder.
Reglas empíricas que sobreviven al contacto con producción:
- Empieza pequeño. Un L2ARC modesto (decenas a pocos cientos de GB) puede entregar la mayor parte del beneficio sin sobrecarga excesiva.
- Prefiere más RAM antes que más L2ARC. Si puedes añadir RAM, hazlo primero. Los aciertos de ARC son más baratos y predecibles que los aciertos en L2ARC.
- Mide la tasa de acierto y la latencia, no sensaciones. L2ARC puede hacer que los gráficos parezcan «mejorados» mientras la latencia p99 sigue siendo horrible porque estás limitado por otra cosa.
- Espera calentamiento. Una caché fría significa volver al rendimiento del pool hasta que la carga vuelva a reproducir suficientes lecturas.
Perillas de ajuste que realmente importan
La mayoría del tuning de L2ARC trata de controlar el churn y decidir qué se admite. Los ajustes por defecto suelen ser conservadores, pero «subirlo al máximo» puede hacer daño—especialmente en sistemas ocupados.
Conceptos clave:
- Tasa de alimentación: Qué tan rápido se puebla L2ARC con buffers expulsados del ARC. Mayor tasa puede calentar más rápido pero incrementa la carga de escritura.
- Política de admisión: Si cachear solo ciertos tipos de datos (metadatos vs datos), y si priorizar bloques frecuentemente usados.
- Interacción con prefetch: Cachear datos prefetcheados puede ser desperdicio cuando las cargas son streaming.
- L2ARC persistente: Útil en entornos con muchos reinicios, pero cambia el comportamiento de importación y las expectativas operativas.
Tres micro-historias corporativas desde las trincheras
Micro-historia #1: El incidente causado por una suposición errónea
Era un clúster de virtualización de tamaño medio. El almacenamiento era un pool ZFS sobre espejos HDD (robusto, aunque poco glamuroso). Las quejas de rendimiento escalaban: tormentas de arranque de VM por la mañana, ventanas de parcheo interminables y tickets de «el almacenamiento se siente lento» que nunca traían métricas.
Un ingeniero bienintencionado propuso L2ARC en un NVMe. La suposición: «caché NVMe = lecturas más rápidas = problema resuelto». Añadieron un dispositivo de cache grande, y el primer día se vio mejor—algunos arranques fueron más rápidos y los helpdesk se callaron. Entonces llegó el reinicio semanal de mantenimiento.
Tras el reinicio, el rendimiento se hundió. No solo volvió al baseline—peor. El host thrasheó: ARC se redujo porque el sistema estaba constreñido de memoria, las cabeceras de L2ARC consumieron más RAM de la esperada, y la caché estaba fría. La tormenta de arranques matutina golpeó el pool lento, la cola del hypervisor se disparó. La latencia se infló y algunas VMs sufrieron timeouts de I/O. La dirección recibió el tipo de informe de incidente que comienza con «Recientemente hicimos un cambio…» y termina con un nuevo proceso de aprobación.
La solución no fue heroica. Eliminaron el L2ARC sobredimensionado, añadieron RAM para restaurar el margen del ARC, y habilitaron L2ARC persistente solo después de confirmar soporte del kernel/módulo y medir el comportamiento de importación. La lección: L2ARC no es un acelerador de «configurar y olvidar»; tiene relación con la RAM, y el comportamiento tras reinicio importa si tu carga tiene tormentas previsibles.
Micro-historia #2: La optimización que salió mal
Una plataforma de ingeniería de datos tenía un objeto store respaldado por ZFS para artefactos intermedios. Las lecturas eran lo bastante «aleatorias», y alguien notó que la tasa de acierto de ARC no era buena. El equipo añadió un NVMe de consumo de alta gama como L2ARC y decidió «hacerlo funcionar de verdad» subiendo la tasa de alimentación y cacheando más agresivamente.
En días, el NVMe empezó a lanzar errores de medio. SMART se veía feo. Lo que pasó no fue misterioso: la carga tenía churn enorme, el dispositivo de cache se estaba escribiendo constantemente, y el comportamiento de escritura sostenida del disco bajo calor no era lo que la hoja de especificaciones sugería. La caja no falló porque NVMe sea malo; falló porque la carga convirtió la «caché» en una cinta de correr de escrituras.
Incluso antes de los errores, las ganancias de rendimiento fueron inconsistentes. El pico de throughput a veces mejoraba, pero las latencias de cola empeoraban durante ingestas pesadas porque el sistema pasaba tiempo alimentando L2ARC mientras también intentaba servir lecturas. La optimización no solo no ayudó: creó un nuevo cuello de botella y un nuevo dominio de fallo.
Reemplazaron el dispositivo por un NVMe de resistencia empresarial, bajaron la tasa de alimentación y cambiaron la admisión para evitar cachear flujos con prefetch. El cambio más importante: reconocieron que la carga era fundamentalmente de streaming y ajustaron la canalización para reducir relecturas. L2ARC pasó a ser una ayuda modesta, no la estrategia principal.
Micro-historia #3: La práctica aburrida pero correcta que salvó el día
Una aplicación financiera funcionaba sobre ZFS, con ventanas de mantenimiento estrictas y mínima tolerancia a sorpresas. El equipo quería L2ARC para un gran conjunto de referencia consultado repetidamente durante horas laborales. Hicieron lo poco fashion: lo planificaron en fases.
Primero midieron: tamaño de ARC, tasa de aciertos de ARC, fallos de caché, distribución de latencias de lectura y I/O del pool. Establecieron una línea base durante la hora más ocupada y otra en horas quietas. Luego añadieron un L2ARC pequeño en un NVMe de calidad servidor con buena resistencia. Sin ajustes al principio; solo observar.
También pusieron guardarraíles operativos: alertas de temperatura y errores de medio del NVMe, líneas de tendencia en la tasa de acierto L2ARC, y un procedimiento de rollback que incluía quitar el dispositivo de cache limpio. Probaron el comportamiento tras reinicio y confirmaron que el tiempo de importación del L2ARC persistente era aceptable.
Cuando más tarde ocurrió un incidente—un despliegue que duplicó accidentalmente la amplificación de lectura—el almacenamiento no fue el chivo expiatorio. Las métricas dejaron claro: la tasa de fallos de ARC se disparó, L2ARC ayudaba pero estaba saturado, y el pool seguía viendo demasiadas lecturas aleatorias. Porque tenían instrumentación limpia, empujaron la corrección a la aplicación y mantuvieron estable el almacenamiento. Las prácticas aburridas salvaron el día: líneas base, cambios por fases y alertas que dispararon antes que los usuarios.
Tareas prácticas (comandos + interpretación)
Los comandos abajo asumen un sistema Linux con OpenZFS instalado. Ajusta rutas para tu distribución. La intención aquí es operativa: «ejecuta esto, lee aquello, decide el siguiente paso.»
Tarea 1: Identificar el layout del pool y dispositivos de cache actuales
cr0x@server:~$ sudo zpool status -v
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
cache
nvme0n1 ONLINE 0 0 0
errors: No known data errors
Interpretación: Confirma si existe L2ARC («cache» en la salida) y muestra errores. Si ves read/write/cksum en el dispositivo de cache, trátalo como un componente fallando—no como «solo cache».
Tarea 2: Confirmar propiedades de datasets que influyen en la caché
cr0x@server:~$ sudo zfs get -o name,property,value -s local,received compression,recordsize,primarycache,secondarycache tank/datasets/vmstore
NAME PROPERTY VALUE
tank/datasets/vmstore compression lz4
tank/datasets/vmstore primarycache all
tank/datasets/vmstore secondarycache all
tank/datasets/vmstore recordsize 128K
Interpretación: Si secondarycache=none, L2ARC no ayudará. Si primarycache=metadata, estás intencionadamente reservando ARC para solo metadatos—válido para algunas cargas, pero cambia expectativas.
Tarea 3: Comprobar tamaño de ARC, objetivo y presión
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c_max|c_min|memory_throttle_count)'
size 4 34359738368
c_min 4 8589934592
c_max 4 68719476736
memory_throttle_count 4 0
Interpretación: El tamaño de ARC es el uso actual; c_max es el techo. Un memory_throttle_count distinto de cero sugiere que ARC se ve forzado a retroceder por presión de memoria—a menudo una señal de que L2ARC puede hacer daño si añades más sobrecarga.
Tarea 4: Medir la tasa de acierto del ARC vs fallos (sanity rápida)
cr0x@server:~$ awk '
/^hits /{h=$3}
/^misses /{m=$3}
END{
total=h+m;
if(total>0) printf("ARC hit%%: %.2f\n", (h/total)*100);
}' /proc/spl/kstat/zfs/arcstats
ARC hit%: 92.14
Interpretación: Un ARC hit% alto a menudo significa que ARC ya está funcionando bien. Si el rendimiento sigue siendo malo, tu cuello de botella puede no ser la caché de lectura.
Tarea 5: Comprobar efectividad de L2ARC (tasa de acierto y tamaño)
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(l2_size|l2_hits|l2_misses|l2_read_bytes|l2_write_bytes)'
l2_hits 4 1843200
l2_misses 4 921600
l2_size 4 214748364800
l2_read_bytes 4 9876543210
l2_write_bytes 4 45678901234
Interpretación: Si l2_hits son ínfimos y l2_write_bytes enormes, puede que estés escribiendo una caché que rara vez se lee. Eso es un impuesto de resistencia y ancho de banda con poco beneficio.
Tarea 6: Observar comportamiento ARC/L2ARC en tiempo real (one-liner)
cr0x@server:~$ sudo arcstat 1
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c l2hits l2miss l2miss% l2read l2write
12:00:01 320 22 6 3 14 19 86 0 0 32G 64G 120 40 25 60M 280M
Interpretación: Buscas si los fallos correlacionan con dolor de latencia, y si L2ARC reduce significativamente los fallos. Si L2ARC está ocupado escribiendo mientras estás limitado por latencia, considera reducir la tasa de alimentación o ajustar admisión.
Tarea 7: Confirmar salud y desgaste del dispositivo (NVMe SMART)
cr0x@server:~$ sudo nvme smart-log /dev/nvme0n1
Smart Log for NVME device:nvme0n1 namespace-id:ffffffff
critical_warning : 0x00
temperature : 48 C
available_spare : 100%
percentage_used : 7%
data_units_read : 12,345,678
data_units_written : 98,765,432
media_errors : 0
num_err_log_entries : 0
Interpretación: percentage_used subiendo rápidamente tras añadir L2ARC es una pista de que estás convirtiendo el NVMe en una carga de escrituras. La temperatura acercándose a rangos de throttling también es una señal de alarma.
Tarea 8: Verificar latencia de lectura a nivel de pool y mezcla de I/O
cr0x@server:~$ sudo zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 3.20T 6.80T 850 220 85.0M 12.0M
mirror-0 3.20T 6.80T 850 220 85.0M 12.0M
sda - - 430 110 42.5M 6.0M
sdb - - 420 110 42.5M 6.0M
cache - - 200 0 20.0M 0.0M
nvme0n1 - - 200 0 20.0M 0.0M
Interpretación: Confirma si las lecturas realmente se están sirviendo desde el dispositivo de cache. También muestra si el pool está saturado en operaciones de lectura.
Tarea 9: Añadir un dispositivo L2ARC con seguridad
cr0x@server:~$ sudo zpool add tank cache /dev/nvme0n1
Interpretación: Esto adjunta el NVMe completo como cache. En muchas configuraciones de producción querrás particiones y nombres estables por-id; aún así, esta es la acción esencial.
Tarea 10: Quitar un dispositivo L2ARC con seguridad
cr0x@server:~$ sudo zpool remove tank nvme0n1
Interpretación: Los dispositivos de cache son removibles. Si estás solucionando problemas o elegiste la unidad equivocada, la remoción es sencilla—no arranques el dispositivo sin más y esperes lo mejor.
Tarea 11: Establecer políticas por dataset sobre qué va a L2ARC
cr0x@server:~$ sudo zfs set secondarycache=metadata tank/datasets/vmstore
cr0x@server:~$ sudo zfs get secondarycache tank/datasets/vmstore
NAME PROPERTY VALUE SOURCE
tank/datasets/vmstore secondarycache metadata local
Interpretación: Esto puede ser un control poderoso cuando los datos son enormes y de streaming pero los metadatos son calientes. Si tu L2ARC se estaba llenando por grandes lecturas secuenciales, esto suele calmarlo.
Tarea 12: Comprobar y ajustar límites de ARC (con cuidado)
cr0x@server:~$ sudo bash -c 'echo 68719476736 > /sys/module/zfs/parameters/zfs_arc_max'
cr0x@server:~$ cat /sys/module/zfs/parameters/zfs_arc_max
68719476736
Interpretación: Si tu sistema tiene RAM y ARC está limitado artificialmente, subir zfs_arc_max puede superar cualquier L2ARC que compres. No lo pongas tan alto que el kernel y las aplicaciones se queden sin memoria.
Tarea 13: Comprobar impactos del prefetch (alto nivel)
cr0x@server:~$ cat /sys/module/zfs/parameters/zfs_prefetch_disable
0
Interpretación: El prefetch es bueno para lecturas secuenciales, pero puede contaminar cachés bajo ciertos patrones. Deshabilitar el prefetch globalmente rara vez es la primera medida correcta; en su lugar, considera políticas por dataset o ajustar admisión para L2ARC si tu implementación lo soporta.
Tarea 14: Confirmar compresión y lecturas lógicas vs físicas
cr0x@server:~$ sudo zfs get -o name,property,value compressratio tank/datasets/vmstore
NAME PROPERTY VALUE
tank/datasets/vmstore compressratio 1.78x
Interpretación: La compresión aumenta la capacidad efectiva de la caché. Un ratio de 1.78x significa que tu ARC/L2ARC están almacenando menos datos físicos para el mismo conjunto lógico de trabajo.
Guía rápida de diagnóstico
Esta es la secuencia de «está lento y la gente está mirando». Puedes ejecutarla en cinco a quince minutos y salir con una hipótesis de trabajo.
Primero: ¿Son lecturas o escrituras?
cr0x@server:~$ sudo zpool iostat -v tank 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 3.20T 6.80T 900 120 90.0M 8.0M
Interpretación: Si las escrituras dominan y la latencia es el problema, mira el comportamiento sync, SLOG, txg y patrones fsync de la aplicación. L2ARC no es el primer interviniente.
Segundo: ¿Faltan cachés o hay un cuello de botella en el dispositivo?
cr0x@server:~$ awk '
/^hits /{h=$3}
/^misses /{m=$3}
/^l2_hits /{l2h=$3}
/^l2_misses /{l2m=$3}
END{
total=h+m;
l2total=l2h+l2m;
if(total>0) printf("ARC hit%%: %.2f\n", (h/total)*100);
if(l2total>0) printf("L2ARC hit%%: %.2f\n", (l2h/l2total)*100);
}' /proc/spl/kstat/zfs/arcstats
ARC hit%: 71.03
L2ARC hit%: 62.50
Interpretación: ARC hit% bajo y L2ARC hit% decente sugiere que L2ARC está ayudando. ARC hit% bajo y L2ARC hit% bajo sugiere que o L2ARC está subdimensionado, frío, mal admitido, o la carga tiene baja reutilización.
Tercero: ¿Es el propio cache NVMe el cuello de botella?
cr0x@server:~$ sudo nvme smart-log /dev/nvme0n1 | egrep 'temperature|critical_warning|media_errors|percentage_used'
temperature : 72 C
critical_warning : 0x00
percentage_used : 31%
media_errors : 0
Interpretación: Alta temperatura puede indicar throttling. El desgaste rápido sugiere que tu política de cache es demasiado escritora para la clase de dispositivo.
Cuarto: ¿La presión de memoria sabotea ARC?
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c_max|memory_throttle_count)'
size 4 10737418240
c_max 4 17179869184
memory_throttle_count 4 921
Interpretación: Si memory_throttle_count crece, ARC está siendo exprimido. Añadir L2ARC en este estado a menudo empeora las cosas. Considera añadir RAM, reducir el tope de ARC solo si es necesario, y arreglar el verdadero consumidor de memoria.
Quinto: Confirma que no persigues el problema equivocado
cr0x@server:~$ sudo iostat -xz 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
22.10 0.00 6.40 1.20 0.00 70.30
Device r/s w/s rkB/s wkB/s await %util
sda 55.0 12.0 6400.0 1100.0 18.2 92.0
nvme0n1 210.0 95.0 24000.0 33000.0 1.9 78.0
Interpretación: Si tus discos están a tope y la latencia es alta, la caché puede ayudar—pero si la CPU está saturada, o la app está bloqueada por otra cosa, estás optimizando la capa equivocada.
Errores comunes: síntomas y soluciones
Error 1: Usar L2ARC para arreglar latencia de escrituras sync
Síntoma: Usuarios se quejan de commits/transacciones lentos; las métricas muestran picos de latencia de escritura; las métricas de lectura no son el problema.
Solución: Evalúa la carga sync: considera un dispositivo SLOG adecuado, revisa ajustes de sync (y si puedes cambiarlos), y perfila patrones fsync. L2ARC es irrelevante aquí.
Error 2: Sobredimensionar L2ARC en un host pobre en RAM
Síntoma: Tras añadir cache, el tamaño de ARC se reduce, memory_throttle_count sube, y la latencia total empeora—especialmente después del arranque.
Solución: Reduce o elimina L2ARC, añade RAM y confirma que los límites ARC max/min son razonables. Si mantienes L2ARC, mantenlo modesto y mide.
Error 3: Cachear lecturas de streaming y llenar L2ARC con basura
Síntoma: Los bytes escritos a L2ARC suben rápidamente, la tasa de acierto L2ARC permanece baja, el desgaste del NVMe aumenta y las ganancias de rendimiento son mínimas.
Solución: Establece secondarycache=metadata para datasets de streaming, o restringe lo que se admite; evita cachear flujos con prefetch si es posible.
Error 4: Compartir el NVMe de L2ARC con otros servicios
Síntoma: Picos de latencia aleatorios que correlacionan con pulls de imágenes, ráfagas de logs o compactación de base de datos en el mismo NVMe.
Solución: Dedica el dispositivo (o al menos aisla con particiones y controles de I/O). Un dispositivo de cache no debería ser un disco scratch de propósito general en producción.
Error 5: Esperar mejora inmediata tras añadir L2ARC
Síntoma: «Añadimos cache y no cambió nada». Luego, días después, mejora—o empeora—dependiendo del churn de la carga.
Solución: Planea el calentamiento. Si el entorno reinicia a menudo y la consistencia importa, evalúa L2ARC persistente y mide el rendimiento post-reinicio explícitamente.
Error 6: Ignorar térmicos y resistencia del NVMe
Síntoma: Throttling, caídas repentinas de rendimiento, saltos en SMART wear, o errores de medio tras un despliegue «exitoso».
Solución: Usa NVMe con resistencia empresarial, asegura flujo de aire, monitorea temperatura y desgaste, y ajusta tasa de alimentación/admision de L2ARC para reducir la intensidad de escritura.
Listas de verificación / plan paso a paso
Paso a paso: decidir si necesitas L2ARC
- Confirma que el problema es latencia/IOPS de lectura. Usa
zpool iostaty herramientas de latencia del sistema; no adivines. - Mide la efectividad de ARC. Si ARC hit% ya es alto, enfócate en otra cosa.
- Estima el tamaño del conjunto de trabajo. Aunque sea aproximado: «¿cuánta data se relee durante la hora pico?» Si está muy por encima de lo que es asequible en NVMe, L2ARC no será milagroso.
- Comprueba margen de RAM. Si el host está justo de memoria, planifica RAM primero.
- Considera la política de caché por dataset. Si la mayoría de lecturas son streaming, L2ARC puede perjudicar a menos que lo restrinjas a metadatos o subconjuntos calientes.
- Evalúa alternativas. Ajustes de recordsize/volblocksize, compresión, vdev especial para metadatos, o simplemente vdevs de pool más rápidos pueden ser mejor ROI.
Paso a paso: desplegar L2ARC de forma segura
- Elige el NVMe adecuado. Resistencia y rendimiento sostenido ganan a benchmarks vistosos.
- Métricas baseline. Captura estadísticas ARC/L2ARC, zpool iostat y distribuciones de latencia durante pico.
- Añade un dispositivo de cache modesto al principio. No empieces con «tan grande como sea posible».
- Mantén los ajustes por defecto inicialmente. Observa por al menos un ciclo de carga (un día/semana laboral).
- Valida el comportamiento tras reinicio. Si el rendimiento tras reinicio es inaceptable, evalúa L2ARC persistente o acepta el tiempo de calentamiento.
- Establece políticas secondarycache por dataset. Especialmente para datasets de streaming conocidos.
- Monitorea salud del NVMe. Temperatura, desgaste, errores de medio; alerta antes de que sea una sorpresa de outage.
- Documenta rollback. Practica
zpool removey confirma que el sistema se comporta como esperas.
Preguntas frecuentes
1) ¿L2ARC acelera escrituras?
No. L2ARC es para lecturas. Si tu problema de escritura es latencia sync, buscas ajuste y elección de SLOG. Si es throughput, mira layout de vdev y ancho de banda.
2) ¿Es mejor comprar más RAM o añadir NVMe para L2ARC?
Más RAM suele ganar. Los aciertos de ARC son más rápidos y simples que los aciertos en L2ARC, y la RAM no introduce contención de dispositivo ni preocupaciones de resistencia. L2ARC es para cuando la RAM no puede sostener el conjunto de trabajo de forma práctica.
3) ¿Qué tamaño debe tener L2ARC?
Suficientemente grande para contener una porción significativa del conjunto de trabajo re-leído, lo bastante pequeño para evitar sobrecarga de memoria y tiempo de calentamiento excesivo. Empieza modesto, mide y escala solo si las tasas de acierto y latencia mejoran.
4) ¿Por qué empeoró el rendimiento tras añadir L2ARC?
Razones comunes: presión de memoria que reduce el ARC efectivo, L2ARC llenándose con datos de streaming/prefetch, contención en el dispositivo de cache, o un NVMe que no sostiene el patrón de escrituras y empieza a throttlear.
5) ¿Puedo usar un NVMe de consumo para L2ARC?
Puedes, pero aceptas riesgos: límites de resistencia, throttling térmico y comportamiento impredecible bajo escrituras sostenidas. Para producción, los dispositivos endurance-rated suelen ser más baratos que el incidente que acabarás documentando.
6) ¿Debo cachear solo metadatos o todo?
Cachear solo metadatos suele ser el mejor «valor por defecto seguro» para cargas mixtas o datasets de streaming. Cachear todo puede ayudar conjuntos de lectura de VM y bases de datos, pero también aumentar churn y desgaste si tu patrón de acceso no es con reutilización elevada.
7) ¿L2ARC persistente elimina el calentamiento?
Reduce el calentamiento tras reinicio, pero no lo elimina en todos los casos. Aún necesitas validar comportamiento de importación, fiabilidad del dispositivo, y que la caché persistida coincida con la realidad de datos tras cambios.
8) ¿Cómo sé si L2ARC se está usando realmente?
Mira l2_hits, l2_read_bytes y herramientas en tiempo real como arcstat. También verifica que las lecturas del pool bajen cuando suben los aciertos L2ARC. Si L2ARC escribe mucho pero se lee poco, no está haciendo trabajo útil.
9) ¿L2ARC es lo mismo que un vdev especial?
No. Un vdev especial almacena ciertas clases de datos (a menudo metadatos y bloques pequeños) como parte del pool, no como caché. Puede ofrecer grandes ganancias consistentes para cargas intensivas en metadatos, pero cambia consideraciones de redundancia y fallo. L2ARC es caché removible; un vdev especial es parte de tu almacenamiento.
Conclusión
L2ARC en NVMe puede ser una herramienta afilada y legítima: reduce la latencia de lectura y aumenta las IOPS de lectura cuando tu conjunto caliente es mayor que la RAM y tu pool es más lento que NVMe. Pero no sustituye a ARC y no es una solución universal de rendimiento.
En producción, el patrón ganador es consistente: mide primero, añade RAM cuando puedas, usa L2ARC cuando tengas lecturas repetidas y margen suficiente, y mantenlo aburrido—dispositivos dedicados, dimensionamiento sensato y métricas que te indiquen cuándo la caché está ayudando en vez de solo trabajar duro.