ZFS sync: la opción que puede hacerte rápido… y inseguro

¿Te fue útil?

ZFS tiene un pequeño regulador llamado sync que parece inocuo hasta que te arruina la semana —o te la salva. Si lo giras en una dirección, tu gráfico de latencia se calma, tus benchmarks se ven heroicos y tu host de VM de repente “se siente rápido”. Si lo giras en la otra, obtienes el tipo de garantías que a los auditores les encanta y con las que los operadores duermen tranquilos. La trampa es que ambos resultados pueden ser verdaderos al mismo tiempo, dependiendo de lo que entiendas por “escrito en disco”.

Esto no es una lección moral sobre “nunca deshabilitar la seguridad”. Es una guía de campo para quienes gestionan producción: qué hace realmente sync, por qué puede estrangular un sistema, cómo ayudan los dispositivos SLOG (y cómo no), y cómo elegir ajustes que coincidan con las promesas de tu carga de trabajo. El objetivo es simple: ser rápido sin convertir accidentalmente tu almacenamiento en una sugerencia educada.

Qué significa realmente “sync” en ZFS (y qué no)

En ZFS, la propiedad de dataset sync controla cómo ZFS trata las solicitudes de escritura síncronas. Esa redacción importa. ZFS no decide ser síncrono al azar; es el llamador quien lo solicita.

Una escritura síncrona es aquella en la que la aplicación (o el protocolo) dice: “No informes éxito hasta que estos datos estén en almacenamiento estable.” Almacenamiento estable es aquel que sobrevivirá a un fallo y pérdida de energía súbita. No “está en RAM”, no “el controlador dice que está en caché”, no “la caché de páginas de Linux se siente optimista hoy”. Estable.

ZFS implementa esta garantía comprometiendo la intención de escritura en el ZIL (ZFS Intent Log). Si tienes un dispositivo de log separado (un SLOG), ZFS puede colocar esos datos del ZIL en un dispositivo de baja latencia para acelerar las escrituras síncronas. Más tarde, ZFS incorpora esos cambios en la pool principal como parte de los commits normales de grupo de transacciones (TXG).

Dos implicaciones inmediatas:

  • sync no hace que tu sistema sea “seguro” por sí mismo. Define lo que ZFS hará cuando el llamador solicite semántica síncrona. Si el llamador nunca lo pide (o está mal configurado), aún puedes perder datos en una pérdida de energía.
  • sync puede absolutamente hacerte más rápido. Pero la aceleración a menudo proviene de eliminar garantías de durabilidad. Por eso este ajuste es famoso: es uno de los pocos interruptores donde rendimiento y seguridad están directamente acoplados.

Aquí va el primer chiste, porque lo necesitaremos más adelante: Desactivar sync es como quitar el detector de humo porque pita cuando quemas tostadas —pacífico hasta que deja de serlo.

Datos interesantes y contexto histórico

Un poco de contexto hace que el comportamiento parezca menos magia y más ingeniería:

  1. ZFS nació en Sun Microsystems a principios de los 2000, diseñado para integridad de extremo a extremo y flujos de trabajo administrativos sensatos a escala —cuando “usar RAID y esperar” todavía era un plan popular.
  2. El ZIL no es una caché de escritura para todo. Existe específicamente para satisfacer la semántica síncrona; la mayoría de las escrituras asíncronas nunca lo tocan.
  3. Un SLOG no es “una caché SSD”. Es un dispositivo dedicado para almacenar rápidamente el ZIL. No acelera lecturas y no acelera automáticamente todas las escrituras.
  4. Muchos arrays de almacenamiento empresariales vendían “caché de escritura respaldada por NVRAM”. Como ingrediente mágico que aceleraba escrituras síncronas. En el mundo ZFS, un SLOG protegido contra pérdida de energía cumple un papel similar, pero solo para el ZIL.
  5. NFS tiene reputación de “lentitud misteriosa”. En gran parte porque tiende a solicitar semánticas síncronas para muchas operaciones. Si el almacenamiento no puede comprometer sync rápidamente, el protocolo de red parece culpable.
  6. Las bases de datos suelen usar fsync() como su línea en la arena. PostgreSQL, MySQL/InnoDB y otras dependen de llamadas explícitas de flush para mantener la durabilidad de transacciones.
  7. Las pilas de virtualización amplifican el dolor. Una VM que hace escrituras síncronas se convierte en un host haciendo escrituras síncronas, multiplicado por cada invitado. Un inquilino ruidoso y sensible a la durabilidad puede dominar la latencia.
  8. Los errores de “orden de escritura” solían ser comunes en sistemas de ficheros y controladoras. El diseño de ZFS (copy-on-write + checksums) no elimina la necesidad de sync, pero hace que la corrupción sea más fácil de detectar y más difícil de crear de forma silenciosa.

Los tres modos: standard, always, disabled

La propiedad sync es por dataset (sistema de ficheros o zvol). Tiene tres valores relevantes:

