Comportamento de leitura do ZFS no disco único

1

Estou tentando configurar o ZFS em um único disco por causa dos incríveis recursos de compactação e captura instantânea. Minha carga de trabalho é um servidor postgres. Os guias habituais sugerem as seguintes configurações:

atime = off
compression = lz4
primarycache = metadata
recordsize=16k

Mas com essas configurações eu vejo alguma estranheza na velocidade de leitura - estou apenas olhando para este atm!

Para referência, aqui está o meu test drive (Intel P4800X) com XFS, é um simples teste direto de E / S com dd:

 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=4K iflag=direct
 910046+0 records in
 910046+0 records out
 3727548416 bytes (3.7 GB) copied, 10.9987 s, 339 MB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=8K iflag=direct
 455023+0 records in
 455023+0 records out
 3727548416 bytes (3.7 GB) copied, 6.05091 s, 616 MB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=16K iflag=direct
 227511+1 records in
 227511+1 records out
 3727548416 bytes (3.7 GB) copied, 3.8243 s, 975 MB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=32K iflag=direct
 113755+1 records in
 113755+1 records out
 3727548416 bytes (3.7 GB) copied, 2.78787 s, 1.3 GB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=64K iflag=direct
 56877+1 records in
 56877+1 records out
 3727548416 bytes (3.7 GB) copied, 2.18482 s, 1.7 GB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=128K iflag=direct
 28438+1 records in
 28438+1 records out
 3727548416 bytes (3.7 GB) copied, 1.83346 s, 2.0 GB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=256K iflag=direct
 14219+1 records in
 14219+1 records out
 3727548416 bytes (3.7 GB) copied, 1.69168 s, 2.2 GB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=512K iflag=direct
 7109+1 records in
 7109+1 records out
 3727548416 bytes (3.7 GB) copied, 1.54205 s, 2.4 GB/s
 [root@at-storage-01 test]# dd if=large_file.bin of=/dev/zero bs=1M iflag=direct
 3554+1 records in
 3554+1 records out
 3727548416 bytes (3.7 GB) copied, 1.51988 s, 2.5 GB/s

Como você pode ver, o drive pode ir até 80k IOPS em 4K, e o mesmo em 8K - aumento linear aqui (De acordo com a especificação, ele pode ir para 550k IOPS no QD16, mas estou testando aqui leia - então tudo como esperado)

Parâmetros do kernel para zfs:

options zfs zfs_vdev_scrub_min_active=48
options zfs zfs_vdev_scrub_max_active=128
options zfs zfs_vdev_sync_write_min_active=64
options zfs zfs_vdev_sync_write_max_active=128
options zfs zfs_vdev_sync_read_min_active=64
options zfs zfs_vdev_sync_read_max_active=128
options zfs zfs_vdev_async_read_min_active=64
options zfs zfs_vdev_async_read_max_active=128
options zfs zfs_top_maxinflight=320
options zfs zfs_txg_timeout=30
options zfs zfs_dirty_data_max_percent=40
options zfs zfs_vdev_scheduler=deadline
options zfs zfs_vdev_async_write_min_active=8
options zfs zfs_vdev_async_write_max_active=64

Agora, o mesmo teste com o ZFS e um tamanho de blocos de 16K:

 910046+0 records in
 910046+0 records out
 3727548416 bytes (3.7 GB) copied, 39.6985 s, 93.9 MB/s
 455023+0 records in
 455023+0 records out
 3727548416 bytes (3.7 GB) copied, 20.2442 s, 184 MB/s
 227511+1 records in
 227511+1 records out
 3727548416 bytes (3.7 GB) copied, 10.5837 s, 352 MB/s
 113755+1 records in
 113755+1 records out
 3727548416 bytes (3.7 GB) copied, 6.64908 s, 561 MB/s
 56877+1 records in
 56877+1 records out
 3727548416 bytes (3.7 GB) copied, 4.85928 s, 767 MB/s
 28438+1 records in
 28438+1 records out
 3727548416 bytes (3.7 GB) copied, 3.91185 s, 953 MB/s
 14219+1 records in
 14219+1 records out
 3727548416 bytes (3.7 GB) copied, 3.41855 s, 1.1 GB/s
 7109+1 records in
 7109+1 records out
 3727548416 bytes (3.7 GB) copied, 3.17058 s, 1.2 GB/s
 3554+1 records in
 3554+1 records out
 3727548416 bytes (3.7 GB) copied, 2.97989 s, 1.3 GB/s

