ZFS te da un superpoder: convierte la RAM disponible en ARC, una caché de lectura que puede hacer que los discos giratorios parezcan sorprendentemente capaces. Entonces alguien ve un SSD libre y empieza la conversación: “¿Y si añadimos un L2ARC?”
A veces L2ARC es una victoria clara. Otras veces es un incidente en cámara lenta: rotación de caché, desgaste del SSD y un presupuesto de RAM que desaparece silenciosamente en metadatos. Esta es la guía de producción que desearía que todo el mundo leyera antes de teclear zpool add ... cache ... un viernes.
Qué es realmente L2ARC (y qué no lo es)
L2ARC es una caché de lectura de segundo nivel para ZFS. ARC vive en RAM. L2ARC vive en dispositivos rápidos (normalmente SSD/NVMe). El objetivo es simple: cuando tu conjunto de trabajo no cabe en RAM, mantener los “bloques más valiosos siguientes” en SSD en lugar de recuperarlos de discos lentos o almacenamiento remoto.
Pero L2ARC no es un interruptor mágico de “hacer almacenamiento más rápido”. Es selectivo. Es oportunista. Tiene costes. Y tiene temperamento.
Qué es L2ARC
- Una caché de datos que ya se han leído (y, dependiendo de la configuración e implementación, a veces también prerrecuperados o metadatos).
- Alimentada por ARC: los bloques entran primero en ARC y luego algunos se promueven a L2ARC.
- Más útil cuando tu carga tiene lecturas repetidas con un conjunto de trabajo más grande que la RAM pero más pequeño que RAM+L2ARC (y lo suficientemente estable para precalentarse).
Qué no es L2ARC
- No es una caché de escritura (eso es otra conversación que involucra SLOG/ZIL).
- No reemplaza a la RAM. ARC sigue haciendo el trabajo pesado, y L2ARC puede consumir RAM para operar.
- No es una solución garantizada para la latencia. Si tu cuello de botella es CPU, fragmentación, escrituras síncronas o red, L2ARC puede no hacer nada —o añadir nuevos problemas.
Broma corta, como corresponde: L2ARC es como una cuota de gimnasio: te sientes productivo al adquirirla, pero los resultados dependen de presentarte regularmente.
Hechos e historia: por qué L2ARC se comporta así
Un poco de contexto ayuda. L2ARC no surgió en un mundo de NVMe barato y servidores con RAM gigantes. Vino de una era en la que “rápido” significaba “unos cuantos SSD decentes y una plegaria”. Algunos hechos y notas históricas concretas que importan operacionalmente:
- ARC de ZFS precede a la economía actual del NVMe. ARC fue diseñado para usar RAM agresivamente porque la RAM era el almacenamiento más rápido que podías comprar sin una reunión especial de compras.
- L2ARC se construyó como una extensión de ARC, no como un sistema de caché separado. Por eso los metadatos y las políticas de ARC influyen mucho en lo que aterriza en L2ARC.
- El L2ARC temprano no persistía entre reinicios. Un reinicio significaba una caché fría y un largo calentamiento. El trabajo posterior de OpenZFS introdujo conceptos de L2ARC persistente, pero aún debes validar el comportamiento en tu plataforma.
- La resistencia de los SSD solía ser una restricción de primer orden. Las “alimentaciones” de L2ARC pueden escribir muchos datos. Los SSD antiguos SLC/SATA lo soportaban; los TLC de consumo baratos pueden morir dramáticamente si los tratas como un vertedero tipo log-structured.
- ARC es adaptativo, pero no omnisciente. Reacciona a patrones de acceso que ha visto; no predice tu próximo trabajo por lotes, la avalancha de inicios de sesión del lunes ni tu ejecución trimestral de analítica.
- Los metadatos de ZFS pueden dominar el I/O en algunas cargas. Si estás rastreando directorios, ejecutando backups o gestionando imágenes de VM con churn, los fallos de metadatos pueden perjudicar más que los fallos de datos.
- El nombre “caché de segundo nivel” es algo engañoso. No es una caché L2 clásica inclusiva de CPU. Puedes tener bloques en ARC y en L2ARC, y el sistema paga sobrecarga para rastrearlos.
- Las alternativas modernas cambiaron la hoja de decisiones. Vdevs especiales para metadatos/bloques pequeños y vdevs primarios más rápidos suelen superar a “lanzar un L2ARC” en muchos casos, especialmente para pools con muchas lecturas aleatorias.
Cómo funciona L2ARC bajo el capó
Seamos precisos sobre la ruta de datos, porque la mayoría de los incidentes con L2ARC comienzan con un modelo mental vago.
La ruta de lectura en la práctica
Cuando una aplicación solicita un bloque:
- ZFS comprueba ARC (RAM). Si acierta: la lectura es lo más rápida posible, has terminado.
- Si ARC falla, ZFS comprueba si el bloque está en L2ARC (SSD). Si acierta: pagas la latencia del SSD y cierta sobrecarga de CPU, pero evitas el disco giratorio o la latencia de red.
- Si L2ARC falla: ZFS lee desde los vdevs principales (HDD/SSD), entonces el bloque entra en ARC. Más tarde, puede escribirse en L2ARC según la política y la tasa de alimentación.
Alimentar L2ARC no es gratis
L2ARC no se popula por arte de magia; se escribe en él. Esas escrituras provienen de buffers gestionados por ARC y están gobernadas por parámetros que limitan cuán agresivamente ZFS empuja datos a L2ARC. Eso significa:
- Si tu carga cambia rápidamente, L2ARC puede pasar su tiempo cachéando las noticias de ayer.
- Si la tasa de alimentación es demasiado agresiva, puedes crear presión de escritura, desgaste del SSD y sobrecoste de CPU, mientras robas espacio de ARC para encabezados/metadatos.
El problema de la sobrecarga en RAM (la parte que la gente olvida)
Para ser útil, L2ARC necesita saber qué hay en él. Ese mapeo no se almacena completamente en el SSD; ZFS mantiene metadatos en RAM para poder decidir rápidamente si un bloque solicitado está en caché y dónde se encuentra.
Traducción operativa: un dispositivo L2ARC grande puede consumir silenciosamente una cantidad no trivial de RAM. Si ya tienes poca memoria, añadir L2ARC puede reducir la efectividad del ARC y aumentar la rotación de expulsiones—convirtiendo una caché de lectura en un impuesto de rendimiento.
La efectividad de la caché depende de la localidad de acceso
L2ARC funciona mejor cuando existe “reutilización”: los mismos bloques se leen una y otra vez durante minutos/horas/días. Si tu carga es un escaneo de una sola pasada sobre un conjunto de datos (lecturas en streaming, backups, grandes escaneos analíticos), L2ARC mayormente registra tu recorrido y luego lo olvida—tras cobrarte por las fotos de recuerdo.
Segunda broma, como corresponde: en producción, L2ARC es inocente hasta que se demuestre lo contrario, pero tiene excelentes abogados y un informe de gastos sospechoso.
Cuándo L2ARC ayuda (y qué significa “ayuda” realmente)
L2ARC no busca hacer tus lecturas más rápidas aún; se trata de convertir tus lecturas comunes más lentas en lecturas “bastante rápidas”. Los mejores candidatos comparten algunos rasgos.
Buenas encajas
- Cargas intensivas en lectura donde el conjunto activo es más grande que la RAM pero lo suficientemente pequeño como para caber en RAM+L2ARC.
- Conjuntos de trabajo estables: tormentas de arranque VDI, binarios de servidores web/app, capas de imágenes de contenedores que se reutilizan, bibliotecas compartidas en servidores de compilación, repositorios de paquetes.
- Lecturas aleatorias sensibles a latencia desde pools HDD donde cada fallo cuesta milisegundos.
- Entornos donde no puedes añadir suficiente RAM (costo, ranuras, restricciones de plataforma), pero puedes añadir un SSD de tamaño y durabilidad adecuados.
Cómo se ve el éxito (medible)
En sistemas reales, “L2ARC ayudó” típicamente significa:
- La tasa de aciertos de ARC se mantiene alta, y la tasa de aciertos de L2ARC es significativa (no solo ruido).
- Las IOPS de lectura de disco bajan, o la latencia de lectura del disco mejora con la misma carga.
- La latencia cola aplicada mejora (p95/p99), no solo el rendimiento medio.
- La sobrecarga de CPU permanece aceptable; no cambiaste la latencia del disco por tiempo de kernel excesivo.
Importante: puede ayudar incluso con una tasa de aciertos modesta
Si tu pool subyacente usa HDD, aun una tasa de aciertos modesta en L2ARC puede ser valiosa. Reemplazar una lectura aleatoria de 10 ms con una lectura SSD de 100 µs–1 ms cambia la forma de la cola y reduce los bloqueos por cabecera. Pero aún necesitas verificar: si el sistema ya está limitado por otra cosa, solo moverás el problema a otro sitio.
Cuándo L2ARC perjudica: los modos de fallo
L2ARC no “perjudica” porque los SSD sean lentos. Perjudica porque añades un subsistema con sus propios costes, y esos costes aparecen exactamente donde ZFS es sensible: memoria, CPU y planificación de I/O.
Modo de fallo 1: presión de RAM y colapso del ARC
El clásico: añades un gran dispositivo L2ARC a una máquina que funcionaba bien solo con ARC. De repente el host empieza a hacer swapping, ARC se reduce, aumenta la rotación de expulsiones y todo se vuelve más lento—incluso lecturas que antes daban en ARC.
Patrón de síntomas: más fallos de página, mayor CPU de sistema, tamaño de ARC oscilando y picos de latencia bajo carga. La gente culpa “al SSD”, pero generalmente es economía de memoria.
Modo de fallo 2: rotación de caché y precalentamiento que no termina
Si tu conjunto de trabajo cambia más rápido de lo que L2ARC puede adaptarse, se convierte en un museo de bloques que antes te importaban. Pagas la sobrecarga de alimentación y obtienes pocos aciertos. Esto es común en:
- Grandes escaneos secuenciales
- Ventanas de backup que tocan todo una vez
- Grandes consultas analíticas que recorren datasets linealmente
- Sistemas CI que consumen muchos artefactos únicos
Modo de fallo 3: amplificación de escritura del SSD y desgaste prematuro
Los dispositivos L2ARC se escriben constantemente. En algunas cargas, el volumen de escrituras puede ser sustancial. Si usas un SSD de consumo con resistencia mediocre y mal comportamiento en escrituras sostenidas, puedes acabar con:
- Degradación del rendimiento del SSD tras agotarse la caché SLC
- GC en segundo plano que amplifica la latencia
- Consumo de resistencia que se convierte en una cinta de reemplazo
Modo de fallo 4: inversión de latencia
Ocasionalmente, L2ARC puede introducir una “velocidad intermedia” que es más lenta que ARC pero aun así consume CPU y recursos de colas. Si tu pool subyacente ya es SSD/NVMe y tu ARC es suficiente, los aciertos en L2ARC pueden ser más lentos que una lectura bien comportada del pool—especialmente si el dispositivo L2ARC está compartido, ocupado o estrangulado.
Modo de fallo 5: complejidad operativa no presupuestada
Añadir L2ARC significa otra clase de dispositivo que monitorizar, reemplazar y planificar en capacidad. También puede complicar el análisis de rendimiento: ahora una lectura puede venir de ARC, L2ARC o del pool, y necesitas saber qué camino domina a las 3 a.m.
Tres micro-historias del mundo corporativo
Micro-historia #1: El incidente causado por una suposición equivocada (“caché SSD = más velocidad”)
La configuración parecía razonable: un servicio de archivos empresarial de tamaño medio sobre un pool RAIDZ2 HDD, muchos clientes y una queja persistente de que los lunes por la mañana iba lento. Alguien añadió un gran SSD SATA como L2ARC durante el fin de semana. La cola de tickets se quedó tranquila durante aproximadamente una hora el lunes. Luego el panel de monitorización brilló como una máquina de pinball.
La latencia subió. El tiempo de CPU en sistema aumentó. La máquina empezó a intercambiar. El equipo de aplicaciones insistía “pero añadimos un SSD, debe ser más rápido”. Mientras tanto, los gráficos de almacenamiento mostraban que el pool HDD ni siquiera estaba saturado; el problema era la presión de memoria y la rotación de reclaim. Los encabezados de L2ARC se habían comido la RAM, ARC se redujo y los metadatos calientes de la carga dejaron de caber. El sistema hizo más I/O real que antes, no menos.
La suposición equivocada fue sutil: creían que L2ARC reemplazaría lecturas de disco sin afectar a nada más. En realidad, L2ARC necesitaba RAM para indexarlo, y esa RAM se tomó del mismo ARC que hacía tolerable el sistema. Una vez que el SO empezó a paginar, cada “optimización” se convirtió en una autoinfligida denegación de servicio.
La solución fue aburrida: quitar L2ARC, añadir RAM y abordar el dolor real—tránsitos de metadatos pesados durante scripts de inicio de sesión. Un intento posterior usó un dispositivo L2ARC mucho más pequeño y expectativas afinadas. La gran mejora vino finalmente de reducir la tormenta de metadatos y mover los archivos pequeños más frecuentemente accedidos a almacenamiento primario más rápido.
Micro-historia #2: La optimización que salió mal (“Hagámoslo cachear más fuerte”)
Un clúster de virtualización tenía un datastore respaldado por ZFS. Las lecturas eran espigas: tormentas de arranque, ciclos de parches y ocasionales “todos inician sesión a la vez”. L2ARC se instaló y pareció levemente útil. Luego alguien decidió ajustarlo agresivamente—alimentación más rápida, dispositivo más grande y “cachear más cosas”. Los gráficos se vieron geniales durante la primera ventana de prueba, que es la señal de que estás a punto de aprender algo caro.
Dos semanas después, el soporte empezó a ver picos de latencia intermitentes. No constantes, no predecibles. El equipo de hipervisores culpó a la red. El equipo de red culpó al almacenamiento. Almacenamiento culpó “desconocido”. La única señal consistente era que el dispositivo L2ARC ocasionalmente llegaba al 100% de utilización durante horas ocupadas, y la máquina pasaba mucho tiempo en hilos del kernel.
El efecto adverso fue amplificación de escritura y contención. Alimentar L2ARC más fuerte aumentó las escrituras al dispositivo de caché, que competían con I/O legítimo del pool en la misma línea de controlador. El GC interno del SSD empezó a aparecer como jitter de latencia. El sistema no estaba “más lento” en promedio; era menos estable, que los usuarios perciben como “está roto”.
La solución eventual: aflojar los ajustes, mover el dispositivo de caché a un camino menos contestado y priorizar latencia consistente sobre rendimiento sintético. L2ARC se quedó, pero se trató como un bisturí en lugar de un soplador de hojas.
Micro-historia #3: La práctica aburrida pero correcta que salvó el día (“Medir primero, cambiar una vez”)
Un equipo de plataforma de datos quería L2ARC para un servicio de analítica. La petición venía con urgencia—las quejas de rendimiento eran fuertes y alguien ya había pedido NVMe. El SRE de guardia hizo lo menos emocionante posible: tomó una línea base y se negó a saltársela.
Capturaron estadísticas de ARC, latencia del pool y p95 de lectura a nivel de aplicación durante carga normal y durante un trabajo pesado conocido. También validaron que el dolor eran lecturas aleatorias de datos algo fríos, no saturación de CPU ni una VM vecina ruidosa. La línea base mostró algo inesperado: ARC ya estaba funcionando bien y la mayoría de los fallos eran lecturas secuenciales largas desencadenadas por escaneos por lotes. L2ARC cachearía el escaneo de ayer y sería inútil hoy.
En lugar de desplegar L2ARC, usaron el presupuesto NVMe para añadir un vdev especial para metadatos y bloques pequeños en un pool de prueba, y ajustaron recordsize/compresión para la carga. No fue glamuroso. Pero las quejas de “listado de directorio lento” y “la primera consulta es horrible” cayeron drásticamente, y el sistema se volvió más predecible bajo carga.
La práctica que salvó el día no fue un tunable secreto. Fue la disciplina de medir el tipo de fallo real y luego elegir el mecanismo que lo aborda. L2ARC es genial cuando el fallo es “datos calientes no caben en RAM”. Es mediocre cuando el fallo es “escaneamos todo una vez”.
Plan de diagnóstico rápido
Este es el orden de operaciones para “entrar en el incidente”. La idea es identificar el cuello de botella en minutos, no ganar una discusión en Slack.
Paso 1: ¿Es presión de memoria o comportamiento de caché?
- Comprueba swapping/paginación y estabilidad del tamaño de ARC.
- Si el sistema está intercambiando, L2ARC es culpable hasta que se demuestre lo contrario.
Paso 2: ¿Las lecturas vienen de ARC, L2ARC o del disco?
- Comprueba las tasas de aciertos de ARC/L2ARC y las tasas de lectura.
- Confirma si L2ARC realmente está sirviendo lecturas (no solo siendo escrito).
Paso 3: ¿Es el propio dispositivo L2ARC el cuello de botella?
- Busca alta utilización, alto await o estrangulamiento en el dispositivo de caché.
- Vigila picos de latencia consistentes con GC del SSD.
Paso 4: ¿El pool subyacente está lento por otra razón?
- Comprueba latencia de I/O del pool y profundidad de cola.
- Busca fragmentación, disco fallando o un problema de camino del controlador.
Paso 5: Valida si la carga encaja
- Si son escaneos secuenciales, L2ARC rara vez brillará.
- Si son lecturas pequeñas aleatorias con reutilización, L2ARC puede ser valioso.
Listas de verificación / plan paso a paso (con comandos)
Estas tareas asumen un sistema Linux con OpenZFS. Los comandos son realistas, pero algunos archivos/rutas varían por distro y versión de ZFS. La meta es operaciones repetibles: observar, decidir, cambiar, verificar.
Tarea 1: Verificar la salud del pool antes de culpar a la caché
cr0x@server:~$ sudo zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:31:10 with 0 errors on Sun Dec 22 03:10:11 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
cache
nvme0n1 ONLINE 0 0 0
errors: No known data errors
Interpretación: Si el pool no está limpio, los síntomas de rendimiento pueden ser efectos secundarios (reintentos, resilver, errores de checksum). Arregla la salud primero.
Tarea 2: Confirmar dispositivos L2ARC y cómo están conectados
cr0x@server:~$ sudo zpool list -v
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 72.5T 51.2T 21.3T - - 28% 70% 1.00x ONLINE -
raidz2 72.5T 51.2T 21.3T - - 28% 70%
sda - - - - - - -
sdb - - - - - - -
sdc - - - - - - -
sdd - - - - - - -
cache - - - - - - -
nvme0n1 1.8T 820G 1.0T - - - -
Interpretación: Los dispositivos L2ARC aparecen bajo cache. Si pretendías un caché en espejo y ves solo un dispositivo, es una decisión de riesgo que quizás no querías tomar.
Tarea 3: Instantánea de “qué está pasando ahora” en una pantalla
cr0x@server:~$ sudo zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 51.2T 21.3T 1.20K 650 210M 95.4M
raidz2 51.2T 21.3T 1.20K 650 210M 95.4M
sda - - 310 160 54.0M 23.4M
sdb - - 280 170 48.9M 24.2M
sdc - - 320 150 56.1M 21.9M
sdd - - 290 170 51.0M 25.9M
cache - - 1.80K 0 290M 0
nvme0n1 - - 1.80K 0 290M 0
---------- ----- ----- ----- ----- ----- -----
Interpretación: Si las lecturas del dispositivo de caché son altas mientras las lecturas del pool son bajas, L2ARC está sirviendo activamente. Si las lecturas del caché están cerca de cero, L2ARC no está ayudando (o aún se está calentando, o la carga no reutiliza).
Tarea 4: Comprobar estadísticas principales de ARC y L2ARC
cr0x@server:~$ grep -E "^(size|c_max|c_min|hits|misses|l2_hits|l2_misses)" /proc/spl/kstat/zfs/arcstats
size 4 68424495104
c_max 4 82463372032
c_min 4 10307921510
hits 4 12943923810
misses 4 1829381021
l2_hits 4 540128112
l2_misses 4 128925291
Interpretación: ARC está en ~68 GiB, máximo ~82 GiB. L2ARC tiene aciertos; ahora calcula si esa tasa es significativa para tu ventana de trabajo, no la vida útil desde el arranque.
Tarea 5: Calcular ratios rápidos de aciertos (ARC y L2ARC)
cr0x@server:~$ python3 - <<'PY'
import re
stats={}
with open("/proc/spl/kstat/zfs/arcstats") as f:
for line in f:
parts=line.split()
if len(parts)==3:
stats[parts[0]]=int(parts[2])
hits=stats.get("hits",0); misses=stats.get("misses",0)
l2h=stats.get("l2_hits",0); l2m=stats.get("l2_misses",0)
arc_total=hits+misses
l2_total=l2h+l2m
print(f"ARC hit ratio: {hits/arc_total:.3f} ({hits}/{arc_total})" if arc_total else "ARC: n/a")
print(f"L2ARC hit ratio: {l2h/l2_total:.3f} ({l2h}/{l2_total})" if l2_total else "L2ARC: n/a")
PY
ARC hit ratio: 0.876 (12943923810/14773304831)
L2ARC hit ratio: 0.807 (540128112/669053403)
Interpretación: Ratios de vida alta pueden engañar si la carga cambió. Vuelve a muestrear deltas sobre 60–300 segundos durante el periodo problemático.
Tarea 6: Muestrear deltas de ARC/L2ARC en el tiempo (método para incidentes reales)
cr0x@server:~$ for i in {1..5}; do
awk '($1=="hits"||$1=="misses"||$1=="l2_hits"||$1=="l2_misses"){print $1,$3}' /proc/spl/kstat/zfs/arcstats
sleep 2
done
hits 12943990112
misses 1829390029
l2_hits 540132882
l2_misses 128925900
hits 12944081201
misses 1829409110
l2_hits 540139551
l2_misses 128926499
hits 12944174500
misses 1829428800
l2_hits 540146002
l2_misses 128927101
hits 12944260110
misses 1829442301
l2_hits 540151774
l2_misses 128927690
hits 12944350990
misses 1829461988
l2_hits 540158441
l2_misses 128928291
Interpretación: Calcula ratios de aciertos entre deltas. Si los deltas de L2ARC muestran pocos aciertos pero muchos fallos, no está en la ruta de lectura de forma significativa.
Tarea 7: Confirmar que no estás haciendo swapping (el asesino silencioso de rendimiento)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 128Gi 97Gi 2.1Gi 1.2Gi 29Gi 24Gi
Swap: 8.0Gi 1.6Gi 6.4Gi
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
5 0 1652280 2211140 112000 23210400 12 28 3180 1200 5200 9800 12 18 55 15 0
6 1 1652280 1976200 111900 23180200 0 64 4020 990 5600 10100 10 22 50 18 0
Interpretación: Swap-in/swap-out distinto de cero durante la carga es una señal clara. Si ves si/so sostenido, arregla la presión de memoria antes de afinar L2ARC.
Tarea 8: Identificar si el dispositivo L2ARC está saturado
cr0x@server:~$ iostat -x 1 5
Linux 6.8.0 (server) 12/25/2025 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
11.20 0.00 18.90 14.30 0.00 55.60
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
nvme0n1 1800.0 297000.0 0.0 0.00 1.40 165.0 40.0 8000.0 3.10 2.80 96.00
sda 300.0 54000.0 2.0 0.60 10.20 180.0 160.0 24000.0 9.50 5.10 88.00
Interpretación: Si el dispositivo de caché está en ~100% de utilización con await en aumento, puede volverse el cuello de botella—especialmente si los aciertos L2ARC dominan.
Tarea 9: Inspeccionar kstats relacionados con L2ARC para tamaño y comportamiento de alimentación
cr0x@server:~$ grep -E "^(l2_size|l2_asize|l2_hdr_size|l2_write_bytes|l2_read_bytes|l2_writes_sent|l2_evicts)" /proc/spl/kstat/zfs/arcstats
l2_size 4 912345678912
l2_asize 4 1000204886016
l2_hdr_size 4 2147483648
l2_write_bytes 4 18765432109876
l2_read_bytes 4 7654321098765
l2_writes_sent 4 987654321
l2_evicts 4 123456789
Interpretación: l2_hdr_size es la sobrecarga en RAM para el bookkeeping de L2ARC. Si son varios GiB y estás justo de memoria, tu “caché” puede estar rentando RAM a precio de prima.
Tarea 10: Añadir un dispositivo L2ARC de forma segura (y verificar)
cr0x@server:~$ sudo zpool add tank cache /dev/disk/by-id/nvme-SAMSUNG_MZQLB1T9HAJR-00007_S4XXXXXXXXX
cr0x@server:~$ sudo zpool status -v 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
cache
nvme-SAMSUNG_MZQLB1T9HAJR-00007_S4XXXXXXXXX ONLINE 0 0 0
Interpretación: Usa siempre rutas de dispositivo estables (by-id). Tras añadir, aún necesitas validar que está sirviendo lecturas y no empujando al host a presión de memoria.
Tarea 11: Eliminar un dispositivo L2ARC durante la resolución
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
errors: No known data errors
Interpretación: Quitar L2ARC suele ser seguro porque es una caché. El riesgo real es el descenso de rendimiento si en verdad te beneficiabas. Úsalo como palanca A/B.
Tarea 12: Distinguir L2ARC de SLOG (la gente los confunde constantemente)
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
nvme2n1 ONLINE 0 0 0
logs
mirror-1 ONLINE 0 0 0
nvme3n1 ONLINE 0 0 0
nvme4n1 ONLINE 0 0 0
Interpretación: Los dispositivos bajo logs son SLOG (para acelerar escrituras síncronas). Los dispositivos bajo cache son L2ARC (caché de lectura). Diferentes problemas, diferentes soluciones.
Tarea 13: Vigilar comportamiento de lectura por dataset (compresión, recordsize)
cr0x@server:~$ sudo zfs get -o name,property,value,source compression,recordsize,primarycache,secondarycache tank/vmstore
NAME PROPERTY VALUE SOURCE
tank/vmstore compression lz4 local
tank/vmstore recordsize 128K local
tank/vmstore primarycache all default
tank/vmstore secondarycache all default
Interpretación: Si secondarycache=none, L2ARC no cachéará ese dataset. Esto puede ser intencional (evitar contaminación por escaneos) o accidental (¿por qué L2ARC es inútil?).
Tarea 14: Excluir datasets con muchos escaneos de L2ARC para reducir rotación
cr0x@server:~$ sudo zfs set secondarycache=none tank/backups
cr0x@server:~$ sudo zfs get secondarycache tank/backups
NAME PROPERTY VALUE SOURCE
tank/backups secondarycache none local
Interpretación: Esta es una de las acciones de ajuste con mayor retorno: evita que backups/escaneos inunden L2ARC con lecturas de una sola pasada.
Tarea 15: Confirmar comportamiento TRIM para dispositivos SSD de caché
cr0x@server:~$ sudo zpool get autotrim tank
NAME PROPERTY VALUE SOURCE
tank autotrim on local
Interpretación: TRIM puede ayudar al rendimiento sostenido del SSD. Si activarlo depende de tus SSDs y versión de kernel/ZFS, pero “apagado para siempre” suele ser inercia heredada.
Tarea 16: Crear un benchmark rápido de antes/después que no mienta demasiado
cr0x@server:~$ sudo bash -c 'echo 3 > /proc/sys/vm/drop_caches'
cr0x@server:~$ sudo zpool iostat -v tank 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 51.2T 21.3T 900 10 180M 1.2M
cache - - 20 0 2.0M 0
nvme0n1 - - 20 0 2.0M 0
Interpretación: Vaciar caches es disruptivo y no representa “vida real”, pero puede demostrar si tu carga alguna vez alcanza L2ARC. Úsalo con cuidado, idealmente en un sistema de prueba o en una ventana controlada.
Errores comunes: síntomas específicos y soluciones
Error 1: Usar L2ARC para arreglar un problema de escritura
Síntoma: Escrituras síncronas lentas, latencia de commit de base de datos, NFS con sync sufriendo, pero las lecturas están bien.
Solución: L2ARC no ayudará. Investiga SLOG, ajustes de sync, latencia de dispositivos de log y patrones de escritura de la aplicación. Confirma con zpool iostat y métricas de carga.
Error 2: Añadir un L2ARC enorme a un host con memoria limitada
Síntoma: Tras añadir L2ARC, el tamaño de ARC baja, el uso de swap sube, la CPU del sistema aumenta y la latencia empeora.
Solución: Quita o reduce L2ARC. Añade RAM. Revisa l2_hdr_size y paginación (vmstat). L2ARC no es “capacidad gratis”.
Error 3: Caché de datasets con muchos escaneos y envenenamiento de la caché
Síntoma: Escrituras L2ARC altas, tasa de aciertos L2ARC baja y degradación de rendimiento durante ventanas de backup/escaneo.
Solución: Ajusta secondarycache=none en datasets con muchos escaneos (backups, scratch analítico, salidas ETL de una sola pasada). Reserva L2ARC para lecturas reutilizables.
Error 4: Elegir el SSD equivocado (unidad de consumo, mala escritura sostenida, firmware pobre)
Síntoma: El dispositivo de caché muestra picos de latencia periódicos, el rendimiento es “bien y luego horrible”, los indicadores de desgaste SMART suben rápidamente.
Solución: Usa SSDs empresariales con QoS predecible y resistencia adecuada. Monitoriza SMART. Considera sobreprovisionamiento y TRIM.
Error 5: Esperar mejora instantánea justo después de habilitar L2ARC
Síntoma: “Añadimos L2ARC y no cambió nada”.
Solución: L2ARC se calienta con el tiempo. Valida con muestreos de delta de hits/misses durante la carga. Si el conjunto de trabajo no se reutiliza, puede que nunca ayude.
Error 6: L2ARC sobre pools ya rápidos all-NVMe sin un cuello de botella claro
Síntoma: Ninguna ganancia medible, a veces latencia ligeramente peor por la sobrecarga.
Solución: Prefiere más RAM (ARC más grande) o ajustar la carga/dataset. En pools muy rápidos, la capa extra de L2ARC puede ser una complejidad innecesaria.
Preguntas frecuentes
1) ¿L2ARC cachea escrituras?
No. L2ARC es una caché de lectura. Las escrituras van al pool (y posiblemente a ZIL/SLOG para semántica síncrona). Si tu problema es latencia de escritura, mira en otra parte.
2) ¿Por qué añadir un SSD de caché puede empeorar el rendimiento?
Porque L2ARC tiene sobrecostes: consume RAM para metadatos de caché, CPU para gestionarlo y ancho de banda de I/O para poblarlo. Si esos costes exceden las lecturas de disco ahorradas—o desencadenan swapping—el rendimiento baja.
3) ¿Qué tamaño debería tener mi L2ARC?
Suficientemente grande para contener la parte “caliente pero no más caliente” de tu conjunto de trabajo, pero no tanto que la sobrecarga de metadatos devore tu presupuesto de RAM. En producción, el tamaño correcto suele estar limitado por la RAM primero, no por la capacidad del SSD.
4) ¿Cómo sé si L2ARC se está usando realmente?
Mira zpool iostat -v para lecturas del dispositivo de caché y comprueba deltas de l2_hits en /proc/spl/kstat/zfs/arcstats durante la ventana de carga. Las estadísticas de vida útil pueden engañar.
5) ¿Debería reflejar los dispositivos L2ARC?
Normalmente no es necesario porque es una caché y se puede reconstruir. Pero si perderlo causa una caída de rendimiento inaceptable y el tiempo de reemplazo importa, el mirroring puede ser una decisión de negocio. Operacionalmente: trátalo como “redundancia de rendimiento”, no de datos.
6) ¿Existe L2ARC persistente?
En algunas versiones y plataformas de OpenZFS, sí—existen características de L2ARC persistente. Pero debes verificar el comportamiento en tu stack exacto. No asumas “persiste” hasta que hayas probado un reinicio y confirmado el comportamiento de caché caliente.
7) ¿Cuál es la diferencia entre L2ARC y un vdev especial?
L2ARC es una capa de caché para lecturas. Un vdev especial forma parte del pool y puede almacenar metadatos (y opcionalmente bloques pequeños) permanentemente en medios más rápidos. Los vdevs especiales pueden cambiar el juego para cargas pesadas en metadatos, pero no son desechables: si los pierdes sin redundancia, puedes perder el pool.
8) ¿Puedo usar L2ARC en un sistema con RAM limitada?
Puedes, pero probablemente no deberías salvo que el L2ARC sea pequeño y esté cuidadosamente validado. El camino más rápido al arrepentimiento es “añadir un L2ARC grande” en un host ya cerca de los límites de memoria.
9) ¿Debería deshabilitar L2ARC para backups?
A menudo sí. Los backups suelen hacer lecturas secuenciales grandes con poca reutilización. Establecer secondarycache=none para datasets de backup es una forma común de evitar la contaminación de la caché.
10) ¿Qué métricas importan más para juzgar L2ARC?
La latencia cola de la aplicación (p95/p99), deltas de aciertos ARC/L2ARC durante la carga, latencia/IOPS de lectura del pool, utilización/latencia del dispositivo de caché y indicadores de presión de memoria (swap, comportamiento de reclaim).
Conclusión
L2ARC es una herramienta potente con una tarea muy específica: rescatar cargas intensivas en lectura cuyo conjunto de trabajo no cabe en RAM, sin pagar el pleno peaje del almacenamiento primario lento. Cuando encaja con la carga, puede suavizar la latencia de cola y reducir el thrash de disco de formas que los usuarios notan inmediatamente.
Pero L2ARC no es “velocidad SSD gratis”. Es una caché que cuesta RAM, CPU y atención operacional. Trátala como infraestructura de producción: mide primero, añádela deliberadamente, protégela de la contaminación por escaneos y estate listo para quitarla como experimento controlado. Si haces eso, L2ARC se comportará como un aliado. Si no, se comportará como cualquier otra “optimización rápida” que hayas conocido: útil hasta el momento en que se convierte en incidente.