Назад | Перейти на главную страницу

ZFS Read Behavior на одном диске

Я пытаюсь установить ZFS на один диск из-за потрясающих возможностей сжатия и создания снимков. Моя рабочая нагрузка - это сервер Postgres. Обычные руководства предлагают следующие настройки:

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

Но с этими настройками я действительно вижу некоторые странности в скорости чтения - я просто смотрю на этот банкомат!

Для справки вот мой тестовый диск (Intel P4800X) с XFS, это простой тест прямого ввода-вывода с 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

Как вы можете видеть, привод может достигать около 80 тыс. Операций ввода-вывода в секунду при чтении 4 КБ, и то же самое при 8 тыс. - линейное увеличение здесь (согласно спецификации он может достигать 550 тыс. Операций ввода-вывода в секунду при QD16, но я тестирую здесь однопоточное последовательное чтение - так что все как положено)

Параметры ядра для 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

Теперь тот же тест с ZFS и размером блока 16К:

 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

Как вы можете видеть, тест чтения 4K достигает максимальной уже 93 МБ / с, а чтение 8K - 184 МБ / с, 16K достигает 352 МБ / с. Основываясь на предыдущих тестах, я определенно ожидал более быстрого чтения на 4k (243,75), 8k (487,5), 16k (975). Кроме того, я прочитал, что размер записи не влияет на производительность чтения, но явно влияет.

для сравнения 128k записей:

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

Что я также могу ясно видеть с помощью iostat, средний размер запроса на диске соответствует размеру записи. Но IOPS намного ниже, чем у XFS.

Так оно и должно себя вести? Где это поведение задокументировано? Мне нужна хорошая производительность для моего сервера postgres (последовательный + случайный), но я также хочу отличную производительность для моих резервных копий, копий и т. Д. (Последовательных) - поэтому кажется, что либо я получаю хорошую последовательную скорость с большими записями, либо хорошую случайную скорость с небольшими записи.

Изменить: Кроме того, я также тестировал с помощью primarycache = all больше странностей, потому что он достигает максимальной скорости 1,3 ГБ / с независимо от размера записи.

Детали сервера:

64 ГБ DDR4 RAM
Intel Xeon E5-2620v4
Intel P4800X

Наблюдаемое поведение связано с тем, как ZFS выполняет сквозное контрольное суммирование, которое основано на концепции размера записи.

По сути, каждый объект раскладывается на соответствующее количество блоков размером с запись, которые отдельно проверяются. Это означает, что при чтении размером меньше записи действительно необходимо передать и пересчитать контрольную сумму все записанный объект, что приводит к потере пропускной способности хранилища.

Это означает, что набор данных ZFS с большими записями плохо работает с небольшими чтениями и, наоборот, хорошо с большими. Напротив, набор данных ZFS с небольшими записями хорошо работает с небольшими чтениями и ниже среднего с большими.

Обратите внимание, что сжатие и моментальные снимки также работают с детализацией размера записи: набор данных с размером записи 4 КБ или 8 КБ будет иметь гораздо более низкий коэффициент сжатия, чем, скажем, набор данных 32 КБ.

Короче говоря, размер записи ZFS не имеет «пуленепробиваемого» значения, скорее вам нужно настроить его в соответствии с требованиями конкретного приложения. Это также означает, что dd - плохой выбор для тестирования (хотя, будучи быстрым и грязным, я также широко его использую!); скорее, вы должны использовать fio (настроен так, чтобы вести себя как ваше приложение) или само приложение.

Ты можешь читать Вот для дополнительной информации.

Для общего использования я бы оставил значение по умолчанию (128 КБ), а для базы данных и виртуальных машин я бы использовал гораздо меньшее значение 32 КБ.

Наконец, обратите внимание на настройку опережающего чтения / предварительной выборки ZFS, которая может значительно увеличить скорость чтения.