1) sync=standard (el valor por defecto)

Esto significa: respetar la petición del llamador. Si la aplicación emite escrituras síncronas o llama a fsync()/fdatasync(), ZFS compromete la intención en el ZIL y solo entonces informa éxito.

Operativamente: este es el modo de “hacer lo que la app pidió”. Si el rendimiento es malo aquí, es una señal real: tu carga de trabajo está pidiendo durabilidad y tu ruta de almacenamiento no puede entregarla rápidamente.

2) sync=always

Esto fuerza que todas las escrituras sean tratadas como síncronas, incluso si el llamador no lo pidió.

Cuándo usarlo: cuando no confías en la carga de trabajo o el middleware para solicitar semántica sync correctamente, pero aún necesitas comportamiento durable. A veces se usa en exportaciones NFS para cargas que son notoriamente mentirosas sobre sus necesidades de durabilidad, o en ciertas imágenes de VM donde quieres garantizar la seguridad “a nivel de host” independientemente de la configuración del invitado.

Compensación: si no tienes un SLOG rápido y seguro, puedes convertir una pool decente en un museo de latencias.

3) sync=disabled

Esto indica a ZFS que trate las solicitudes síncronas como asíncronas. Aceptará escrituras sync antes de que realmente estén en almacenamiento estable.

Cuándo usarlo: para datos que puedes permitirte perder en un fallo (espacio temporal, cachés, intermediarios analíticos transitorios), o en arquitecturas muy específicas donde la durabilidad se gestiona en otro lugar (por ejemplo, la app tiene su propio log de commits replicado y aceptas explícitamente la pérdida local).

Riesgo: cualquier aplicación que crea que obtuvo un commit durable puede estar equivocada. Eso incluye bases de datos. Incluye sistemas de ficheros de VM. Incluye clientes NFS que realizan escrituras seguras.

Segundo chiste, y luego volvemos a lo serio: Poner sync=disabled en un volumen de base de datos es como poner “probablemente” en medio de tu libro de contabilidad—los auditores no lo encuentran encantador.

Quién solicita escrituras síncronas: apps, bases de datos, NFS, hipervisores

La mayor parte del drama de rendimiento alrededor de sync proviene de no entender quién solicita la semántica síncrona y por qué.

Bases de datos

Las bases de datos suelen convertir “transacción comprometida” en un fsync() sobre un write-ahead log (WAL) o redo log. El log es algo secuencial, pero el requisito es estricto: cuando la base de datos dice commit, el log debe sobrevivir a un fallo. Si ZFS tarda 5 ms en satisfacer eso, la latencia de commit de la base de datos es al menos 5 ms, incluso si todo lo demás es rápido.

Algunas bases de datos pueden relajar esto (por ejemplo, modos de “async commit”), pero eso es una decisión a nivel de aplicación. El almacenamiento no debería cambiar silenciosamente el significado de “commit” sin que lo sepas.

NFS

Los clientes NFS a menudo solicitan escrituras estables, y los servidores deben respetarlas. En servidores NFS respaldados por ZFS, esto significa que la ruta ZIL/SLOG se convierte en el camino caliente. Puedes tener una pool rapidísima para throughput asíncrono y aún así padecer una latencia terrible en NFS si los commits síncronos son lentos.

Virtualización (zvols, imágenes de VM)

Los hipervisores y los sistemas de ficheros invitados pueden generar una cantidad sorprendente de operaciones síncronas —actualizaciones de metadatos, commits de journal, barreras, flushes. Un único ajuste “seguro” en un invitado puede traducirse en flushes constantes en el host, y esos flushes se mapean directamente a la ruta ZIL.

Por eso verás la queja clásica: “Mi pool SSD es rápida pero mi host de VM se siente lento”. A menudo la pool está bien en escrituras masivas, pero la latencia de escritura síncrona es pobre.

La ruta de escritura síncrona en ZFS: TXGs, ZIL, SLOG y qué llega realmente al almacenamiento estable

ZFS escribe datos en grupos de transacciones (TXGs). Los cambios se acumulan en memoria y periódicamente se comprometen a disco en lotes. Ese batching es la razón por la que ZFS puede ser eficiente: convierte muchas escrituras aleatorias pequeñas en IO más ordenado.

Las solicitudes síncronas complican esto. La aplicación no puede esperar al siguiente commit de TXG (que podría tardar segundos). Así que ZFS usa el ZIL: un log de intención que registra suficiente información para reproducir la operación tras un fallo. El ZIL se escribe rápido, luego la escritura síncrona puede ser reconocida. Más tarde, cuando el TXG commit se ejecuta, los datos reales aterrizan en sus estructuras finales en disco y las entradas del ZIL quedan obsoletas.

Verdad operativa clave: el ZIL solo se lee durante la recuperación tras un fallo. En operación normal, se escribe, no se lee. Un dispositivo SLOG no está ahí para mejorar lecturas en estado estable; está ahí para aceptar escrituras pequeñas, sensibles a la latencia, rápida y seguramente.

