ZFS no Linux - L2ARC não está sendo lido

2

Hoje fiz alguns testes no L2ARC usando o último ZFS no Linux 0.7.10. Eu vi que o L2ARC é preenchido com dados, mas com as configurações do módulo padrão, os dados que residem no cache L2ARC nunca são tocados. Em vez disso, os dados são lidos a partir dos vdevs do conjunto principal. Eu também tenho visto 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 os patches mais recentes
  • ZFS no Linux 0.7.10
  • 2 GB de RAM

Eu fiz algumas configurações do ZFS:

  • l2arc_headroom=1024 e l2arc_headroom=1024 para acelerar a população L2ARC

Veja como o pool foi criado e o layout. Eu sei que é bastante estranho para uma configuração do mundo real, mas isso foi destinado 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 dos dados já foram movidos para o L2ARC, mas não todos. Então, leia-o 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 é preciso se livrar do L1ARC primeiro. Eu fiz o seguinte, que parece ter funcionado.

[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 que era importante).
Então, rodando o comando dd if=/tank/testfile of=/dev/null bs=512 novamente, eu estava assistindo zpool iostat -v 5 em um segundo terminal.

Para minha surpresa, o arquivo foi lido a partir do vdevs normal 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
----------  -----  -----  -----  -----  -----  -----

Eu, então, mexi com algumas configurações como zfetch_array_rd_sz , zfetch_max_distance , zfetch_max_streams , l2arc_write_boost e l2arc_write_max , configurando-as para um número ímpar alto. Mas nada mudou.

Depois de mudar

  • l2arc_noprefetch=0 (o padrão é 1 )
  • ou zfs_prefetch_disable=1 (o padrão é 0 )
  • alternar os dois de seus padrões

as leituras são servidas a partir do L2ARC. Novamente executando dd if=/tank/testfile of=/dev/null bs=512 e assistindo zpool iostat -v 5 em um segundo terminal e se livrando 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 depois de alternar os parâmetros do módulo mencionados acima.

Eu também li que o L2ARC pode ser grande demais. Mas os tópicos que encontrei sobre esse tópico estavam se referindo a problemas de desempenho ou o mapa de espaço para o L2ARC estragando o L1ARC. O desempenho não é meu problema aqui, e até onde eu posso dizer, o mapa espacial para o L2ARC também não é tão grande assim.

[root@host ~]# grep hdr /proc/spl/kstat/zfs/arcstats 
hdr_size                        4    279712
l2_hdr_size                     4    319488

Como já foi mencionado, não tenho certeza se esse é o comportamento pretendido ou se estou perdendo alguma coisa.

    
por Thomas 09.09.2018 / 17:21

2 respostas

2

Então, depois de ler este tópico, principalmente este post , parece que isso é o comportamento padrão do ZFS.

O que acontece é que o arquivo entra no L1ARC depois de ser lido e, devido aos blocos acessados, é considerado colocado no L2ARC.
Agora, em uma segunda leitura do arquivo, o ZFS está fazendo uma pré-busca no arquivo, que ignora o L2ARC, embora os blocos do arquivo estejam armazenados no L2ARC.

Desativando a pré-busca completamente com zfs_prefetch_disable=1 ou dizendo ao ZFS para fazer a pré-busca no L2ARC com l2arc_noprefetch=0 , as leituras farão uso dos 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 de arquivo 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 no L2ARC e nunca sejam lidos. Já que isso estragaria o L2ARC e poderia despejar blocos de arquivos menores não sendo pré-buscados e metadados, o que você deseja manter no L2ARC.

Não encontrei uma maneira de dizer ao ZFS para colocar apenas arquivos pequenos no L2ARC e não mesclar os candidatos de pré-busca ao L2ARC. Por enquanto, dependendo do tamanho dos arquivos e do tamanho do L2ARC, é necessário fazer a troca. Uma abordagem diferente parece estar disponível na versão ZoL 0.8.0, onde é possível usar diferentes Classes de Alocação e deve possibilitar, por exemplo. coloque seus metadados em SSDs rápidos, enquanto deixa blocos de dados em discos rotativos lentos . Isso ainda deixará a contenção arquivos pequenos vs. arquivos grandes para o L2ARC, mas resolverá o acesso rápido no problema de metadados.

    
por 15.09.2018 / 13:36
1

O que acontece neste caso é que o ZFS está tentando preservar a largura de banda do L2ARC para leituras aleatórias / não de streaming, onde bater nos discos físicos causaria estragos no desempenho. Leituras de streaming são servidas muito bem de HDDs mecânicos, e qualquer pool com 6/8 + discos provavelmente superará qualquer dispositivo SATA L2ARC para leituras sequenciais. E qualquer zpool de tamanho médio (isto é: 24/48 + discos) dará abundância de largura de banda real sequencial.

Como você descobriu, você pode alterar o L2ARC para permitir que ele se comporte de forma mais semelhante ao cache da vítima (isto é: 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 arquitetado (corretamente) para preservar o desgaste / uso do L2ARC para onde ele pode ser realmente vantajoso: para armazenar em cache os blocos realmente usados para um desempenho mais rápido de leituras aleatórias.

    
por 15.09.2018 / 19:20