Nada arruina una guardia tranquila como “compramos dos terabytes de caché NVMe y el rendimiento empeoró”. Miras los gráficos: los discos parecen bien, las CPU parecen aburridas, y la latencia todavía tiene picos como si la pagaran por milisegundo.
L2ARC es la perilla más tentadora en ZFS porque parece un intercambio simple: flash barato y rápido compra caché estilo RAM caro. En producción es más enredado. A veces 200GB de L2ARC son una victoria clara. Otras veces 2TB es una manera muy cara de calentar un NVMe mientras te roba RAM.
El modelo mental: qué es realmente L2ARC
ARC es tu caché de primer nivel: en memoria, rápido y ferozmente optimizado. L2ARC no es “ARC pero en SSD.” Es un caché de segundo nivel para bloques que ya estuvieron en ARC y fueron expulsados. Ese detalle lo es todo.
ARC y L2ARC resuelven problemas distintos
ARC es donde ZFS quiere estar. Cachea bloques y metadatos usados recientemente y con frecuencia, y se adapta entre MRU (reciente) y MFU (frecuente). Los aciertos en ARC son baratos.
L2ARC es un caché de víctimas. Almacena datos que ARC no pudo retener. Eso significa que L2ARC solo ayuda cuando:
- Tu carga de trabajo tiene un conjunto de trabajo mayor que la RAM, pero aún suficientemente pequeño para caber de forma significativa en L2ARC.
- Hay reutilización. L2ARC no sirve para lecturas de una sola vez.
- La penalización por fallo en disco es lo suficientemente alta como para que un acierto en SSD sea materialmente mejor.
Aquí está la parte que la gente olvida: L2ARC gasta RAM para almacenar punteros de SSD
L2ARC mantiene metadatos en RAM que mapean los encabezados de ARC a bloques almacenados en el dispositivo L2. Un L2ARC más grande significa más metadatos en memoria. Si esos metadatos aprietan al ARC, puedes perder más de lo que ganas.
Además, llenar L2ARC no es gratis. Consume ancho de banda de I/O y ciclos de CPU para escribir en el dispositivo de caché. Bajo mucho churn, eso puede convertirse en presión autoinfligida.
Lo que realmente estás dimensionando
Cuando “dimensionas L2ARC”, estás equilibrando:
- Ganancia en tasa de aciertos (cuántas lecturas evitan medios más lentos)
- Reducción efectiva de ARC (RAM consumida por metadatos de L2ARC y comportamiento de alimentación)
- Amplificación de escritura (las escrituras para llenar L2ARC; además de cualquier característica de persistencia)
- Perfil de latencia (NVMe es rápido, pero no gratis; y no todos los fallos son iguales)
- Comportamiento en fallo y recuperación (tiempo de calentamiento del caché; tormentas de reinicio; pérdida de dispositivo)
Idea parafraseada de Werner Vogels (CTO de Amazon): Todo falla, todo el tiempo—diseña y opera asumiendo esa realidad.
Eso aplica también a los cachés. L2ARC es una optimización de rendimiento. Trátalo como una bandera de función con un plan de salida.
Hechos interesantes y un poco de historia
Un poco de contexto hace que los controles sean menos místicos. Hechos cortos y concretos:
- L2ARC se introdujo temprano en Solaris ZFS como una forma de extender el caché más allá de la RAM, originalmente orientado a dispositivos flash empresariales.
- ARC precede al moderno “page cache + evicción sofisticada”; ZFS construyó un caché coherente con su propia lógica de expulsión en lugar de depender enteramente del page cache del sistema operativo.
- Históricamente, L2ARC no era persistente: reiniciar significaba un caché frío y un largo calentamiento; trabajo posterior de OpenZFS añadió opciones de persistencia en algunas plataformas.
- Los primeros diseños de L2ARC estaban limitados por la resistencia del SSD; alimentar L2ARC podía escribir mucho más de lo que la gente esperaba.
- La sobrecarga de metadatos siempre ha sido el impuesto; a medida que ARC se volvió más inteligente (y más grande), L2ARC a veces se volvió menos atractivo para cargas generales.
- L2ARC solo cachea lecturas; no acelera escrituras síncronas (eso es territorio de SLOG, y aun así es matizado).
- Los special vdevs cambiaron el juego: poner metadatos (y opcionalmente bloques pequeños) en flash puede vencer a L2ARC porque cambia dónde vive la data, no solo dónde se cachea.
- NVMe hizo “L2ARC enorme” asequible, por eso ahora vemos más casos donde la gente lo sobredimensiona y descubre la moraleja de metadatos/RAM.
Por qué 200GB puede vencer a 2TB
El titular no es un truco. Un L2ARC más pequeño suele ganar porque el caching trata sobre densidad de reutilización, no capacidad bruta. Si cacheas muchos bloques que no volverán a usarse, has construido un vertedero muy rápido.
1) Tu conjunto de trabajo tiene un “núcleo caliente” y una “cola fría”
La mayoría de las cargas de producción lo tienen. Piensa: tormentas de arranque de VM versus datos de usuario de larga cola; índices de bases de datos versus tablas históricas; artefactos de build versus artefactos de la semana pasada.
Un L2ARC de 200GB que contenga la cola caliente de las expulsiones del ARC puede dar una alta tasa de aciertos. Un L2ARC de 2TB puede traer también la cola fría, desperdiciando metadatos en RAM y ancho de banda de alimentación. Cuando eso pasa, ARC se encoge, metadatos calientes salen, y pierdes los aciertos más baratos que tenías.
2) L2ARC compite con ARC por la RAM (indirectamente)
El rendimiento de ZFS suele depender de memoria. No “más memoria es bueno” en sentido pegadizo—específicamente: ¿tienes suficiente ARC para mantener metadatos y tus bloques calientes residentes?
Un L2ARC grande incrementa la cantidad de contabilidad en memoria. Eso reduce el espacio efectivo de ARC para datos realmente cacheados. Si los fallos de ARC aumentan al agrandar L2ARC, puedes degradar el rendimiento.
3) L2ARC tiene una tasa de llenado; los cachés enormes no se llenan a tiempo
L2ARC se llena gradualmente. Si tu carga recorre datos más rápido de lo que L2ARC puede poblar, el caché nunca se vuelve representativo. Sigues pagando para llenarlo y no obtienes suficientes aciertos a cambio.
Un L2ARC más pequeño se calienta más rápido y se mantiene relevante. En entornos con reinicios frecuentes, failovers o mantenimientos, el tiempo de calentamiento no es académico.
4) No todos los “aciertos” son iguales
Incluso una tasa de aciertos perfecta en L2ARC puede ser una mala inversión si el cuello de botella no son las lecturas desde medios lentos. Si estás limitado por CPU en compresión, cifrado, checksums, o un bloqueo de aplicación mono-hilo, la capacidad de L2ARC no lo arreglará.
5) La “penalización por lectura aleatoria” es donde L2ARC gana
Si tu pool es principalmente HDD, las lecturas aleatorias son caras, y L2ARC puede ser dramático—si los datos se reutilizan. Si tu pool ya es todo NVMe, L2ARC a menudo se convierte en un redondeo. Un L2ARC grande en un pool rápido aún puede hacer daño al consumir metadatos en RAM y generar escrituras extra.
Broma #1: Comprar un L2ARC más grande para arreglar la latencia es como comprar una nevera más grande para arreglar el hambre—quizás solo termines con más sobras.
Un método de dimensionamiento que no depende de vibras
Si recuerdas una sola regla: no dimensiones L2ARC por el tamaño del disco; dimensiona por la reutilización medida y el margen de RAM.
Paso 1: Prueba que tienes un problema de fallos de lectura
Empieza respondiendo tres preguntas:
- ¿Estamos limitados por latencia en las lecturas desde el pool?
- ¿Los aciertos de ARC son altos pero aún insuficientes, es decir, el conjunto de trabajo excede la RAM?
- ¿Hay reutilización en el flujo de expulsión (es decir, ¿L2ARC sería realmente golpeado)?
Si no puedes demostrar esto, la recomendación por defecto es aburrida: añade RAM o arregla la carga de trabajo.
Paso 2: Estima el conjunto “apto para L2”
Estás buscando bloques que sean:
- Accedidos con frecuencia, pero no lo suficiente para permanecer en ARC bajo presión
- Costosos de recuperar desde el pool (lecturas aleatorias en HDD, o latencia remota SAN)
- Suficientemente estables para beneficiarse del calentamiento del caché
En la práctica, ese conjunto “apto para L2” suele ser mucho más pequeño que el tamaño total del dataset. Podría ser los 50–300GB de bloques OS de VM, o unos pocos cientos de gigabytes de índices de base de datos, no “los 12TB de archivos de usuario”.
Paso 3: Asegura margen de RAM para metadatos ARC y encabezados de L2ARC
Un L2ARC sobredimensionado puede dejar sin ARC. El indicio es: el tamaño de ARC deja de crecer, los fallos de metadatos suben, y el sistema se vuelve “entrecortado” bajo carga.
Regla práctica realmente útil: si ya luchas con la presión del ARC, no añadas L2ARC todavía. Arregla la memoria primero, o mueve metadatos a un special vdev, o reduce el conjunto de trabajo.
Paso 4: Elige clase de dispositivo y resistencia como un adulto
L2ARC escribe. No constantemente como un log, pero lo suficiente como para importar. QLC de consumo puede funcionar para cachés modestos con comportamiento de alimentación conservador; también puede morir avergonzantemente rápido bajo cargas con mucho churn.
Elige un NVMe con protección contra pérdida de energía si te importa la consistencia durante cortes. L2ARC es “solo caché”, pero el mal comportamiento súbito del dispositivo aún puede añadir modos de fallo y timeouts feos.
Paso 5: Empieza pequeño, mide y luego crece
No instales 2TB porque estaba en oferta. Instala 200–400GB. Mide tasa de aciertos, latencia, comportamiento de ARC y carga de escritura durante una semana. Luego decide si expandir.
Broma #2: L2ARC es como un canal de Slack de toda la empresa—útil cuando está curado, un desastre cuando todos vuelcan todo en él.
Tareas prácticas: comandos, salidas, decisiones (12+)
Estos son los chequeos diarios que te mantienen honesto. Las salidas son ejemplos; tus números variarán. El punto es lo que cada uno te dice y qué decisión tomas después.
Tarea 1: Confirma pool y layout de vdev (porque nada tiene sentido sin ello)
cr0x@server:~$ zpool status -v tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 00:32:11 with 0 errors on Tue Dec 24 02:14:22 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
cache
nvme0n1 ONLINE 0 0 0
errors: No known data errors
Significado: Estás en RAIDZ2 con HDDs y un dispositivo NVMe de caché. La penalización por lectura aleatoria en HDDs es real, así que L2ARC podría importar.
Decisión: Si esto fuera todo-NVMe o SSDs en espejo, sería escéptico sobre el valor de L2ARC y me enfocaría primero en ARC y la carga de trabajo.
Tarea 2: Comprueba tamaño, objetivo y presión de ARC
cr0x@server:~$ arc_summary | head -n 25
ARC Summary:
Memory Throttle Count: 0
ARC Size: 22.5 GiB
Target Size: 24.0 GiB
Min Size (Hard Limit): 8.0 GiB
Max Size (High Water): 24.0 GiB
Most Recently Used Cache Size: 7.1 GiB
Most Frequently Used Cache Size: 13.8 GiB
Significado: ARC está cerca del máximo. Eso puede estar bien o ser señal de que estás limitado por memoria.
Decisión: Si ARC está fijo en el máximo y tu OS está intercambiando o los servicios tienen poca memoria, no crezcas L2ARC—añade RAM o reduce el máximo de ARC solo si es necesario.
Tarea 3: Mide la ratio de aciertos de ARC y los misses de datos demandados
cr0x@server:~$ arcstat 1 5
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
12:01:01 8320 410 4 320 3 62 1 28 0 22G 23.8G
12:01:02 8011 398 4 310 3 59 1 29 0 22G 23.8G
12:01:03 8550 460 5 370 4 61 1 29 0 22G 23.8G
12:01:04 7902 402 5 322 4 55 1 25 0 22G 23.8G
12:01:05 8122 405 4 330 4 53 1 22 0 22G 23.8G
Significado: La tasa de misses de ARC es ~4–5%, los misses de datos demandados dominan. Eso no es terrible. Si L2ARC ayuda depende de lo que cuesten esos misses.
Decisión: Si miss% es bajo y la latencia sigue siendo mala, sospecha cuellos de botella no relacionados con almacenamiento. Si miss% es alto y las lecturas son aleatorias, L2ARC podría ayudar.
Tarea 4: Comprueba presencia de L2ARC y ratio de aciertos
cr0x@server:~$ arc_summary | sed -n '60,110p'
L2ARC Summary:
L2ARC Size: 186.2 GiB
L2ARC Evict Misses: 0
L2ARC Hits: 1823124
L2ARC Misses: 9311042
L2ARC Read Hit Ratio: 16.4%
L2ARC Writes: 412019
Significado: La ratio de aciertos de L2ARC es ~16%. Eso puede ser significativo en pools con HDD, menos en pools con SSD.
Decisión: Si la ratio de aciertos está en un dígito y el dispositivo está ocupado, reduce o elimina L2ARC y enfócate en otra cosa. Si es >15–30% y la latencia de lectura mejora, mantenlo y considera un crecimiento modesto.
Tarea 5: Verifica comportamiento de alimentación de L2ARC y si el dispositivo está saturado
cr0x@server:~$ iostat -x 1 3 nvme0n1
Linux 6.8.0 (server) 12/26/2025 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
10.12 0.00 3.21 1.02 0.00 85.65
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await wareq-sz aqu-sz %util
nvme0n1 820.0 89200.0 0.0 0.00 0.35 108.78 290.0 38100.0 1.90 131.38 0.80 48.00
Significado: NVMe no está saturado (%util 48%). Bien. Si estuviera cerca del 100% con w_await alto, llenar L2ARC podría estar dañando.
Decisión: Si el dispositivo de caché está saturado, limita la tasa de alimentación (tunables específicos de plataforma) o reduce L2ARC.
Tarea 6: Confirma si el pool es realmente la fuente de latencia
cr0x@server:~$ zpool iostat -v tank 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 38.2T 12.1T 1400 520 180M 62.1M
raidz2-0 38.2T 12.1T 1400 520 180M 62.1M
sda - - 230 90 30.1M 10.2M
sdb - - 240 85 29.8M 10.1M
sdc - - 225 88 29.6M 10.3M
sdd - - 235 86 30.2M 10.4M
sde - - 240 86 30.5M 10.2M
sdf - - 230 85 29.8M 10.1M
cache - - 710 260 86.0M 38.1M
nvme0n1 - - 710 260 86.0M 38.1M
---------- ----- ----- ----- ----- ----- -----
Significado: El dispositivo de caché está haciendo lecturas significativas. Eso es L2ARC pagando renta.
Decisión: Si “cache” muestra lecturas cercanas a cero mientras los misses son altos, L2ARC no se está usando (o no puede calentarse). Investiga churn, desajuste de recordsize, o que la carga sea de streaming.
Tarea 7: Detecta lecturas en streaming que L2ARC no ayudará
cr0x@server:~$ zfs get -o name,property,value -s local,default recordsize,primarycache,secondarycache tank/data
NAME PROPERTY VALUE
tank/data primarycache all
tank/data secondarycache all
tank/data recordsize 128K
Significado: El dataset cachea tanto en ARC como en L2ARC y usa records de 128K. Escaneos secuenciales grandes pueden arrasar la utilidad del caché.
Decisión: Para datasets de streaming/backup, establece secondarycache=none (o incluso primarycache=metadata) para proteger el caché para datos sensibles a latencia.
Tarea 8: Aplica política de caché por dataset (con cuidado, quirúrgicamente)
cr0x@server:~$ sudo zfs set secondarycache=none tank/backups
cr0x@server:~$ zfs get -o name,property,value secondarycache tank/backups
NAME PROPERTY VALUE
tank/backups secondarycache none
Significado: Las lecturas de backup no contaminarán L2ARC. ARC aún puede cachear según la configuración de primarycache.
Decisión: Haz esto cuando tengas cargas mixtas y backups/reconstrucciones estén aplastando las tasas de acierto del caché.
Tarea 9: Comprueba la presión de metadatos y si un special vdev es mejor
cr0x@server:~$ arc_summary | sed -n '25,60p'
ARC Miscellaneous:
Deleted: 112.3 MiB
Mutex Misses: 0
Demand Data Hits: 51234123
Demand Data Misses: 9123421
Demand Metadata Hits: 88123411
Demand Metadata Misses: 923412
Significado: Existen misses de metadatos pero no están explotando. Si los misses de metadatos fueran enormes y la latencia irregular durante búsquedas de directorios/operaciones VM, un special vdev para metadatos podría vencer a L2ARC.
Decisión: Si tu dolor es dominado por metadatos (patrones tipo VMFS, muchos archivos pequeños, recorridos de directorios), considera un special vdev antes de aumentar L2ARC.
Tarea 10: Verifica que no estés confundiendo SLOG con L2ARC
cr0x@server:~$ zpool status tank | sed -n '1,25p'
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
logs
nvme1n1 ONLINE 0 0 0
cache
nvme0n1 ONLINE 0 0 0
Significado: Tienes un dispositivo de log separado (SLOG) y uno de caché (L2ARC). Buena separación.
Decisión: Si tu problema es latencia de escrituras síncronas y sigues agregando L2ARC, detente. Mide la carga sync y el comportamiento del SLOG en su lugar.
Tarea 11: Valida que la carga realmente esté leyendo (no esperando locks o CPU)
cr0x@server:~$ pidstat -dru 1 3
Linux 6.8.0 (server) 12/26/2025 _x86_64_ (32 CPU)
12:10:11 UID PID %usr %system %wait %CPU CPU kB_rd/s kB_wr/s Command
12:10:12 999 18322 2.00 0.50 15.00 2.50 6 1200.00 200.00 postgres
12:10:12 0 1421 0.10 0.20 0.00 0.30 2 0.00 0.00 zfs
Significado: La app muestra %wait. Eso podría ser espera de I/O, pero también puede ser espera de locks dependiendo del stack. Aun así, es una señal para correlacionar con la latencia de almacenamiento.
Decisión: Si la CPU está al máximo o la app está limitada por locks, los cambios en tamaño de L2ARC no lo arreglarán. No hagas “teatro de caché”.
Tarea 12: Observa la latencia real de I/O a nivel de dispositivo
cr0x@server:~$ iostat -x 1 3 sda
Device r/s rkB/s r_await w/s wkB/s w_await aqu-sz %util
sda 220.0 30100.0 18.20 85.0 10200.0 6.40 4.10 98.00
sda 235.0 31000.0 21.50 92.0 11000.0 7.10 4.80 99.00
sda 210.0 29000.0 16.80 80.0 9800.0 5.90 3.70 96.00
Significado: HDD está saturado y r_await de lectura es alto. Si L2ARC puede absorber algunas lecturas, reducirás esto.
Decisión: Si los HDDs están al límite en lecturas, L2ARC probablemente ayuda. Si los HDDs están inactivos y la latencia sigue alta, el problema está en otro lado.
Tarea 13: Confirma compresión y alineación de recordsize (la eficiencia del caché depende de ello)
cr0x@server:~$ zfs get -o name,property,value compression,recordsize tank/pg
NAME PROPERTY VALUE
tank/pg compression lz4
tank/pg recordsize 16K
Significado: recordsize 16K para un dataset de base de datos; eso puede mejorar localidad y la utilidad del caché para patrones OLTP.
Decisión: Si estás cacheando registros enormes de 1M para lecturas aleatorias, puedes desperdiciar caché. Ajusta recordsize por dataset.
Tarea 14: Evalúa rápidamente margen de memoria
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 128Gi 41Gi 12Gi 1.0Gi 75Gi 78Gi
Swap: 16Gi 0.0Gi 16Gi
Significado: Mucha memoria disponible; ARC puede ser grande sin dejar sin recursos al espacio de usuario.
Decisión: Si la memoria disponible es baja y el swap está activo, arregla eso primero. L2ARC no sustituye la RAM cuando el OS está ahogándose.
Tarea 15: Línea base de la tasa de escritura de L2ARC (chequeo de endurance)
cr0x@server:~$ sudo smartctl -a /dev/nvme0 | sed -n '1,80p'
SMART/Health Information (NVMe Log 0x02)
Critical Warning: 0x00
Temperature: 41 Celsius
Available Spare: 100%
Percentage Used: 3%
Data Units Read: 18,240,112
Data Units Written: 9,882,441
Host Read Commands: 312,114,901
Host Write Commands: 210,441,022
Significado: “Data Units Written” tiende a subir con la alimentación L2ARC y la carga. Mídelo con el tiempo.
Decisión: Si la resistencia del dispositivo de caché se consume rápido, reduce el churn de L2ARC (políticas de dataset, L2ARC más pequeño, mejor dimensionamiento de ARC) o usa una unidad más duradera.
Guía de diagnóstico rápido
Estás en un incidente. No tienes tiempo para debates filosóficos sobre cachés. Aquí qué revisar primero, segundo, tercero, para encontrar el cuello de botella sin engañarte a ti mismo.
Primero: ¿es siquiera almacenamiento?
- Comprueba saturación de CPU del host y la cola de ejecución. Si la CPU está al máximo, la afinación de almacenamiento es una distracción.
- Comprueba esperas a nivel de aplicación (locks de BD, pools de hilos). Los gráficos de almacenamiento pueden parecer culpables por asociación.
Segundo: si es almacenamiento, ¿son lecturas, escrituras o metadatos?
- Lecturas: latencia alta de lectura en vdevs HDD; miss% de ARC subiendo; lecturas de L2ARC significativas.
- Escrituras síncronas: picos de latencia correlacionados con fsync; métricas de SLOG y latencia del dispositivo importan.
- Metadatos: recorridos de directorios lentos; operaciones VM lentas; misses de metadatos altos; un special vdev puede ser mejor.
Tercero: ¿el caché está ayudando o perjudicando ahora mismo?
- Tamaño de ARC cerca del máximo con mala ratio de aciertos: probablemente conjunto de trabajo demasiado grande o carga de streaming.
- Ratio de aciertos de L2ARC baja con alta utilización del dispositivo: churn de caché; reduce L2ARC o excluye datasets.
- Ratio de aciertos de L2ARC decente pero sin mejora de latencia: el pool puede ya ser rápido, o el cuello está en otro lado.
Cuarto: elige la palanca correcta
- Añadir RAM cuando ARC está constreñido y los misses de metadatos duelen.
- Añadir o afinar L2ARC cuando los misses de lectura son caros y hay reutilización.
- Añadir un special vdev cuando metadatos y bloques pequeños dominan.
- Arreglar políticas por dataset cuando backups o escaneos están contaminando el caché.
- Arreglar la carga cuando los patrones de acceso son patológicos (lecturas aleatorias enormes, desajuste de recordsize, escaneos sin control).
Tres micro-historias corporativas desde el frente
Micro-historia 1: El incidente causado por una suposición equivocada
La empresa ejecutaba un clúster de virtualización en un servidor de almacenamiento con ZFS: RAIDZ2 HDDs para capacidad, un par de NVMes para “cosas de rendimiento.” El equipo supuso que L2ARC era básicamente “más RAM pero más barato,” así que partieron la mayor parte de un NVMe en una porción de L2ARC de varios terabytes. Número grande, gran victoria. Esa fue la suposición.
Un mes después, un reinicio de mantenimiento rutinario se convirtió en una caída lenta. Tras el arranque, la latencia de las VM fue horrible durante horas. No “un poco degradada.” Inquilinos abrieron tickets. La dirección preguntó si el equipo de almacenamiento había cambiado algo. La respuesta fue “no,” que era técnicamente verdad y operacionalmente inútil.
La historia real: L2ARC había estado sosteniendo muchos bloques calientes de los que dependía el conjunto de trabajo en horas laborales. El reinicio lo borró. ARC solo no pudo sostener el conjunto. El L2ARC tardó mucho en calentarse porque la tasa de llenado no podía seguir el churn. Peor aún, durante el calentamiento consumía ancho de banda de I/O escribiendo contenido de caché mientras los inquilinos ya esperaban lecturas.
La solución no fue heroica. Redujeron L2ARC a unos cientos de gigabytes para que se calentara rápido, excluyeron datasets de backup del secondarycache y documentaron que los reinicios implican una ventana de calentamiento. El resultado sorprendente: un L2ARC más pequeño dió un rendimiento más estable y una ventana de “pos-reinicio” más corta.
Micro-historia 2: La optimización que salió mal
Otro equipo hospedaba un clúster de bases de datos en ZFS. Vieron misses de lectura y decidieron “ir con todo”: L2ARC masivo, ajustes agresivos para llenarlo más rápido y un NVMe brillante dedicado a caché. Los gráficos se vieron bien por un día. La ratio de aciertos subió. Todos se sintieron ingeniosos.
Luego empezaron las quejas por latencia de escritura. Ni siquiera en el dataset de la base de datos—en todo el host. El dispositivo NVMe de caché mostró alta utilización y latencia de escritura incrementada. El pool de HDD también se volvió más ocupado, aunque intentaban reducir lecturas. El equipo había construido una máquina que constantemente movía bloques a L2ARC, los expulsaba y repetía el proceso. El churn del caché se volvió una carga.
También estaban consumiendo RAM en metadatos de L2ARC, lo que silenciosamente redujo la capacidad de ARC para mantener metadatos realmente calientes residentes. Más misses de ARC. Más tráfico de disco. Ya puedes imaginar el resto.
El plan de rollback los salvó: desactivar la alimentación agresiva, recortar el tamaño de L2ARC y mover datasets pesados en metadatos a un special vdev. El rendimiento volvió al baseline. Después de eso, trataron L2ARC como un bisturí, no como un estilo de vida.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Una plataforma de medios tenía una flota de almacenamiento ZFS con cargas mixtas: subidas de usuarios, lecturas de transcodificación, escaneos analíticos y backups nocturnos. Nunca confiaron ciegamente en los cachés. Tenían una práctica constante: cada dataset de alto throughput tenía política de caché explícita, y cada dispositivo de caché tenía monitorización de endurance con alertas.
Una noche, los jobs analíticos cambiaron y empezaron a hacer escaneos grandes contra un dataset que aún estaba configurado con secondarycache=all. La ratio de aciertos L2ARC se desplomó, las escrituras NVMe subieron en pico y las cargas interactivas vieron mayor latencia. El sistema no murió; simplemente se volvió desagradable.
El on-call siguió su runbook: comprobar arcstat, confirmar churn de L2ARC, identificar el dataset por el horario de la carga y cambiar la política del dataset. Pusieron secondarycache=none en el dataset analítico y dejaron primarycache intacto. En minutos, L2ARC se estabilizó y el rendimiento interactivo se recuperó.
Sin heroicidades. Sin “debemos rediseñar el almacenamiento.” Solo higiene aburrida: políticas de caché por dataset y vigilar el dispositivo de caché como si fuera hardware de producción—porque lo es.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: el rendimiento empeoró tras añadir un L2ARC enorme
Causa raíz: La sobrecarga de metadatos de L2ARC y el churn de alimentación reducen el ARC efectivo y añaden carga de escritura; el caché almacena bloques de baja reutilización.
Solución: Reduce L2ARC; excluye datasets de streaming (secondarycache=none); confirma que ARC tiene margen; considera añadir RAM en su lugar.
2) Síntoma: la ratio de aciertos de L2ARC es baja (dígitos) y no mejora
Causa raíz: Carga de streaming/escaneos, baja reutilización, el caché se calienta demasiado lento, o los datasets no son elegibles para L2ARC.
Solución: Identifica datasets de escaneo y desactiva secondarycache; mantén L2ARC más pequeño; verifica ajustes de secondarycache; mide la ratio de aciertos en una ventana representativa.
3) Síntoma: gran ratio de aciertos de L2ARC pero la latencia no mejora
Causa raíz: El cuello de botella no son lecturas lentas (CPU, locks, red, escrituras sync, vdevs fragmentados). O el pool ya es SSD-rápido.
Solución: Correlaciona latencia de la app con r_await del dispositivo; revisa SLOG para cargas sync; revisa CPU y scheduling; no sigas comprando caché.
4) Síntoma: después de reinicio/failover, el sistema está lento por horas
Causa raíz: L2ARC no persistente (o persistencia ineficaz) más caché sobredimensionado con calentamiento lento; el conjunto de trabajo depende de bloques cacheados.
Solución: Reduce L2ARC; asegúrate de que la carga sea resiliente a caché frío; programa lecturas de calentamiento si procede; documenta el comportamiento esperado de calentamiento.
5) Síntoma: el dispositivo NVMe de caché se desgasta más rápido de lo esperado
Causa raíz: Alta churn y escrituras continuas de alimentación; L2ARC usado como depósito para datos fríos.
Solución: Reduce tamaño de caché; desactiva L2ARC para datasets de escaneo; elige una unidad con resistencia adecuada; monitoriza SMART “Percentage Used” y tendencias de bytes escritos.
6) Síntoma: listados de directorios, operaciones VM y cargas de “IO pequeño” son lentas
Causa raíz: Carga dominada por metadatos; L2ARC ayuda algo, pero la colocación persistente (special vdev) a menudo ayuda más.
Solución: Considera un special vdev para metadata/bloques pequeños; confirma comportamiento de misses de metadata; asegura suficiente RAM para metadatos en ARC.
7) Síntoma: el dispositivo de caché está al 100% de utilización con alta latencia de escritura
Causa raíz: Alimentación de L2ARC compitiendo con lecturas; dispositivo de caché demasiado pequeño/lento para el churn; alimentación agresiva.
Solución: Limita la tasa de alimentación/tunables donde sea aplicable; reduce L2ARC; pásate a NVMe más rápido; reduce datasets elegibles.
Listas de verificación / plan paso a paso
Lista de decisión: ¿deberías añadir L2ARC en absoluto?
- Medios del pool: ¿Mayormente HDD o backend de alta latencia? Si sí, L2ARC puede ayudar. ¿Todo-NVMe? Sé escéptico.
- ARC al máximo y aún hay misses: Confirma que ARC está en/near max y que los misses importan.
- Reutilización existe: Confirma que la carga revisita datos (no puro streaming).
- Margen de RAM: Asegura que el espacio de usuario no esté intercambiando; ARC pueda permitirse cierta sobrecarga de metadatos.
- Tolerancia operativa: ¿Estás de acuerdo con el calentamiento tras reinicio? Si no, mantenlo pequeño o planifica persistencia.
Paso a paso: dimensionar L2ARC de forma segura
- Baselina por 7 días. Captura: arcstat miss%, L2ARC hit%, latencia de dispositivos del pool y utilización del dispositivo de caché.
- Define políticas por dataset. Excluye backups/escaneos de L2ARC primero (
secondarycache=none). - Empieza con 200–400GB. Prefiere “pequeño y caliente” sobre “enorme y obsoleto”.
- Verifica que se esté usando. Revisa
zpool iostatlecturas en “cache” y la ratio de aciertos de L2ARC. - Vigila comportamiento de RAM. Tamaño de ARC, misses de metadatos y disponibilidad de memoria del sistema.
- Vigila endurance. Rastrear escrituras NVMe y “Percentage Used” con el tiempo.
- Crece solo con evidencia. Si la ratio de aciertos mejora y la latencia baja sin dejar sin ARC, escala en incrementos.
- Mantén un plan de rollback. Sé capaz de desacoplar el dispositivo de caché y revertir políticas de dataset rápidamente.
Cuándo dejar de aumentar L2ARC
- Los misses de metadatos de ARC suben o ARC se encoge notablemente.
- La utilización del dispositivo de caché sube sin una caída correspondiente de latencia.
- La ratio de aciertos de L2ARC se estanca: gigabytes extra almacenan bloques cada vez más fríos.
- El tiempo de calentamiento se vuelve operacionalmente doloroso.
Preguntas frecuentes
1) ¿Vale la pena L2ARC en un pool todo-SSD o todo-NVMe?
Usualmente no. Si tu pool ya sirve lecturas aleatorias en territorio submilisegundo, L2ARC añade complejidad, sobrecarga de RAM y carga de escritura por pequeñas ganancias. Invierte esfuerzo en dimensionar ARC, recordsize y ajuste de la carga primero.
2) ¿Por qué un L2ARC más pequeño se calienta más rápido?
Porque el caché se llena con el tiempo. Un caché más pequeño alcanza un conjunto representativo de bloques expulsados frecuentemente antes. Un caché enorme puede permanecer parcialmente irrelevante por largos periodos bajo churn.
3) ¿Puede L2ARC causar mayor latencia incluso si la ratio de aciertos mejora?
Sí. Si llenar L2ARC compite con I/O del pool o el dispositivo de caché se convierte en cuello de botella, puedes aumentar trabajo en segundo plano. Además, si los metadatos de L2ARC reducen la efectividad de ARC, pierdes aciertos baratos en ARC y terminas haciendo más I/O lento.
4) ¿Debería añadir RAM en lugar de L2ARC?
Si puedes, sí—especialmente cuando tu ARC está constreñido y los misses de metadatos duelen. La RAM mejora ARC directamente, ayuda metadatos y no tiene calentamiento ni problemas de endurance. L2ARC es para cuando el conjunto de trabajo es mayor que la RAM y los misses de lectura son caros.
5) ¿L2ARC ayuda escrituras?
No. L2ARC es un caché de lectura. Si tu dolor es latencia de escrituras síncronas, mira SLOG, ajustes de sync y patrones de fsync de la aplicación.
6) ¿Qué ajustes de dataset importan más para el comportamiento de L2ARC?
secondarycache controla la elegibilidad para L2ARC. primarycache controla la elegibilidad para ARC. recordsize afecta granularidad y eficiencia del caché. La compresión puede ayudar ajustando más datos lógicos por byte cacheado.
7) ¿Un special vdev es mejor que L2ARC?
Herramientas distintas. Un special vdev cambia la colocación para metadatos (y opcionalmente bloques pequeños), mejorando a menudo la latencia de forma predecible para cargas dominadas por metadatos. L2ARC cachea lo que ARC expulsa. Si tu cuello de botella son metadatos y lecturas aleatorias pequeñas, los special vdevs frecuentemente superan a “añadir más L2ARC”.
8) ¿Cuál es una buena ratio objetivo de aciertos L2ARC?
No hay número mágico. En pools HDD, incluso 10–20% puede ser una gran mejora si pega lecturas caras. En pools SSD rápidos, necesitarías mucho más para justificar la sobrecarga. Siempre relaciónalo con mejoras de latencia y reducción del r_await en HDD.
9) ¿Cómo evito que backups y escaneos destrocen mi caché?
Pónlos en su propio(s) dataset(s) y establece secondarycache=none. Para streams especialmente abusivos, considera primarycache=metadata también, según patrones de acceso.
10) ¿Qué pasa si falla el dispositivo L2ARC?
ZFS puede seguir funcionando; es un dispositivo de caché, no de datos. Pero la falla aún puede crear ruido operacional: errores de I/O, timeouts y cambios de rendimiento a medida que desaparecen los aciertos. Monitorízalo y prepárate para desacoplarlo limpiamente.
Conclusión: siguientes pasos prácticos
Si estás a punto de comprar 2TB de “caché” porque tu caja ZFS se siente lenta, haz una pausa. Mide primero. El mejor tamaño para L2ARC rara vez es “tan grande como sea posible.” Es “tan pequeño como sea necesario para capturar los misses reutilizados sin robarle el almuerzo al ARC.”
Siguientes pasos que puedes hacer esta semana
- Ejecuta
arcstatdurante el pico y correlaciona miss% con latencia visible por los usuarios. - Lista datasets y marca a los streamers: backups, escaneos analíticos, copias masivas. Establece
secondarycache=noneen ellos. - Si ya tienes L2ARC, verifica la ratio de aciertos y la utilización del dispositivo de caché. Si es baja en aciertos y alta en ocupación, redúcelo.
- Toma una decisión: si estás limitado por memoria, compra RAM antes que caché.
- Si los metadatos son tu problema, planea un special vdev en lugar de un L2ARC más grande.
Haz el trabajo aburrido de medición. Luego elige el cambio más pequeño que te dé una mejora estable. Así evitas que los cachés se conviertan en un segundo trabajo.