Hoy hice algunas pruebas en L2ARC usando el último ZFS en Linux 0.7.10. He visto que L2ARC se llena de datos, pero con la configuración predeterminada del módulo, los datos que residen en la caché L2ARC nunca se tocan. En cambio, los datos se leen de los vdevs del grupo principal. También he visto este comportamiento en 0.7.9 y no estoy seguro de si ese es el comportamiento esperado.
Incluso si ese fuera el comportamiento esperado, creo que es extraño estropear el L2ARC con datos que nunca se leen.
La instalación de prueba es una VM:
- CentOS 7.5 con los últimos parches
- ZFS en Linux 0.7.10
- 2 GB de RAM
Hice algunas configuraciones de ZFS:
l2arc_headroom=1024
yl2arc_headroom=1024
acelerar la población L2ARC
Así es como se creó la piscina y su distribución. Sé que es bastante extraño para una configuración del mundo real, pero esto fue pensado únicamente para pruebas L2ARC.
[root@host ~]# zpool create tank raidz2 /dev/sda /dev/sdb /dev/sdc cache sdd -f
[root@host ~]# zpool list -v
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 2.95G 333K 2.95G - 0% 0% 1.00x ONLINE -
raidz2 2.95G 333K 2.95G - 0% 0%
sda - - - - - -
sdb - - - - - -
sdc - - - - - -
cache - - - - - -
sdd 1010M 512 1009M - 0% 0%
Ahora escriba algunos datos en un archivo y observe el uso del dispositivo.
[root@host ~]# dd if=/dev/urandom of=/tank/testfile bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 9.03607 s, 59.4 MB/s
[root@host ~]# zpool list -v
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 2.95G 1.50G 1.45G - 10% 50% 1.00x ONLINE -
raidz2 2.95G 1.50G 1.45G - 10% 50%
sda - - - - - -
sdb - - - - - -
sdc - - - - - -
cache - - - - - -
sdd 1010M 208M 801M - 0% 20%
Muy bien, algunos de los datos ya se trasladaron al L2ARC, pero no todos. Entonces, léelo más veces para que esté completamente en L2ARC.
[root@host ~]# dd if=/tank/testfile of=/dev/null bs=512 # until L2ARC is populated with the 512MB testfile
[root@host ~]# zpool list -v
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 2.95G 1.50G 1.45G - 11% 50% 1.00x ONLINE -
raidz2 2.95G 1.50G 1.45G - 11% 50%
sda - - - - - -
sdb - - - - - -
sdc - - - - - -
cache - - - - - -
sdd 1010M 512M 498M - 0% 50%
Bien, L2ARC está completo y listo para ser leído. Pero primero es necesario deshacerse de L1ARC. Hice lo siguiente, que pareció funcionar.
[root@host ~]# echo $((64*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; echo $((1024*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; arc_summary.py -p1
------------------------------------------------------------------------
ZFS Subsystem Report Sun Sep 09 17:03:55 2018
ARC Summary: (HEALTHY)
Memory Throttle Count: 0
ARC Misc:
Deleted: 20
Mutex Misses: 0
Evict Skips: 1
ARC Size: 0.17% 1.75 MiB
Target Size: (Adaptive) 100.00% 1.00 GiB
Min Size (Hard Limit): 6.10% 62.48 MiB
Max Size (High Water): 16:1 1.00 GiB
ARC Size Breakdown:
Recently Used Cache Size: 96.06% 1.32 MiB
Frequently Used Cache Size: 3.94% 55.50 KiB
ARC Hash Breakdown:
Elements Max: 48
Elements Current: 100.00% 48
Collisions: 0
Chain Max: 0
Chains: 0
Muy bien, ahora estamos listos para leer desde L2ARC (perdón por el prefacio tan largo, pero pensé que era importante).
Entonces, al ejecutar el dd if=/tank/testfile of=/dev/null bs=512
comando nuevamente, estaba mirando zpool iostat -v 5
en una segunda terminal.
Para mi sorpresa, el archivo se leyó desde los vdev normales en lugar del L2ARC, aunque el archivo se encuentra en L2ARC. Este es el único archivo en el sistema de archivos y no hay ninguna otra actividad activa durante mis pruebas.
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.50G 1.45G 736 55 91.9M 96.0K
raidz2 1.50G 1.45G 736 55 91.9M 96.0K
sda - - 247 18 30.9M 32.0K
sdb - - 238 18 29.8M 32.0K
sdc - - 250 18 31.2M 32.0K
cache - - - - - -
sdd 512M 498M 0 1 85.2K 1.10K
---------- ----- ----- ----- ----- ----- -----
Luego jugueteé con algunas configuraciones como , , zfetch_array_rd_sz
y zfetch_max_distance
, configurándolas en un número impar alto. Pero nada cambió. zfetch_max_streams
l2arc_write_boost
l2arc_write_max
Después de cambiar
l2arc_noprefetch=0
(el valor predeterminado es1
)- o
zfs_prefetch_disable=1
(el valor predeterminado es0
) - alternar ambos desde sus valores predeterminados
las lecturas se sirven desde L2ARC. De nuevo corriendo dd if=/tank/testfile of=/dev/null bs=512
y mirando zpool iostat -v 5
en una segunda terminal y deshaciéndote de L1ARC.
[root@host ~]# echo 0 > /sys/module/zfs/parameters/l2arc_noprefetch
[root@host ~]# echo $((64*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; echo $((1024*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; arc_summary.py -p1
...
[root@host ~]# dd if=/tank/testfile of=/dev/null bs=512
Y el resultado:
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.50G 1.45G 0 57 921 102K
raidz2 1.50G 1.45G 0 57 921 102K
sda - - 0 18 0 34.1K
sdb - - 0 18 0 34.1K
sdc - - 0 19 921 34.1K
cache - - - - - -
sdd 512M 497M 736 0 91.9M 1023
---------- ----- ----- ----- ----- ----- -----
Ahora los datos se leen desde L2ARC, pero solo después de alternar los parámetros del módulo mencionados anteriormente.
También he leído que L2ARC puede tener un tamaño demasiado grande. Pero los hilos que encontré sobre ese tema se referían a problemas de rendimiento o al mapa espacial del L2ARC que estropeaba el L1ARC.
El rendimiento no es mi problema aquí y, hasta donde puedo decir, el mapa espacial del L2ARC tampoco es tan grande.
[root@host ~]# grep hdr /proc/spl/kstat/zfs/arcstats
hdr_size 4 279712
l2_hdr_size 4 319488
Como ya se mencionó, no estoy seguro de si ese es el comportamiento previsto o si me falta algo.
Respuesta1
Entonces, después de leer sobre este tema, principalmenteesta publicación, parece que este es el comportamiento predeterminado de ZFS.
Lo que sucede es que el archivo llega a L1ARC después de ser leído y, debido a los bloques a los que se accede, se considera que está colocado en L2ARC.
Ahora, en una segunda lectura del archivo, ZFS está realizando una captación previa del archivo, lo que omite el L2ARC aunque los bloques del archivo están almacenados en L2ARC.
Al deshabilitar completamente la captación previa zfs_prefetch_disable=1
o decirle a ZFS que realice la captación previa en L2ARC con l2arc_noprefetch=0
, las lecturas harán uso de los bloques del archivo que residen en L2ARC.
Esto podría ser deseable si su L2ARC es lo suficientemente grande en comparación con los tamaños de archivos que se están leyendo.
Pero es posible que uno quiera poner solo metadata
en L2ARC con zfs set secondarycache=metadata tank
. Esto evita que archivos grandes terminen en L2ARC y nunca se lean. Ya que esto seríaarruinarL2ARC y podría desalojar bloques de archivos más pequeños que no se están recuperando previamente y metadatos que desea conservar en L2ARC.
No he encontrado una manera de decirle a ZFS que pongasolo archivos pequeñosen L2ARC y no fusionar los candidatos de captación previa en L2ARC. Entonces, por ahora, dependiendo del tamaño de los archivos y del tamaño de L2ARC, uno tiene que hacer una compensación.
Un enfoque diferente parece estar disponible en la versión ZoL 0.8.0, donde es posible utilizar diferentesClases de asignacióny debería permitir, por ejemplo, colocar sus metadatos en SSD rápidos, dejando bloques de datos enlentodiscos giratorios. Esto todavía dejará la contienda.archivos pequeñosvs.archivos grandespara L2ARC, pero resolverá el problema del acceso rápido a los metadatos.
Respuesta2
Lo que sucede en este caso es que ZFS está tratando de preservar el ancho de banda L2ARC para lecturas aleatorias/sin transmisión, donde golpear los discos físicos causaría estragos en el rendimiento. Las lecturas de transmisión se realizan bastante bien desde discos duros mecánicos, y cualquier grupo con más de 6/8 discos probablemente superará a cualquier dispositivo SATA L2ARC para lecturas secuenciales. Y cualquier zpool de tamaño mediano (es decir, 24/48+ discos) daráinfinidadde ancho de banda real secuencial.
Como descubrió, puede modificar L2ARC para permitir que se comporte de manera más similar a un caché de víctima (es decir, almacenar cualquier cosa expulsada de ARC; si se encuentra un bloque en L2ARC, ni siquiera intente acceder al grupo principal). En algunas configuraciones específicas esto puede ser algo bueno; sin embargo, ZFS fue diseñado (correctamente) para preservar el desgaste/uso de L2ARC donde puede ser realmente ventajoso: almacenar en caché los bloques realmente usados para un rendimiento de lecturas aleatorias más rápido.