En algún punto, todo administrador de ZFS se enfrenta al mismo villano: un working set que no cabe en RAM. El síntoma es familiar: picos de latencia, discos que se quejan, usuarios afirmando “el almacenamiento está lento” con la certeza moral de quien nunca miró iostat.
Usar NVMe como L2ARC suena como la solución obvia: añadir un dispositivo de caché rápido y seguir con la vida. A veces es brillante. A veces es una forma cara de desgastar tu NVMe mientras el rendimiento permanece tercamente mediocre. Este artículo trata de saber en qué mundo estás antes de aprenderlo en producción.
Qué es L2ARC (y qué no es)
ZFS tiene una caché primaria llamada ARC (Adaptive Replacement Cache). Vive en RAM y es extremadamente buena haciendo lecturas repetidas económicas. Cuando ARC es demasiado pequeña para tu working set, ZFS puede extender el cache hacia un dispositivo rápido: L2ARC, el “Level 2 ARC”. L2ARC es caché de lectura. No es un buffer de escritura, no es un acelerador de journaling, no es una varita mágica.
Qué ocurre en la práctica:
- ARC sigue lo que está caliente. Si ARC no puede mantenerlo, ZFS puede empujar parte de esos datos a L2ARC.
- En un fallo de lectura en ARC, ZFS puede mirar en L2ARC. Si se encuentra, se lee desde NVMe en lugar de desde discos giratorios o SSDs más lentos.
- El contenido de L2ARC se popula con el tiempo. Históricamente no persistía entre reinicios; las implementaciones más nuevas pueden persistirlo (más adelante verás más).
Qué L2ARC no hace:
- No acelera escrituras síncronas (eso es territorio de SLOG, y aun así: solo para cargas específicas).
- No arregla un pool lento por fragmentación, diseño de vdev pobre o un cuello de botella de CPU.
- No elimina la necesidad de dimensionar correctamente la RAM. L2ARC todavía necesita metadatos en RAM para ser útil.
Verdad operativa seca: L2ARC es una herramienta para abaratar un tipo específico de latencia de lectura. Si tu problema es “las lecturas aleatorias me matan y los datos se vuelven a leer”, puede brillar. Si tu problema es “todo es aleatorio y nunca se repite”, no servirá.
Una cita que debería estar en cada turno de guardia: La esperanza no es una estrategia
— atribuida al General Gordon R. Sullivan. Trata a L2ARC igual: mide, luego decide.
Hechos e historia interesante (corto, útil y algo opinado)
- ARC precede a la mayoría de las prácticas de “almacenamiento en la nube”. ZFS y ARC vienen de la ingeniería de la era Solaris donde la memoria era cara y los discos lentos, así que la política de caché era asunto serio.
- L2ARC fue diseñado para caché de lectura, no para durabilidad. Las implementaciones tempranas perdían la caché al reiniciar; eso moldeó las expectativas operativas por años.
- L2ARC necesita RAM para describir lo que hay en él. Cada bloque cacheado necesita metadatos en ARC. Un L2ARC gigantesco puede robar silenciosamente RAM que tu ARC necesita desesperadamente.
- NVMe hizo a L2ARC menos embarazoso. Los primeros dispositivos L2ARC eran a menudo SSDs SATA; las mejoras de latencia fueron reales, pero no siempre dramáticas. La baja latencia de NVMe cambia los trade-offs.
- Prefetch y L2ARC tienen una relación complicada. Las lecturas secuenciales pueden inundar las cachés con cosas que nunca volverás a tocar. ZFS añadió controles (como
l2arc_noprefetch) porque la gente seguía cacheando sus arrepentimientos. - Hay un “impuesto de calentamiento”. L2ARC se llena gradualmente, no instantáneamente. Las primeras horas (o días) pueden verse peor que “sin L2ARC”, especialmente si lo dimensionaste mal.
- La tasa de alimentación de la caché está deliberadamente limitada. ZFS limita cuán agresivamente escribe en L2ARC para evitar convertir tu sistema en una fábrica de escritura de caché.
- L2ARC no es una característica sin coste. Consume CPU, memoria y escrituras hacia tu NVMe. Ese desgaste es real; plánificalo como planeas la retención de logs.
- L2ARC persistente existe ahora en implementaciones modernas de ZFS. Reduce el dolor de calentamiento tras reinicios, pero no es universal y no es gratis.
Cuándo NVMe L2ARC realmente ayuda
L2ARC es para cargas con lecturas repetidas que fallan en ARC pero podrían servirse más rápido que lo que proporciona tu pool.
Buenos candidatos
- Hosts de VM con bloques “calientes” estables entre muchos invitados: bibliotecas compartidas, archivos de arranque, binarios comunes, repositorios de parches.
- Bases de datos con patrones de solo lectura donde el working set es un poco más grande que la RAM (o donde te niegas a comprar más RAM por finanzas).
- Caches de CI/build donde las mismas toolchains se usan repetidamente y tu pool está en HDD.
- Clusters de analytics que vuelven a escanear las mismas particiones “recientes”, pero no de forma puramente secuencial.
La condición clave: L2ARC debe ser más rápido que lo que reemplaza
Si tu pool ya es NVMe o un espejo SSD poderoso, L2ARC puede ser redundante. Si tu pool es HDD RAIDZ con lecturas aleatorias, L2ARC puede parecer un milagro — asumiendo que realmente estás releyendo los mismos bloques.
Broma #1: L2ARC es como una segunda nevera—genial si guardas sobras, inútil si solo comes comida para llevar.
Cuándo L2ARC es una trampa
La mayoría de las historias “L2ARC fue decepcionante” se reducen a una de estas:
1) Tu carga no vuelve a leer
Ingesta de backups, escaneos fríos de analytics, copias de archivos únicas, procesamiento secuencial de medios grandes—estos tienden a fluir por la caché y desaparecer. L2ARC se convierte en tráfico de escritura hacia NVMe con poco retorno en tasa de aciertos.
2) Tu ARC queda hambriento, y L2ARC lo empeora
L2ARC requiere metadatos en RAM. Si tu sistema ya tiene presión de memoria, añadir un L2ARC grande puede reducir el tamaño efectivo de ARC e incrementar los fallos. Felicidades, cacheaste más en NVMe mientras perdiste lo que hace que la caché sea rápida: RAM.
3) Tu problema no son las lecturas
Si el dolor son escrituras síncronas, pequeñas escrituras aleatorias o contención de metadata, L2ARC podría no hacer casi nada. A menudo la solución correcta es un layout de vdev diferente, un vdev especial para metadata/bloques pequeños, más RAM o ajustar la aplicación.
4) Acabas de construir una caché que hace thrashing
Thrash significa que los bloques se escriben en L2ARC y se expulsan antes de ser reutilizados. Eso puede pasar porque el working set es demasiado grande, la tasa de alimentación de la caché es demasiado alta, o el patrón es una ventana rodante mayor que ARC+L2ARC.
Elegir NVMe para L2ARC: latencia, resistencia y por qué “rápido” no basta
Para L2ARC, quieres baja latencia bajo carga mixta, no solo un rendimiento secuencial heroico que nunca alcanzarás en una caché. Los números de marketing no muestran la latencia cola-coda cuando el dispositivo está caliente, parcialmente lleno y haciendo garbage collection en segundo plano. Ese es tu mundo real.
Latencia y comportamiento de colas
Los aciertos en L2ARC son lecturas aleatorias. Tu NVMe debería manejar altas IOPS sin convertir la latencia p99 en una sorpresa semanal. Las unidades con rendimiento consistente (a menudo modelos “enterprise-ish”) importan aquí. Los discos de consumo pueden estar bien, pero el riesgo es un comportamiento más brusco cuando la caché SLC se agota o bajo escrituras sostenidas por llenado de caché.
Endurance es una característica, no una nota al pie
L2ARC se popula mediante escrituras. Algunas cargas causan churn constante: los bloques se escriben en caché, se reemplazan, se escriben otra vez. Eso puede agotar las calificaciones TBW de las unidades de consumo más rápido de lo que espera tu equipo de compras.
Regla práctica: si no puedes explicar con seguridad tu tasa de escritura de caché, no compres el NVMe más barato. Compra uno que puedas reemplazar sin una discusión de carrera.
Protección contra pérdida de energía (PLP)
L2ARC es una caché; no se requiere que sea durable. Pero el comportamiento ante pérdida de energía aún importa porque un dispositivo que se comporta mal durante apagones puede colgar el bus PCIe, bloquear rutas I/O o desencadenar resets de controlador. PLP no es obligatorio para L2ARC, pero el “comportamiento empresarial aburrido” es valioso en producción.
Dimensionamiento de L2ARC: matemática simple, restricciones reales
La gente dimensiona L2ARC como dimensiona almacenamiento de objetos: “más es mejor.” Así terminas con una caché de 4 TB delante de un sistema con 64 GB de RAM y un ARC que jadea.
La realidad del overhead en RAM
L2ARC necesita metadatos en ARC para cada bloque cacheado. El overhead exacto varía por implementación y recordsize, pero debes asumir un coste real y no trivial en RAM. Si ARC ya está ajustado, un L2ARC grande puede perjudicar. Quieres suficiente RAM para mantener los metadatos más valiosos y los datos de uso frecuente en ARC, mientras L2ARC atrapa lo que se desborda.
Empieza pequeño y demuestra valor
Puntos de partida operativamente sensatos:
- Elige un tamaño de L2ARC que sea no más que algunos múltiplos de la RAM para sistemas típicos, a menos que hayas medido y puedas justificar más.
- Prefiere NVMe “bien dimensionado” sobre “el más grande disponible.” Una caché que nunca se calienta es un monumento al optimismo.
- Mide ratios de acierto y mejoras de latencia antes de escalar.
Recordsize y compresión importan
ZFS cachea bloques. Si tus datasets usan recordsize de 1M para escrituras secuenciales grandes, eso puede cambiar el comportamiento de caché comparado con 16K típico de algunas bases de datos. La compresión también afecta cuánto “lógico” cabe en la caché y puede mejorar la capacidad efectiva de la caché —a veces dramáticamente.
Controles de ajuste que importan (y los que mayormente no)
La mayor parte del tuning de L2ARC se trata de reducir el caché inútil y prevenir que el relleno de caché se convierta en su propia carga de trabajo.
Prefiere cachear lecturas bajo demanda sobre prefetch
Prefetch es ZFS intentando ayudar para acceso secuencial. Para L2ARC puede ser activamente perjudicial porque llena la caché con datos que se leyeron una vez, de forma secuencial, y que nunca volverán a leerse.
Enfoque común: habilita L2ARC pero evita cachear prefetch. En Linux/OpenZFS, esto suele controlarse con l2arc_noprefetch. Los valores por defecto y el comportamiento pueden variar por versión; mide en tu build.
Controla la tasa de alimentación
L2ARC se popula desde la expulsión de ARC. Hay tunables que controlan cuánto se escribe por intervalo y cuán rápido se escala. Si empujas demasiado, tú:
- Aumentas la carga de escritura en NVMe (golpe a la endurance).
- Gastas CPU en bookkeeping de caché.
- Potencialmente compites con I/O del workload real.
L2ARC persistente: agradable, pero no lo idolatres
L2ARC persistente reduce el calentamiento tras reboot guardando cabeceras y contenido de caché entre reinicios. Puede ser una gran ganancia para sistemas que se reinician por parches y necesitan rendimiento predecible post-reboot. Pero la persistencia puede aumentar la complejidad y el comportamiento de escaneo en el arranque. Trátala como cualquier otra característica: prueba, luego despliega.
Tareas prácticas: comandos, salidas y las decisiones que tomas
Estas son tareas reales que puedes ejecutar en un host Linux OpenZFS. Las salidas son representativas. Tus números variarán; tus decisiones no deberían ser basadas en corazonadas.
Task 1: Verificar la salud del pool antes de tocar la caché
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:11:43 with 0 errors on Sun Dec 22 03:10:12 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
errors: No known data errors
Qué significa: No estás en llamas. Si ves errores de checksum o vdevs degradados, arregla eso primero.
Decisión: Solo añade L2ARC a un pool estable. Un dispositivo de caché no rescatará un pool enfermo.
Task 2: Comprueba si ya existe un L2ARC
cr0x@server:~$ sudo zpool list -v tank
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 65.4T 41.2T 24.2T - - 22% 63% 1.00x ONLINE -
raidz2 65.4T 41.2T 24.2T - - 22% 63%
sda - - - - - - -
sdb - - - - - - -
sdc - - - - - - -
sdd - - - - - - -
sde - - - - - - -
sdf - - - - - - -
Qué significa: No se muestra una sección cache, por lo que no hay L2ARC.
Decisión: Procede a seleccionar y adjuntar un NVMe, o detente si puedes resolver el problema con RAM o layout en su lugar.
Task 3: Confirma la identidad y salud del dispositivo NVMe (antes de que ZFS lo toque)
cr0x@server:~$ lsblk -o NAME,MODEL,SIZE,ROTA,TYPE,MOUNTPOINT | grep -E 'nvme|NAME'
NAME MODEL SIZE ROTA TYPE MOUNTPOINT
nvme0n1 Samsung SSD 980 PRO 931.5G 0 disk
Qué significa: Estás a punto de usar /dev/nvme0n1, 1 TB, no rotacional.
Decisión: Confirma que no estás apuntando al disco del SO. Si este NVMe también contiene root, detente. Compartir es posible pero rara vez sensato.
Task 4: Comprueba SMART y los indicadores de endurance del NVMe
cr0x@server:~$ sudo smartctl -a /dev/nvme0n1 | sed -n '1,35p'
smartctl 7.4 2023-08-01 r5530 [x86_64-linux-6.8.0] (local build)
=== START OF INFORMATION SECTION ===
Model Number: Samsung SSD 980 PRO 1TB
Serial Number: S5GXNF0R123456A
Firmware Version: 5B2QGXA7
PCI Vendor/Subsystem ID: 0x144d
IEEE OUI Identifier: 0x002538
Total NVM Capacity: 1,000,204,886,016 [1.00 TB]
Unallocated NVM Capacity: 0
Controller ID: 6
Number of Namespaces: 1
Namespace 1 Size/Capacity: 1,000,204,886,016 [1.00 TB]
SMART/Health Information (NVMe Log 0x02)
Critical Warning: 0x00
Temperature: 44 Celsius
Available Spare: 100%
Available Spare Threshold: 10%
Percentage Used: 2%
Data Units Written: 14,512,331
Data Units Read: 22,900,112
Qué significa: La unidad está sana, bajo desgaste (Percentage Used).
Decisión: Si el desgaste ya es alto, no ofrezcas este dispositivo para churn de caché. Si debes hacerlo, limita la tasa de alimentación y monitoriza las escrituras.
Task 5: Observa el tamaño actual de ARC y la presión
cr0x@server:~$ arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsize c
12:10:01 8160 1432 17 902 11 420 5 110 1 46G 58G
12:10:02 7992 1470 18 961 12 401 5 108 1 46G 58G
12:10:03 8421 1522 18 1002 12 413 5 107 1 46G 58G
Qué significa: ARC es ~46G, target/limit ~58G. Tasa de fallos ~18%. Eso puede estar bien o ser terrible según la latencia del pool.
Decisión: Si ARC está muy por debajo de su objetivo porque el SO lo está estrangulando, arregla la presión de memoria primero. L2ARC no sustituye a la RAM.
Task 6: Mide de dónde vienen tus lecturas ahora mismo
cr0x@server:~$ sudo zpool iostat -v tank 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 41.2T 24.2T 8900 420 195M 6.8M
raidz2 41.2T 24.2T 8900 420 195M 6.8M
sda - - 1500 70 33.0M 1.2M
sdb - - 1490 72 32.8M 1.1M
sdc - - 1520 71 33.5M 1.1M
sdd - - 1475 68 32.4M 1.1M
sde - - 1460 69 32.1M 1.1M
sdf - - 1455 70 31.9M 1.1M
Qué significa: Las lecturas están golpeando fuertemente los vdevs HDD. Si la latencia es alta y el working set se relee, L2ARC puede ayudar.
Decisión: Si los discos están saturados y las lecturas son aleatorias, una caché es plausible. Si las lecturas son pequeñas y centradas en metadata, considera un vdev especial en su lugar.
Task 7: Adjuntar NVMe como L2ARC
cr0x@server:~$ sudo zpool add tank cache /dev/nvme0n1
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
cache
nvme0n1 ONLINE 0 0 0
Qué significa: NVMe es ahora un dispositivo de caché (L2ARC).
Decisión: No declares victoria. Ahora monitoriza calentamiento, ratio de aciertos y escrituras NVMe.
Task 8: Verifica que L2ARC se esté usando (tasas de acierto y tamaño)
cr0x@server:~$ arcstat 1 5 | sed -n '1,6p'
time read miss miss% ... l2hit l2miss l2miss% l2bytes arcsize c
12:18:01 9010 1210 13 ... 2200 980 31 190G 47G 58G
12:18:02 9155 1198 13 ... 2350 960 29 191G 47G 58G
12:18:03 9033 1160 12 ... 2480 910 27 192G 47G 58G
12:18:04 9199 1205 13 ... 2605 920 26 194G 47G 58G
12:18:05 9122 1188 13 ... 2710 890 25 195G 47G 58G
Qué significa: L2ARC tiene ~195G poblados y está sirviendo aciertos (l2hit). El porcentaje de fallos L2 está cayendo a medida que se calienta.
Decisión: Si l2bytes se mantiene pequeño durante horas bajo carga constante, algo anda mal: tasa de alimentación, workload, o simplemente no estás expulsando bloques útiles.
Task 9: Vigila I/O del NVMe para asegurar que el llenado de caché no esté destrozando la latencia
cr0x@server:~$ iostat -x 1 3 | sed -n '1,25p'
Linux 6.8.0 (server) 12/26/2025 _x86_64_ (32 CPU)
Device r/s w/s rMB/s wMB/s await svctm %util
nvme0n1 3200.0 180.0 125.0 40.0 0.7 0.2 68.0
sda 250.0 12.0 4.1 0.3 18.4 2.2 55.0
sdb 240.0 11.0 4.0 0.3 19.1 2.2 54.0
Qué significa: NVMe está ocupada, pero la latencia (await) es baja. Los HDD muestran await más alto, típico.
Decisión: Si el await del NVMe sube a varios ms y compite con el I/O de la aplicación, reduce la escritura a L2ARC o revalúa. Tu caché no debe convertirse en el dispositivo más caliente.
Task 10: Confirma las propiedades del dataset que influyen en el comportamiento de la caché
cr0x@server:~$ sudo zfs get -o name,property,value,source recordsize,primarycache,secondarycache,compression tank/vmstore
NAME PROPERTY VALUE SOURCE
tank/vmstore recordsize 128K local
tank/vmstore primarycache all default
tank/vmstore secondarycache all default
tank/vmstore compression lz4 local
Qué significa: Tanto ARC como L2ARC están permitidos (primarycache=all, secondarycache=all).
Decisión: Si un dataset tiene secondarycache=none, L2ARC no lo cacheará. Eso puede ser correcto para backups en streaming, o una configuración silenciosa equivocada.
Task 11: Excluir datasets de streaming del L2ARC para evitar contaminación
cr0x@server:~$ sudo zfs set secondarycache=none tank/backups
cr0x@server:~$ sudo zfs get -o name,property,value,source secondarycache tank/backups
NAME PROPERTY VALUE SOURCE
tank/backups secondarycache none local
Qué significa: El dataset de backups no pobl·ará L2ARC.
Decisión: Haz esto cuando tengas grandes lectores/escritores secuenciales que expulsarían bloques cacheados útiles. Reserva la caché para las cargas que “pagan renta”.
Task 12: Inspeccionar parámetros del módulo relacionados con L2ARC (Linux OpenZFS)
cr0x@server:~$ sudo sysctl -a 2>/dev/null | grep -E 'l2arc_|zfs\.arc_' | head
zfs.l2arc_noprefetch = 1
zfs.l2arc_write_max = 8388608
zfs.l2arc_write_boost = 33554432
zfs.arc_max = 62277025792
zfs.arc_min = 15569256448
Qué significa: El prefetch no se cachea en L2ARC, y los límites de escritura están establecidos (bytes por intervalo).
Decisión: Si l2arc_noprefetch es 0 y tienes workloads secuenciales, considera activarlo. Si el llenado de caché es demasiado agresivo, ajusta l2arc_write_max con cuidado y valida.
Task 13: Cambiar un tunable de L2ARC de forma segura (temporal) y validar impacto
cr0x@server:~$ sudo sysctl -w zfs.l2arc_write_max=4194304
zfs.l2arc_write_max = 4194304
Qué significa: Se redujo la tasa máxima de escritura hacia L2ARC (aquí a 4 MiB por intervalo; el intervalo depende de la implementación).
Decisión: Usa esto si las escrituras NVMe compiten con lecturas/escrituras sensibles a latencia. Revisa iostat y la latencia p99 de la aplicación tras el cambio.
Task 14: Confirma que no confundes SLOG con L2ARC
cr0x@server:~$ sudo zpool status tank | sed -n '1,35p'
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
cache
nvme0n1 ONLINE 0 0 0
Qué significa: Solo hay un vdev de cache presente. No hay sección logs, lo que significa que no hay SLOG.
Decisión: Si tu dolor son escrituras síncronas (NFS con sync, bases de datos con patrones fsync-intensos), L2ARC no lo arreglará. Considera SLOG—con cuidado—solo después de medir.
Task 15: Eliminar L2ARC (si no ayuda) sin drama
cr0x@server:~$ sudo zpool remove tank nvme0n1
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
Qué significa: L2ARC se ha desenganchado. El pool no cambia estructuralmente (los vdevs cache no guardan datos únicos).
Decisión: Si el rendimiento no cambia o mejora después de eliminarlo, tu caché era ruido o daño. Deja de intentar hacerlo funcionar y arregla el verdadero cuello de botella.
Task 16: Evaluar la presión de memoria y comportamiento de reclaim (Linux)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 128Gi 94Gi 4.1Gi 1.2Gi 30Gi 26Gi
Swap: 16Gi 2.3Gi 13Gi
Qué significa: RAM está muy usada, disponible es 26Gi, swap está en uso.
Decisión: La actividad de swap en una caja de almacenamiento suele ser señal de que ARC está exprimido o el host está sobrecomprometido (VMs, contenedores). Antes de añadir L2ARC, considera añadir RAM o reducir workloads co-ubicados. El overhead de metadatos de L2ARC no ayudará a un host que está haciendo swap.
Playbook de diagnóstico rápido: encuentra el cuello de botella en minutos
Este es el orden que ahorra tiempo en producción. El objetivo no es “recopilar todas las métricas.” El objetivo es “identificar el recurso limitante y la solución más simple”.
Primero: determina si tienes un problema de latencia de lectura o otra cosa
- Revisa I/O del pool y proxies de latencia:
zpool iostat -v 1,iostat -x 1. - Si los discos no están ocupados y la latencia es baja, tu problema puede ser CPU, red, locks de aplicación o comportamiento de escrituras síncronas.
Segundo: comprueba la efectividad de ARC y la presión de memoria
- Usa
arcstatpara evaluar la tasa de fallos y la estabilidad del tamaño de ARC. - Usa
free -hy observa swap. Si el host está haciendo swap, arregla eso. L2ARC no cura la inanición de memoria.
Tercero: confirma que la carga tiene localidad temporal
- Busca lecturas repetidas: comportamiento de buffer cache de DB, tormentas de arranque de VM, builds de CI repetidos.
- Si es principalmente streaming, L2ARC será un generador de desgaste.
Cuarto: prueba un L2ARC pequeño y mide
- Añade NVMe L2ARC y observa
l2hit,l2missy la latencia p95/p99 de la aplicación. - El calentamiento importa; evalúa sobre un ciclo de trabajo, no 10 minutos.
Quinto: si es intensivo en metadata, considera un diseño distinto
- I/O aleatorio de metadata en pools HDD a menudo responde mejor a un vdev especial que a L2ARC.
- Si la latencia de escrituras síncronas es el problema, mídelo y considera SLOG (con el dispositivo correcto y expectativas reales).
Tres mini-historias del mundo corporativo desde el frente
Mini-historia 1: El incidente causado por una suposición equivocada
Tenían un cluster de virtualización ocupado sobre HDD RAIDZ2. Los usuarios se quejaban de “lentitud aleatoria”, sobre todo los lunes por la mañana. El equipo de storage vio IOPS de lectura en el pool y decidió “arreglarlo bien” con un gran NVMe L2ARC—varios terabytes, porque compras ama los números redondos.
Se instaló limpiamente. Los gráficos parecían emocionantes: la utilización de NVMe saltó y las IOPS de lectura del pool bajaron. Todos se sintieron inteligentes por un día.
Luego la latencia empezó a trepar. No en el pool HDD—en el host. El tamaño de ARC se encogió. El hipervisor empezó a hacer swap bajo carga. Las tormentas de arranque de VM empeoraron, no mejoraron, y el helpdesk aprendió vocabulario nuevo.
La suposición equivocada fue simple: “L2ARC es caché extra, así que no puede empeorar la memoria.” En realidad, el L2ARC gigante consumió metadatos de ARC y redujo la caché efectiva en RAM. El sistema cambió aciertos rápidos en RAM por aciertos más lentos en NVMe y más fallos. Removieron el L2ARC, añadieron RAM a los hosts, y reintrodujeron una caché más pequeña después, dirigida a datasets específicos. El rendimiento se normalizó y se mantuvo aburrido.
Mini-historia 2: La optimización que salió mal
Un equipo de plataforma de datos corría analytics en un pool ZFS respaldado por SSDs. Querían dashboards más rápidos, y alguien sugirió L2ARC en un NVMe de consumidor sobrante. “Es solo caché; si falla, nada se rompe.” Eso era técnicamente cierto en el sentido más estrecho.
Afilaron los parámetros de escritura de L2ARC agresivamente para “calentarlo más rápido.” Se calentó más rápido. También escribió constantemente, porque el workload escaneaba grandes ventanas de datos con poca reutilización. L2ARC se convirtió en una cinta de correr de escritura.
Unas semanas después, el NVMe empezó a tirar errores de medio. No catastrófico, pero suficiente para generar alertas y pequeñas perturbaciones I/O. Durante un incidente, el reset del dispositivo causó stalls temporales que parecían un outage de almacenamiento a nivel de cluster. La gente culpó a ZFS. ZFS sobrellevo; el dispositivo estaba teniendo un mal día.
El postmortem fue incómodo porque la “optimización” no mejoró el p99 del dashboard de todos modos. La solución fue aburrida: remover L2ARC, ajustar consultas para reducir churn, y más tarde añadir un vdev especial pequeño para metadata y bloques pequeños. Los dashboards mejoraron y el NVMe dejó de morirse por una característica que nadie pudo cuantificar.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Una firma de servicios financieros corría ZFS para almacenamiento de VM y servicios internos. Tenían L2ARC en NVMe en espejo (sí, en espejo—porque tenían ranuras y les gustaba dormir tranquilos). Su política de cambios era dolorosamente estricta: cada cambio en storage requería una línea base pre-cambio, un plan de rollback y una métrica de éxito explícita.
El parcheo trimestral requería reinicios, y antes habían visto dips de rendimiento post-reboot mientras las cachés se calentaban. Probaron L2ARC persistente en staging, confirmaron el comportamiento de arranque y lo desplegaron con tunables cuidadosamente elegidos y un camino documentado para “desactivar persistencia”.
Luego vino una semana fea: un deploy de aplicación aumentó la amplificación de lectura e hizo las cachés menos efectivas. Porque tenían líneas base, pudieron probar que no era “el storage envejeciendo”. Ajustaron las políticas de caché del dataset para la carga ruidosa y protegieron la caché de la contaminación. Sin heroísmos. Sin llamadas a proveedores. Solo competencia.
No fue glamoroso, pero previno el clásico bucle de sala de guerra: “el storage está lento” → “añadir caché” → “sigue lento” → “añadir más caché.” Su proceso aburrido salvó días de fricción.
Broma #2: Lo único más persistente que L2ARC es un stakeholder preguntando si podemos “simplemente añadir más NVMe”.
Errores comunes: síntomas → causa raíz → solución
1) Síntoma: la tasa de aciertos de L2ARC permanece cerca de cero
Causa raíz: La carga es streaming o tiene baja localidad de re-lectura; o el dataset tiene secondarycache=none; o la caché es demasiado pequeña y hace thrash inmediato.
Solución: Verifica propiedades del dataset con zfs get secondarycache. Excluye datasets de streaming. Si la localidad es baja, elimina L2ARC e invierte en otra cosa.
2) Síntoma: el tamaño de ARC se reduce después de añadir L2ARC, aumentan los misses
Causa raíz: El overhead en RAM por metadatos L2ARC reduce la capacidad de ARC; el host tiene presión de memoria; L2ARC sobredimensionado.
Solución: Reduce el tamaño de L2ARC (usa una partición/dispositivo más pequeño), añade RAM o elimina L2ARC. Confirma con arcstat y free -h.
3) Síntoma: alta utilización de NVMe, picos de latencia, la aplicación empeora
Causa raíz: Tasa de alimentación de L2ARC demasiado agresiva; NVMe es un disco de consumo con mal comportamiento sostenido; el llenado de caché compite con el workload.
Solución: Baja l2arc_write_max/l2arc_write_boost. Usa un NVMe con rendimiento consistente. Considera excluir datasets ruidosos de L2ARC.
4) Síntoma: el rendimiento es genial… hasta el reinicio, luego horrible por horas
Causa raíz: L2ARC no persistente requiere calentamiento; la carga depende fuertemente de aciertos en caché.
Solución: Evalúa soporte de L2ARC persistente en tu versión de ZFS. Si no está disponible o no es deseable, planifica reinicios y pre-calienta, o incrementa RAM para reducir la dependencia en L2ARC.
5) Síntoma: esperabas escrituras más rápidas, pero nada cambió
Causa raíz: L2ARC es caché de lectura. Las escrituras están condicionadas por ZIL/SLOG, el layout del pool y semánticas sync.
Solución: Mide escrituras síncronas. Si es necesario, evalúa SLOG con el dispositivo correcto y prueba. No cargo-cultes “NVMe = más rápido”.
6) Síntoma: L2ARC ayuda algunas cargas, pero los backups ralentizan todo
Causa raíz: Contaminación de caché y presión de expulsión por lecturas/escrituras secuenciales de backups.
Solución: Pon secondarycache=none (y a veces primarycache=metadata) en datasets de backup. Mantén la caché para workloads interactivos/calientes.
7) Síntoma: mucho uso de CPU en kernel bajo carga tras habilitar L2ARC
Causa raíz: Overhead de bookkeeping de caché más actividad elevada de expulsión; posiblemente demasiados bloques pequeños o feed agresivo.
Solución: Reduce la tasa de escritura de L2ARC; asegúrate de no cachear prefetch; considera aumentar recordsize donde corresponda o repensar el patrón I/O del workload.
8) Síntoma: NVMe se desgasta más rápido de lo esperado
Causa raíz: Churn constante por baja localidad; caché sobredimensionada con alta rotación; tunables de escritura agresivos.
Solución: Mide la tasa de escritura, limita la alimentación, excluye datasets de streaming, o elimina L2ARC. Compra dispositivos de mayor endurance cuando la carga lo justifique.
Listas de verificación / plan paso a paso
Plan A: Decide si deberías añadir L2ARC en absoluto
- Confirma que es un problema de lectura. Si tu pool está limitado por escrituras o por sync, para y diagnostica eso en su lugar.
- Mide la tasa de fallos de ARC y el headroom de RAM. Si el host tiene presión de memoria, prioriza RAM y colocación de workloads.
- Valida la localidad de re-lectura. L2ARC es para “lecturas que vuelven”. Si no lo hacen, no las caches.
- Revisa el layout del pool y el dolor de metadata. Si la metadata es el cuello de botella, un vdev especial puede superar a L2ARC.
Plan B: Implementar NVMe L2ARC de forma segura
- Línea base antes de cambios. Captura
arcstat,zpool iostat,iostat -xy latencia de la aplicación. - Elige un NVMe sensato. Favorece latencia consistente y endurance sobre throughput pico.
- Comienza con un tamaño de caché moderado. Demuestra valor antes de escalar.
- Adjunta el dispositivo como
cache. Verifica conzpool status. - Evita la contaminación de caché. Pon
secondarycache=noneen datasets de streaming. - Monitorea calentamiento y carga del dispositivo. Observa
l2hit/l2missyawaitdel NVMe. - Ajusta con cautela. Reduce la tasa de escritura de L2ARC si compite con I/O real.
- Documenta rollback. Sabe cómo
zpool removeel dispositivo de cache y qué significa “éxito”.
Plan C: Guardarraíles operativos que te mantienen fuera de problemas
- Alerta sobre desgaste y errores de media del NVMe. L2ARC puede ser duro con las unidades; trátalo como un componente consumible.
- Rastrea ratios de acierto de caché a lo largo del tiempo. Una caché útil puede volverse inútil tras cambios en la aplicación.
- Planificación de reinicios. Si L2ARC no es persistente, programa reinicios cuando el calentamiento no perjudique.
- Mantén los cambios pequeños. Si cambias tamaño de caché, tunables y propiedades de datasets a la vez, nunca sabrás qué funcionó.
Preguntas frecuentes
1) ¿Es L2ARC lo mismo que SLOG?
No. L2ARC es una caché de lectura. SLOG es un dispositivo de log separado usado para acelerar escrituras síncronas acortando la ruta de commit del ZIL. Problema distinto, herramienta distinta.
2) ¿Debería espejar dispositivos L2ARC?
Usualmente no, porque L2ARC no contiene datos únicos. Si falla, pierdes caché y el rendimiento vuelve al del pool. Espeja solo si el coste operativo de perder la caché es alto y tienes ranuras y presupuesto.
3) ¿Puede L2ARC empeorar el rendimiento?
Sí. Los mecanismos habituales son encogimiento de ARC (overhead de metadatos), contención por llenado de caché y contaminación por workloads secuenciales. “Caché” no es automáticamente “más rápido”.
4) ¿Cuánto tarda L2ARC en calentarse?
Depende de tu working set, la tasa de expulsión de ARC y los límites de alimentación de L2ARC. Para sistemas ocupados puede ser horas; para sistemas más tranquilos, días. Si necesitas ganancias instantáneas, compra más RAM primero.
5) ¿Debería cachear prefetch en L2ARC?
La mayoría de las veces: no. Prefetch puede inundar L2ARC con datos secuenciales que no se volverán a leer. Si tu workload es principalmente secuencial y se vuelve a leer, pruébalo—no asumas.
6) ¿Cómo evito que los backups arruinen mi caché?
Pon secondarycache=none en datasets de backup. En algunos entornos, considera también primarycache=metadata para datasets de streaming para que ARC mantenga metadata pero no datos voluminosos.
7) ¿Vale la pena habilitar L2ARC persistente?
Si tus cargas son sensibles al calentamiento post-reboot y tu versión de ZFS lo soporta de forma fiable, puede ser una gran mejora de calidad de vida. Prueba reinicios en staging y observa el comportamiento de arranque y uso de memoria.
8) Tengo un pool todo NVMe. ¿Aún necesito L2ARC?
Rara vez. ARC en RAM sigue siendo más rápido que NVMe. Pero si el working set es enorme y muy re-lecturado, y tu pool está tan ocupado que descargar lecturas ayuda, L2ARC aún puede ser útil. Mide primero; si no, solo añades complejidad.
9) ¿Qué es mejor: más RAM o más L2ARC?
Más RAM, casi siempre. Los aciertos en ARC son más baratos que los aciertos en L2ARC, y la RAM no se desgasta por haber mirado el mismo archivo dos veces. Usa L2ARC cuando la RAM ya esté razonablemente dimensionada y aún faltes.
10) ¿Cómo sé si L2ARC se paga a sí mismo?
Observa la latencia p95/p99 y el throughput de la aplicación, no solo ratios de caché. Un aumento de l2hit es bonito, pero la métrica de negocio es “menos requests lentas”. Si no puedes mostrar mejora, elimínalo.
Próximos pasos prácticos
- Línea base hoy. Captura
arcstat,zpool iostat -vyiostat -xdurante un periodo conocido como “lento”. - Decide si la carga vuelve a leer. Si es streaming, no construyas un santuario de caché.
- Arregla la presión de memoria primero. Si estás haciendo swap o ARC no puede alcanzar un tamaño estable, L2ARC es una distracción.
- Empieza con un NVMe L2ARC pequeño y protégelo. Excluye datasets de streaming, evita cachear prefetch y mantén tasas de alimentación razonables.
- Mide resultados, no sentimientos. Si la latencia p99 mejora y el desgaste de NVMe es aceptable, mantenlo. Si no, quítalo y pasa a cambios de layout o RAM.