Otra verdad: si no tienes un SLOG separado, los bloques del ZIL viven en la pool principal. Eso puede estar bien en pools muy rápidas y de baja latencia —especialmente all-flash con protección contra pérdida de energía. En pools más lentas (discos giratorios, o SSDs con mala latencia bajo escrituras síncronas), puede ser brutal.

Realidades del SLOG: lo que acelera y lo que no puede

La gente compra un SLOG por la misma razón por la que compra mejor café: quiere que las mañanas duelan menos. Pero un SLOG no es un dispositivo milagroso. Acelera una cosa: la latencia de los reconocimientos de escrituras síncronas.

Lo que ayuda un SLOG

  • Cargas NFS intensivas en sync que están limitadas por la latencia de commit.
  • Bases de datos que están acotadas por la latencia de commit (y donde la BD insiste en commits durables).
  • Clusters de VM donde los flushes son frecuentes y bloqueantes.

Lo que no ayuda un SLOG

  • Latencia de lectura o IOPS de lectura (eso es territorio de ARC/L2ARC, y aun eso tiene matices).
  • Throughput de escrituras asíncronas masivas (eso recae principalmente en los vdevs principales y el comportamiento de TXG).
  • Cargas que emiten pocas escrituras síncronas; no lo notarás.

Qué hace a un buen SLOG

Dos propiedades: baja latencia bajo escrituras síncronas y protección contra pérdida de energía. Quieres que el dispositivo reconozca escrituras solo cuando los datos estén realmente seguros. Los SSDs de consumo pueden ser rápidos pero mentir sobre la durabilidad de flushes. Los SSDs empresariales (o dispositivos diseñados para logging de escritura) suelen rendir mejor aquí porque tienen capacitores y firmware diseñados para esta tarea.

El tamaño no es lo principal. El SLOG solo necesita almacenar una pequeña ventana de transacciones síncronas pendientes —típicamente segundos, no todo el dataset. Latencia, no capacidad, es lo que estás comprando.

Replica del SLOG

Si un dispositivo SLOG falla, la pool puede continuar (ZFS puede retroceder), pero corres el riesgo de perder las últimas transacciones síncronas reconocidas si el dispositivo de log muere de forma inapropiada. En la práctica, muchos equipos espejan el SLOG por una paranoia que en realidad está justificada —especialmente en almacenamiento compartido para VMs o bases de datos.

Tres mini-historias del mundo corporativo (relatos de guerra realistas)

Mini-historia #1: Un incidente causado por una suposición incorrecta

El equipo de almacenamiento heredó un cluster NFS respaldado por ZFS que alimentaba una granja de compilaciones y un puñado de servicios internos “pequeños”. Apareció un servicio nuevo: un sistema de colas con estado que escribía mensajes diminutos constantemente y dependía de commits síncronos para su corrección. Todos asumieron que sería “como las otras apps”, porque vivía en el mismo clúster de Kubernetes y usaba la misma clase NFS.

No lo era. El servicio de colas forzaba escrituras estables, y la latencia pasó de “bien” a “¿qué está pasando?” de la noche a la mañana. Los jobs de build empezaron a agotar tiempos en lugares que no tenían sentido. El equipo de red fue llamado porque los gráficos de latencia de NFS parecían pérdida de paquetes. El SRE de guardia reinició demonios, luego nodos, luego cuestionó la realidad.

Tras unas horas de whack-a-mole, alguien ejecutó zpool iostat -v 1 y notó un dispositivo pequeño (el único SLOG) atascado en altas operaciones de escritura con latencia fea, mientras la pool principal tenía margen. El SLOG era un viejo SSD SATA de consumo —rápido en benchmarks, terrible en escrituras síncronas sostenidas y probablemente no respetando las semánticas de flush de forma fiable. Se había convertido en el cuello de botella y la fuente de la latencia de cola.

La solución fue mundana: reemplazar el SLOG por un dispositivo adecuado de baja latencia y protegido contra pérdida de energía y espejarlo. El rendimiento se estabilizó inmediatamente. El postmortem no fue sobre culpas; fue sobre suposiciones. El entorno cambió de “artefactos de build mayoritariamente asíncronos” a “carga de trabajo que exige sync”, y los ajustes de almacenamiento no evolucionaron con ello.

Mini-historia #2: Una optimización que salió mal

Un equipo de plataforma de virtualización tenía una pool ZFS alojando discos de VM (zvols). Un clúster nuevo entró en producción y, bajo carga, rindió peor que el antiguo —aunque el hardware era más nuevo. Alguien encontró un post que sugería sync=disabled para “ganancias de rendimiento masivas” en almacenamiento de VM. Lo probaron en un host de staging con IO sintético y obtuvieron números preciosos.