Como você pode ver, o teste de leitura 4K já atinge 93 MB / se o 8K é lido em 184 MB / s, o 16K atinge 352 MB / s. Com base nos testes anteriores, eu definitivamente esperaria leituras mais rápidas no 4k (243.75), 8k (487.5), 16k (975). Além disso, li que o tamanho do registro não tem impacto sobre o desempenho de leitura, mas é claro que o faz.

para comparação 128k registra:

910046+0 records in
910046+0 records out
3727548416 bytes (3.7 GB) copied, 107.661 s, 34.6 MB/s
455023+0 records in
455023+0 records out
3727548416 bytes (3.7 GB) copied, 55.6932 s, 66.9 MB/s
227511+1 records in
227511+1 records out
3727548416 bytes (3.7 GB) copied, 27.3412 s, 136 MB/s
113755+1 records in
113755+1 records out
3727548416 bytes (3.7 GB) copied, 14.1506 s, 263 MB/s
56877+1 records in
56877+1 records out
3727548416 bytes (3.7 GB) copied, 7.4061 s, 503 MB/s
28438+1 records in
28438+1 records out
3727548416 bytes (3.7 GB) copied, 4.1867 s, 890 MB/s
14219+1 records in
14219+1 records out
3727548416 bytes (3.7 GB) copied, 2.6765 s, 1.4 GB/s
7109+1 records in
7109+1 records out
3727548416 bytes (3.7 GB) copied, 1.87574 s, 2.0 GB/s
3554+1 records in
3554+1 records out
3727548416 bytes (3.7 GB) copied, 1.40653 s, 2.7 GB/s

O que eu também posso ver claramente com o iostat, o disco tem um tamanho médio de solicitação do tamanho de registro correspondente. Mas as IOPS são muito menores do que com o XFS.

É assim que deve se comportar? Onde esse comportamento é documentado? Eu preciso de um bom desempenho para meu servidor postgres (sequencial + aleatório), mas também quero um ótimo desempenho para meus backups, cópias, etc. (sequencial) - parece que obtém boas sequências de velocidade com grandes registros ou boa velocidade aleatória com pequenos registros.

Edit: Além disso, eu também testei com primarycache = tudo, há mais estranheza porque ele atinge o máximo de 1,3 GB / s, independentemente do tamanho do registro.

Detalhes do servidor:

64 GB de RAM DDR4
Intel Xeon E5-2620v4
Intel P4800X

    
por Thomas Rosenstein 26.09.2017 / 15:17

1 resposta

3

O comportamento observado é devido à forma como o ZFS faz a soma de verificação de ponta a ponta, que é baseada no conceito de recordsize.

Basicamente, cada objeto é decomposto em um número apropriado de partes do tamanho de registros, que são somadas separadamente. Isso significa que as leituras de menor que o tamanho de registros realmente precisam transferir e verificar novamente o objeto registrado whole , levando a uma largura de banda de armazenamento "desperdiçada".

Isso significa que o conjunto de dados ZFS de grande tamanho de registros tem um desempenho ruim com leituras pequenas e, inversamente, com leituras grandes. Pelo contrário, o conjunto de dados ZFS de pequenos registros e gravações funciona bem com leituras pequenas e sub-par com leituras grandes.

Observe que a compactação e os instantâneos também funcionam com a granularidade do registro: um conjunto de dados com registro de 4 KB ou 8 K terá uma taxa de compactação muito menor do que, digamos, um conjunto de dados de 32 K.

Em suma, o tamanho do registro do ZFS não tem valor "à prova de balas", em vez disso, é necessário ajustá-lo ao requisito de aplicativo específico. Isto também implica que dd é uma má escolha para benchmarking (embora, sendo rápido e sujo, eu também o use extensivamente!); em vez disso, você deve usar fio (ajustado para se comportar como seu aplicativo) ou o próprio aplicativo.

Você pode ler aqui para obter mais informações.

Para uso geral, eu deixaria para o valor padrão (128K), enquanto para banco de dados e máquinas virtuais eu usaria um valor muito menor de 32K.

Por fim, preste atenção ao ajuste de leitura antecipada / pré-busca do ZFS, que pode aumentar consideravelmente a velocidade de leitura.

    
por 26.09.2017 / 22:45

Tags