Hoje fiz alguns testes no L2ARC usando o ZFS mais recente no Linux 0.7.10. Eu vi que o L2ARC fica cheio de dados, mas com as configurações padrão do módulo, os dados que residem no cache L2ARC nunca são tocados. Em vez disso, os dados são lidos dos vdevs do pool principal. Também vi esse comportamento em 0.7.9 e não tenho certeza se esse é o comportamento esperado.
Mesmo que esse seja o comportamento esperado, acho estranho estragar o L2ARC com dados que nunca são lidos.
A instalação de teste é uma VM:
- CentOS 7.5 com patches mais recentes
- ZFS no Linux 0.7.10
- 2 GB de RAM
Fiz algumas configurações do ZFS:
l2arc_headroom=1024
el2arc_headroom=1024
para acelerar a população L2ARC
Veja como o pool foi criado e o layout. Eu sei que é um tanto estranho para uma configuração do mundo real, mas isso foi planejado apenas para testes 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%
Agora grave alguns dados em um arquivo e observe o uso do 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%
Tudo bem, alguns dados já foram movidos para o L2ARC, mas não todos. Então, leia mais algumas vezes para torná-lo completamente em 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%
Ok, o L2ARC está preenchido e pronto para ser lido. Mas primeiro é preciso se livrar do L1ARC. Eu fiz o seguinte, que pareceu 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
Tudo bem, agora estamos prontos para ler o L2ARC (desculpe pelo longo prefácio, mas achei importante).
Então, executando o dd if=/tank/testfile of=/dev/null bs=512
comando novamente, fiquei observando zpool iostat -v 5
em um segundo terminal.
Para minha surpresa, o arquivo foi lido nos vdevs normais em vez do L2ARC, embora o arquivo esteja no L2ARC. Este é o único arquivo no sistema de arquivos e nenhuma outra atividade está ativa durante meus testes.
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
---------- ----- ----- ----- ----- ----- -----
Em seguida , mexi em algumas configurações como zfetch_array_rd_sz
, zfetch_max_distance
, e , definindo-as para um número ímpar alto. Mas nada mudou. zfetch_max_streams
l2arc_write_boost
l2arc_write_max
Depois de mudar
l2arc_noprefetch=0
(o padrão é1
)- ou
zfs_prefetch_disable=1
(o padrão é0
) - alternar ambos de seus padrões
as leituras são servidas pelo L2ARC. Novamente executando dd if=/tank/testfile of=/dev/null bs=512
e observando zpool iostat -v 5
em um segundo terminal e livre-se do 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
E o 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
---------- ----- ----- ----- ----- ----- -----
Agora os dados são lidos do L2ARC, mas somente após alternar os parâmetros do módulo mencionados acima.
Eu também li que o L2ARC pode ser muito grande. Mas os tópicos que encontrei sobre esse tópico referiam-se a problemas de desempenho ou ao mapa espacial do L2ARC estragando o L1ARC.
O desempenho não é meu problema aqui e, pelo que posso dizer, o mapa espacial do L2ARC também não é tão grande.
[root@host ~]# grep hdr /proc/spl/kstat/zfs/arcstats
hdr_size 4 279712
l2_hdr_size 4 319488
Como já mencionado, não tenho certeza se esse é o comportamento pretendido ou se estou faltando alguma coisa.
Responder1
Então, depois de ler sobre esse assunto, principalmenteesta postagem, parece que este é o comportamento padrão do ZFS.
O que acontece é que o arquivo chega ao L1ARC após ser lido e devido aos blocos acessados ele é considerado colocado no L2ARC.
Agora, em uma segunda leitura do arquivo, o ZFS está fazendo uma pré-busca no arquivo, o que ignora o L2ARC, embora os blocos do arquivo estejam armazenados no L2ARC.
Ao desabilitar completamente a pré-busca zfs_prefetch_disable=1
ou instruir o ZFS para fazer a pré-busca no L2ARC com l2arc_noprefetch=0
, as leituras usarão os blocos do arquivo que residem no L2ARC.
Isso pode ser desejado se o seu L2ARC for grande o suficiente em comparação com os tamanhos dos arquivos que estão sendo lidos.
Mas pode-se querer colocar apenas metadata
no L2ARC com zfs set secondarycache=metadata tank
. Isso evita que arquivos grandes acabem em L2ARC e nunca sejam lidos. Já que isso seriaestragaro L2ARC e pode expulsar blocos de arquivos menores que não foram pré-buscados e metadados, que você deseja manter no L2ARC.
Não encontrei uma maneira de dizer ao ZFS para colocarapenas arquivos pequenosno L2ARC e não mesclar os candidatos de pré-busca no L2ARC. Então, por enquanto, dependendo do tamanho dos arquivos e do tamanho do L2ARC, é necessário fazer uma troca.
Uma abordagem diferente parece estar disponível na versão ZoL 0.8.0, onde é possível usar diferentesClasses de Alocaçãoe deve tornar possível, por exemplo, colocar seus metadados em SSDs rápidos, deixando blocos de dados ativados.lentodiscos giratórios. Isso ainda deixará a disputaarquivos pequenosvs.arquivos grandespara L2ARC, mas resolverá o problema de acesso rápido aos metadados.
Responder2
O que acontece neste caso é que o ZFS está tentando preservar a largura de banda L2ARC para leituras aleatórias/sem streaming, onde atingir os discos físicos causaria estragos no desempenho. As leituras de streaming são muito bem servidas em HDDs mecânicos, e qualquer pool com discos 6/8+ provavelmente superará qualquer dispositivo SATA L2ARC para leituras sequenciais. E qualquer zpool de tamanho médio (ou seja: 24/48+ discos) fornecerábastantede largura de banda real sequencial.
Como você descobriu, você pode alterar o L2ARC para permitir que ele se comporte de forma mais semelhante a um cache de vítima (ou seja: armazene qualquer coisa despejada do ARC; se um bloco for encontrado no L2ARC, nem tente acessar o pool principal). Em algumas configurações específicas, isso pode ser bom; no entanto, o ZFS foi (corretamente) arquitetado para preservar o desgaste/uso do L2ARC onde pode ser realmente vantajoso: armazenar em cache blocos realmente usados para desempenho de leituras aleatórias mais rápido.