Así que lo desplegaron gradualmente. La ganancia de rendimiento fue real: la latencia de commit se desplomó, el IO wait bajó, los inquilinos dejaron de quejarse. Se sentía como trabajo heroico —hasta el primer evento real de corte de energía. No fue un apagón catastrófico, solo un corte en un rack durante mantenimiento. Los hosts se reiniciaron, el almacenamiento se importó correctamente y la mayoría de las VMs arrancaron bien.

Pero algunas no. Los sistemas de ficheros quedaron corruptos de maneras que el journaling no arregló. Una VM de base de datos arrancó pero le faltaban los últimos minutos de transacciones comprometidas —transacciones que la app había reconocido hacia servicios upstream. La opción “rápida” había cambiado silenciosamente el significado de “commit” dentro de esos invitados. Eso provocó corrupción lógica: no bloques rotos, sino verdad de negocio rota.

El rollback fue sencillo. La limpieza no lo fue. Tuvieron que reconciliar pedidos perdidos y reprocesar eventos desde logs upstream. En el informe final, la lección no fue “nunca afines ZFS”. Fue: si deshabilitas sync en almacenamiento de VM, estás haciendo una promesa de durabilidad en nombre de cada invitado, y más vale que tu arquitectura la tolere. Si no, tu benchmark es solo un truco de confianza.

Mini-historia #3: Una práctica aburrida pero correcta que salvó el día

Un equipo de servicios financieros operaba un par de servidores ZFS exportando NFS a un clúster de aplicaciones. Tenían una costumbre que parecía tediosa: antes de cada pico trimestral de tráfico, ejecutaban un “simulacro de durabilidad”. Era simple: verificar propiedades sync de datasets, comprobar la salud del SLOG, verificar que los flushes se comportaban como se esperaba y ejecutar una simulación controlada de pérdida de energía en un laboratorio con la misma clase de hardware.

Los ingenieros se quejaban de que era culto al cargo. Nada fallaba nunca en el simulacro. Ese era el punto. Era el equivalente en almacenamiento a revisar el paracaídas estando todavía en tierra.

Entonces tuvieron un incidente real: un bug de firmware hizo que uno de los dispositivos de log empezara a reportar salud mientras silenciosamente timoutaba bajo ciertos depths de cola. ZFS no lo marcó inmediatamente como faulty, pero la latencia se disparó cuando la carga entró en una fase intensa en sync. Porque el equipo tenía números base de latencia de simulacros anteriores, detectaron la desviación rápido y no perdieron una noche culpando a NFS, la red o la aplicación.

Reemplazaron el par de SLOG durante una ventana de mantenimiento y el clúster volvió a la normalidad. Sin pérdida de datos, sin misterio. Ingeniería aburrida, que es lo que quieres cuando hay dinero en juego.

Tareas prácticas: comandos, qué observar y cómo interpretarlos

Los comandos abajo asumen un entorno OpenZFS típico en Linux. Ajusta nombres de pool/dataset para que coincidan con tu sistema. Cada tarea incluye qué significa la salida en la práctica.

Task 1: Encuentra los ajustes sync de tus datasets (y la herencia)

cr0x@server:~$ zfs get -r -o name,property,value,source sync tank
NAME               PROPERTY  VALUE     SOURCE
tank               sync      standard  default
tank/vm            sync      disabled  local
tank/vm/critical   sync      standard  inherited from tank
tank/nfs           sync      standard  local

Interpretación: No mires solo la raíz del pool. Un único dataset “útil” con sync=disabled puede esconderse en tu jerarquía de almacenamiento para VMs. La columna source es tu detector de verdad: local vs inherited vs default.

Task 2: Comprueba si tienes un SLOG (y qué es)

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:18:42 with 0 errors on Mon Dec 16 03:10:05 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            nvme0n1                 ONLINE       0     0     0
            nvme1n1                 ONLINE       0     0     0
        logs
          mirror-1                  ONLINE       0     0     0
            nvme2n1                 ONLINE       0     0     0
            nvme3n1                 ONLINE       0     0     0

errors: No known data errors

Interpretación: La sección logs es tu SLOG. Si falta, tu ZIL vive en los vdevs principales. Si es un solo dispositivo (no espejado), decide si toleras ese perfil de riesgo.

Task 3: Observa la latencia por vdev bajo carga

cr0x@server:~$ zpool iostat -v tank 1
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        1.20T  2.40T    110    980  8.5M  72.1M
  mirror-0                  1.20T  2.40T    110    220  8.5M  15.4M
    nvme0n1                     -      -     60    120  4.2M   7.8M
    nvme1n1                     -      -     50    100  4.3M   7.6M
logs                             -      -      -      -
  mirror-1                       -      -      0    760  0K   56.7M
    nvme2n1                      -      -      0    380  0K   28.4M
    nvme3n1                      -      -      0    380  0K   28.3M
--------------------------  -----  -----  -----  -----  -----  -----

Interpretación: Si los dispositivos de log llevan la mayor parte de las operaciones de escritura mientras los vdevs principales están calmados, tu carga es intensiva en sync. Si el rendimiento es malo, el SLOG es el primer sospechoso.

Task 4: Confirma que ZFS ve el ashift correcto (alineación del tamaño de sector)

cr0x@server:~$ zdb -C tank | grep -E "ashift|vdev_tree" -n | head
52:        vdev_tree:
83:            ashift: 12
121:            ashift: 12

Interpretación: ashift=12 significa sectores de 4K. Una desalineación (ashift demasiado pequeño) puede crear amplificación de escritura y latencia fea, incluyendo para tráfico sync.

Task 5: Comprueba la salud del pool ZFS y contadores de errores

cr0x@server:~$ zpool status tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:18:42 with 0 errors on Mon Dec 16 03:10:05 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            nvme0n1 ONLINE       0     0     0
            nvme1n1 ONLINE       0     0     0

errors: No known data errors

Interpretación: Depurar rendimiento sync en un pool con errores latentes es como ajustar un motor con una bomba de aceite rota. Arregla la integridad primero.

Task 6: Identificar llamadores intensivos en sync observando actividad de fsync (Linux)

cr0x@server:~$ sudo perf trace -e fsync,fdatasync,openat -a --duration 10
     0.000 ( 0.008 ms): postgres/1931 fdatasync(fd: 7) = 0
     0.012 ( 0.006 ms): postgres/1931 fdatasync(fd: 7) = 0
     0.030 ( 0.010 ms): qemu-kvm/2210 fsync(fd: 31) = 0
     0.044 ( 0.009 ms): qemu-kvm/2210 fsync(fd: 31) = 0

Interpretación: Buscas frecuencia. Si ves miles de llamadas sync por segundo, tu presupuesto de latencia se está gastando en durabilidad.

Task 7: Medir la latencia de escrituras sync con fio (directo, parecido a sync)

cr0x@server:~$ fio --name=syncwrite --filename=/tank/test/syncwrite.bin \
  --rw=write --bs=4k --iodepth=1 --numjobs=1 --direct=1 \
  --fsync=1 --size=1G --runtime=30 --time_based=1
syncwrite: (g=0): rw=write, bs=4K-4K, ioengine=psync, iodepth=1
...
  write: IOPS=6200, BW=24.2MiB/s (25.4MB/s)(726MiB/30001msec)
    clat (usec): min=90, max=9200, avg=160.4, stdev=210.7

Interpretación: --fsync=1 fuerza un flush en cada escritura, aproximando el peor comportamiento de commit. La latencia media es agradable; el max y la cola son lo que sienten tus usuarios.

Task 8: Comparar comportamiento con sync=disabled en un dataset desechable

cr0x@server:~$ sudo zfs create tank/test_nodur
cr0x@server:~$ sudo zfs set sync=disabled tank/test_nodur
cr0x@server:~$ fio --name=syncwrite --filename=/tank/test_nodur/syncwrite.bin \
  --rw=write --bs=4k --iodepth=1 --numjobs=1 --direct=1 \
  --fsync=1 --size=1G --runtime=15 --time_based=1
...
  write: IOPS=42000, BW=164MiB/s (172MB/s)(2462MiB/15001msec)
    clat (usec): min=18, max=480, avg=22.7, stdev=7.1

Interpretación: Este delta demuestra exactamente lo que estás sacrificando: reconocimiento durable. Trata este resultado como herramienta diagnóstica, no como “solución”. Si la única forma de ser rápido es mentir, la solución real es mejorar la ruta sync (frecuentemente SLOG).

Task 9: Inspeccionar si los datasets usan zvols (común en almacenamiento VM)

cr0x@server:~$ zfs list -t volume -o name,volsize,volblocksize,sync,logbias
NAME           VOLSIZE  VOLBLOCKSIZE  SYNC      LOGBIAS
tank/vm-001      120G         16K     standard  latency
tank/vm-002      200G         16K     disabled  latency

Interpretación: Los zvols a menudo soportan patrones IO de VM. Observa cualquier sync=disabled sorprendente. También fíjate en volblocksize —influye en la amplificación de IO y latencia.

Task 10: Comprobar logbias (preferencia latencia vs throughput)

cr0x@server:~$ zfs get -r logbias tank/vm
NAME      PROPERTY  VALUE    SOURCE
tank/vm   logbias   latency  default

Interpretación: logbias=latency fomenta el uso del dispositivo de log para escrituras sync. throughput puede reducir el uso del log en algunos casos. Esto no sustituye un sync correcto, pero puede influir en el comportamiento para ciertas cargas.

Task 11: Confirmar compresión y recordsize (pueden cambiar la historia sync indirectamente)

cr0x@server:~$ zfs get compression,recordsize tank/nfs
NAME      PROPERTY     VALUE     SOURCE
tank/nfs  compression  lz4       local
tank/nfs  recordsize   128K      default

Interpretación: La compresión puede reducir IO físico (a menudo bueno), pero aumenta trabajo CPU. Si tu problema de “sync lento” es realmente saturación CPU durante commits TXG, perseguir otra cosa te hará perder tiempo a menos que midas.

Task 12: Comprobar presión CPU en tiempo real y IO wait durante tormentas sync

cr0x@server:~$ vmstat 1 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 712344  89244 3821000   0    0     8   420  980 1900 12  6 78  4  0
 5  3      0 701112  89244 3818200   0    0     0  8200 1200 2400 10  7 55 28  0
 3  2      0 700980  89244 3818500   0    0     0  7900 1180 2300 11  7 56 26  0

Interpretación: Un aumento de wa (IO wait) durante periodos intensos en sync sugiere que la ruta de almacenamiento está bloqueando al CPU. Si wa es bajo pero la latencia es alta, podrías estar enfrentando colas, comportamiento de flush de dispositivos o un dispositivo de log saturado.

Task 13: Detectar sistemas de ficheros en red que fuerzan semántica sync (ángulo servidor NFS)

cr0x@server:~$ sudo nfsstat -s
Server rpc stats:
calls      badcalls   badfmt     badauth    badclnt
18233990   0          0          0          0

Server nfs v4:
null         compound
0            11239821

Server nfs v3:
null        getattr     setattr     lookup      access
0           226001      8402        110240      90412
commit      write       create      mkdir       remove
340882      901220      4800        220         1900

Interpretación: Alta actividad NFS commit es una pista: los clientes exigen semánticas de almacenamiento estable. Si los commits son frecuentes y lentos, tu ruta ZIL/SLOG importa más que tu throughput masivo.

Task 14: Verificar que los dispositivos de log realmente están haciendo trabajo (o no)

cr0x@server:~$ iostat -x 1 5 | egrep 'nvme2n1|nvme3n1|nvme0n1'
nvme2n1  0.00  740.00  0.00  56000.00  0.00  74.20  0.02  0.35  3.10  0.20  74.9
nvme3n1  0.00  735.00  0.00  55800.00  0.00  73.80  0.02  0.34  3.00  0.19  75.1
nvme0n1 55.00  120.00  8200.00  15400.00  3.40  15.30  0.10  0.80  2.10  0.40  25.0

Interpretación: Si los dispositivos de log muestran altas tasas de escritura y alta utilización, están en el camino caliente. Si muestran actividad casi nula bajo una carga intensiva en sync, o bien la carga no es realmente sync, o el dataset no está en standard/always, o el sistema está configurado diferente a lo que crees.

Guía rápida de diagnóstico (qué comprobar primero, segundo, tercero)

Cuando “ZFS está lento” hace sonar tu pager, no tienes tiempo para filosofía. Necesitas una secuencia de triage que encuentre el cuello de botella rápido.

Primero: Determina si el dolor está relacionado con sync

  1. Comprueba las propiedades sync de los datasets en la ruta caliente (zfs get -r sync en los datasets/zvols relevantes).
  2. Observa zpool iostat -v 1 y busca dominancia de escritura en dispositivos de log (o vdevs principales luchando con escrituras pequeñas).
  3. En Linux, muestrea la frecuencia de fsync/fdatasync con perf trace (o logs/ métricas a nivel de aplicación).

Decisión: Si ves llamadas sync frecuentes y alta actividad/latencia en el log, es un cuello de botella en la ruta sync. Si no, no pierdas tiempo culpando a sync.

Segundo: Localiza el punto de estrangulamiento (SLOG vs vdevs principales vs CPU)

  1. Si hay un SLOG: inspecciona su clase de dispositivo, salud y utilización. Usa iostat -x y zpool iostat -v para ver si está saturado.
  2. Si no hay SLOG: comprueba la latencia de los vdevs principales bajo carga intensiva en sync. Discos giratorios haciendo escrituras sync pueden parecer “congelaciones aleatorias” para aplicaciones.
  3. Comprueba saturación CPU y IO wait (vmstat, top). Un sistema ocupado puede hacer que los commits sync parezcan almacenamiento cuando en realidad es planificación y contención.

Tercero: Valida las expectativas de durabilidad antes de “arreglar” rendimiento

  1. Identifica la clase de carga: base de datos, discos VM, directorios home NFS, cache de builds, scratch, datos efímeros replicados.
  2. Pregunta: ¿cuál es la ventana aceptable de pérdida de datos ante una pérdida de energía súbita? “Ninguna” es una respuesta válida.
  3. Solo entonces considera cambios como añadir un SLOG, espejarlo, ajustar datasets o (poco frecuente) deshabilitar sync para datos realmente desechables.

Errores comunes (con síntomas específicos y soluciones)

Error 1: Deshabilitar sync en almacenamiento de VM o base de datos “porque es lento”

Síntomas: Los benchmarks y latencias mejoran dramáticamente; después, tras un fallo o evento de energía, ves corrupción de sistemas de ficheros, transacciones BD comprometidas faltantes o estado de aplicación inconsistente.

Solución: Restaurar sync=standard (o always si procede). Invierte en un SLOG apropiado y/o reduce la presión de sync en la capa de aplicación mediante ajustes soportados (con aceptación explícita del riesgo).

Error 2: Comprar un SLOG rápido pero no seguro contra pérdida de energía

Síntomas: Gran rendimiento; luego, problemas inexplicables de integridad tras pérdida de energía abrupta; o descubres que el dispositivo ignora flushes.

Solución: Usa dispositivos con protección contra pérdida de energía diseñados para escrituras sostenidas de baja latencia. Espeja el SLOG cuando la integridad de la carga importe.

Error 3: Esperar que el SLOG acelere todo

Síntomas: Añades un SLOG y no ves mejora; o solo una mejora pequeña; los usuarios aún se quejan de latencias de lectura.

Solución: Confirma que la carga emite escrituras sync. Si es de lectura, enfócate en dimensionar ARC, número de vdevs, recordsize y el rendimiento del dispositivo subyacente —no en SLOG.

Error 4: Afinar sin medir la latencia cola

Síntomas: La latencia media parece bien; los usuarios se quejan de bloqueos; pausas de VM; picos en commits de BD.

Solución: Mide y grafica percentiles (p95/p99). Los cuellos de botella sync suelen aparecer como latencia de cola por colas y tormentas de flush.

Error 5: Mezclar datos “críticos” y “desechables” bajo la misma política de dataset

Síntomas: Alguien pone sync=disabled para un directorio de caché y lo aplica accidentalmente a un dataset padre usado por datos reales; o la herencia cambia tras refactorizaciones.

Solución: Usa datasets separados con propiedades explícitas. Verifica con zfs get -r -o name,property,value,source e incorpora comprobaciones en el provisioning.

Error 6: Ignorar que NFS puede forzar comportamiento sync

Síntomas: Clientes NFS muestran alta latencia; CPU/red del servidor parecen bien; el throughput de almacenamiento no está al máximo; sin embargo las operaciones bloquean.

Solución: Inspecciona patrones commit/write de NFS y asegúrate de que la ruta sync del servidor sea rápida y segura (SLOG + dispositivos apropiados). No “arregles” deshabilitando sync salvo que los datos sean realmente descartables.

Listas de verificación / plan paso a paso

Checklist A: Decidir el modo sync correcto por dataset

  1. Clasifica los datos: estado crítico, datos de usuario, base de datos, imágenes de VM, cache, scratch, efímeros replicados.
  2. Define la pérdida aceptable ante un fallo: ninguna, segundos, minutos, “no importa”. Escríbelo.
  3. Configura sync=standard para la mayoría de los datos reales.
  4. Considera sync=always solo cuando necesites imponer durabilidad independientemente del comportamiento del llamador.
  5. Usa sync=disabled solo para datasets explícitamente desechables (y mantenlos aislados).

Checklist B: Añadir un SLOG de forma segura (cuando esté justificado)

  1. Demuestra que estás limitado por sync: mide la tasa de fsync y la utilización ZIL/SLOG.
  2. Elige dispositivos con protección contra pérdida de energía y latencia predecible bajo escrituras sostenidas.
  3. Espeja el SLOG para cargas importantes.
  4. Añádelo y valida con pruebas de carga reales, no solo throughput sintético.

Paso a paso: Implementar un dataset dedicado “sync seguro y rápido”

Este es un patrón común para exportaciones NFS o volúmenes de base de datos donde quieres durabilidad con rendimiento razonable.

cr0x@server:~$ sudo zfs create tank/prod_safe
cr0x@server:~$ sudo zfs set sync=standard tank/prod_safe
cr0x@server:~$ sudo zfs set logbias=latency tank/prod_safe
cr0x@server:~$ sudo zfs set atime=off tank/prod_safe
cr0x@server:~$ sudo zfs set compression=lz4 tank/prod_safe
cr0x@server:~$ zfs get -o name,property,value,source sync,logbias,atime,compression tank/prod_safe
NAME            PROPERTY     VALUE     SOURCE
tank/prod_safe  sync         standard  local
tank/prod_safe  logbias      latency   local
tank/prod_safe  atime        off       local
tank/prod_safe  compression  lz4       local

Interpretación: Esto no “garantiza rapidez”, pero alinea el comportamiento de ZFS con una estrategia de sync de baja latencia manteniendo la durabilidad.

Paso a paso: Crear un dataset explícitamente desechable (y etiquétalo como radiactivo)

cr0x@server:~$ sudo zfs create tank/scratch_ephemeral
cr0x@server:~$ sudo zfs set sync=disabled tank/scratch_ephemeral
cr0x@server:~$ sudo zfs set compression=off tank/scratch_ephemeral
cr0x@server:~$ sudo zfs set atime=off tank/scratch_ephemeral
cr0x@server:~$ zfs get -o name,property,value,source sync,compression tank/scratch_ephemeral
NAME                  PROPERTY     VALUE     SOURCE
tank/scratch_ephemeral sync         disabled  local
tank/scratch_ephemeral compression  off       local

Interpretación: Haz obvio el radio de acción. Manténlo fuera de rutas de herencia usadas por datos reales.

Preguntas frecuentes

1) ¿Significa sync=disabled “puedo perder los últimos segundos”?

Puede ser peor. Puedes perder datos que la aplicación creía comprometidos de forma segura. Eso puede causar corrupción lógica: una base de datos o servicio puede reconocer una transacción y luego olvidarla tras un fallo. “Unos segundos” no es una cota fiable a menos que toda la pila esté diseñada con ese modo de fallo en mente.

2) Si tengo un SAI/UPS, ¿puedo desactivar sync de forma segura?

Un UPS reduce el riesgo pero no lo elimina. Ocurren kernel panics, resets de controladora, bugs de firmware, cortes accidentales y fallos de doble alimentación. Además, un UPS no ayuda si un dispositivo miente sobre la finalización de flushes. Si necesitas garantías de durabilidad, trata el UPS como defensa en profundidad, no como sustituto.

3) ¿Necesito un SLOG en una pool all-NVMe?

No siempre. Algunas pools NVMe tienen latencia suficientemente baja para que el ZIL en-pool sea aceptable. El factor decisivo es la latencia de escrituras sync bajo tu carga y el comportamiento de flush de los dispositivos. Mide antes de comprar hardware.

4) ¿Debe ser grande el SLOG?

Normalmente no. El SLOG sostiene un log a corto plazo de operaciones sync hasta que los TXGs commiten. La consistencia de latencia y la seguridad ante pérdida de energía importan mucho más que la capacidad. Sobredimensionarlo es común y en su mayoría inofensivo, pero rara vez es el cuello de botella o la ventaja.

5) ¿Cuál es la diferencia entre ZIL y SLOG otra vez?

El ZIL es un mecanismo: el intent log usado para satisfacer semánticas sync. El SLOG es un dispositivo: un lugar dedicado para almacenar registros ZIL, idealmente más rápido y más seguro que la pool principal para ese patrón de escritura específico.

6) ¿Por qué NFS es lento en mi servidor ZFS aunque las escrituras locales son rápidas?

Los clientes NFS suelen solicitar escrituras estables. Las pruebas locales a menudo usan IO bufferizado/asíncrono que no fuerza flushes. Si tu ruta ZIL/SLOG es lenta, la latencia NFS se verá terrible mientras el throughput masivo parece estar bien.

7) ¿Es sync=always más seguro que sync=standard?

Puede ser, en el sentido de que fuerza durabilidad incluso si la aplicación no la solicita. Pero también puede causar penalizaciones de rendimiento grandes. Úsalo cuando tengas una razón específica para desconfiar de los llamadores —y cuando tu ruta sync (SLOG o pool principal) pueda asumirlo.

8) ¿Puedo “arreglar” la latencia sync cambiando recordsize o la compresión?

A veces de forma indirecta. La latencia sync suele estar relacionada con comportamiento de flush/commit y latencia de dispositivos. Pero si los commits TXG están causando retropresión, la CPU y la amplificación de escritura pueden importar. No adivines: mide latencia de llamadas sync, latencia de dispositivo y comportamiento TXG juntos.

9) Si espejo mi SLOG, ¿eso duplica la latencia?

Puede incrementarla algo, porque las escrituras deben ser comprometidas en ambos dispositivos. Pero con dispositivos de baja latencia adecuados, un SLOG espejado suele ser todavía drásticamente más rápido que loguear en vdevs principales más lentos —y mejora la resiliencia frente a fallo del dispositivo de log.

10) ¿Cuál es la regla práctica más amigable para operadores?

Si la carga abriría un bug al perder una escritura “comprometida”, no uses sync=disabled. En su lugar, haz que sync sea rápido de la forma honesta: buenos dispositivos, buen SLOG (si hace falta) y diseño de datasets consciente de la carga de trabajo.

Conclusión

El sync de ZFS es una de esas opciones que parece un truco porque puede serlo. También puede ser una trampa. La propiedad no trata de “hacer ZFS más rápido”. Trata de si ZFS respetará el contrato de durabilidad del llamador —o lo reescribirá en silencio.

La mentalidad de producción es tratar sync como una decisión de política, no como un truco de afinado. Empieza identificando quién está pidiendo semánticas síncronas y por qué. Mide la ruta ZIL/SLOG, no solo el throughput masivo. Si necesitas rendimiento y veracidad en el reconocimiento, invierte en una ruta de escrituras sync adecuada y mantén los ajustes alineados con la promesa de negocio que realizan tus sistemas.

← Anterior
DNS local para usuarios VPN: Evitar filtraciones de DNS y fallos de enrutamiento dividido
Siguiente →
Debian 13: Tu servidor no arranca tras actualizaciones — la reversión limpia de GRUB que realmente funciona

Deja un comentario