Это продолжение:Высокоскоростная сетевая запись с большой емкостью хранилища. Установка существенно изменилась.
У меня есть пул с одним raid-z2
с 6 дисками, все диски Exos X18 CMR. Используя fio
и ручные тесты, я знаю, что массив может поддерживать около 800 МБ/с последовательной записи в среднем, это нормально и соответствует ожидаемой производительности этого массива. Машина представляет собой Ryzen5 Pro 2400 GE (4C/8T, 3,8 ГГц boost) с 32G ECC RAM, загрузочным/системным диском NVMe и 2x10Gbps Ethernet-портами (Intel x550-T2). Я использую современную систему Arch с zfs 2.1.2-1.
Мой вариант использования — видеоархив в основном большого (~30G) сжатого видео с однократной записью и однократным чтением. Я отключил atime
, установил recordsize=1M
, установил compressios=off
и , dedup=off
поскольку данные фактически несжимаемы, и тестирование показало худшую производительность, чем , compression=lz4
несмотря off
на то, что говорилось в Интернете, и по замыслу нет дублирующихся данных. Этот пул совместно используется по сети через Samba. Я настроил свою сеть и Samba до точки, где передача с NVMe NTFS на машине Windows на NVMe ext4 достигает 1 ГБ/с, т. е. достаточно близко к насыщению соединения 10 Гбит/с кадрами Jumbo размером 9 КБ.
Вот тут-то я и сталкиваюсь с проблемами. Я хочу иметь возможность передавать один целый 30G видеоархив со скоростью 1 ГБ/с на raid-z2
массив, который может поддерживать только последовательную запись со скоростью 800 МБ/с. Мой план состоит в том, чтобы использовать грязные страницы на основе ОЗУ для поглощения перелива и сбрасывать их на диск после того, как передача будет «завершена» на стороне клиента. Я прикинул, что мне понадобятся только (1024-800)*30~=7G
грязные страницы в ОЗУ, которые можно сбросить на диск в течение ~10 секунд после завершения передачи. Я понимаю последствия для целостности данных, и риск приемлем, поскольку я всегда могу снова передать файл позже в течение месяца на случай, если отключение питания приведет к потере или неполноте файла.
Однако я не могу заставить ZFS вести себя так, как я ожидаю... Я отредактировал свой /etc/modprobe.d/zfs.conf
файл следующим образом:
options zfs zfs_dirty_data_max_max=25769803776
options zfs zfs_dirty_data_max_max_percent=50
options zfs zfs_dirty_data_max=25769803776
options zfs zfs_dirty_data_max_percent=50
options zfs zfs_delay_min_dirty_percent=80
Я выполнил соответствующую mkinitcpio -P
команду для обновления initramfs и убедился, что настройки были применены после перезагрузки:
# arc_summary | grep dirty_data
zfs_dirty_data_max 25769803776
zfs_dirty_data_max_max 25769803776
zfs_dirty_data_max_max_percent 50
zfs_dirty_data_max_percent 50
zfs_dirty_data_sync_percent 20
То есть я установил максимальный размер грязных страниц на 24G, что намного больше, чем 7G, которые мне нужны, и удержал, чтобы начать откладывать запись, пока не будет использовано 80% этого объема. Насколько я понимаю, пул должен быть в состоянии поглотить 19G в ОЗУ, прежде чем он начнет отталкивать записи от клиента (Samba) с задержкой.
Однако, по моим наблюдениям, при записи с клиента Windows, примерно через 16 секунд при скорости записи ~1 ГБ/с производительность записи резко падает ( iostat
диски по-прежнему работают усердно, чтобы сбросить данные), что, как я могу предположить, является механизмом отталкивания для регулирования записи ZFS. Однако это не имеет смысла, так как, по крайней мере, даже если бы ничего не было сброшено в течение 16 секунд, оно должно было установиться через 3 секунды. Кроме того, в конце она снова падает, см. изображение: [ ][https://i.stack.imgur.com/Yd9WH.png]
Я пробовал настроить , zfs_dirty_data_sync_percent
чтобы начать запись раньше, потому что буфер грязных страниц намного больше, чем по умолчанию, и я также пробовал настроить масштабирование активного ввода-вывода с , zfs_vdev_async_write_active_{min,max}_dirty_percent
чтобы оно начиналось раньше, а также чтобы записи быстрее набирали скорость с большим грязным буфером. Оба они просто немного сместили положение обрыва, но далеко не так, как я ожидал.
Вопросы:
- Я неправильно понял, как работает задержка регулирования записи?
- Возможно ли то, что я пытаюсь сделать?
- Если да, то что я делаю не так?
Да, я знаю, я буквально гонюсь за парой секунд и никогда не окуплю усилия, потраченные на достижение этого. Это нормально, это личное дело между мной и ZFS на данный момент, и дело принципа ;)
решение1
Вам также необходимо увеличить zfs_txg_timeout
параметр с текущего значения по умолчанию в 5 секунд до значения около 7G/0,2G/s = 35 с, поэтому значения 40 с должно быть достаточно.
В вашей /etc/modprobe.d/zfs.conf
:
options zfs zfs_txg_timeout=40
Обратите внимание, что ARC — это именно то, что нужно, кэш «чтения» с нулевым взаимодействием с кэшем записи, поэтому убедитесь, что ваш ARC не настроен на потребление дополнительных 7G+ данных, которые ваш кэш записи блоков должен поглощать на поток записи 30 ГБ. Кэш записи для ZFS похож на любой другой простой кэш записи блоков (например, параметр commit
для файловых систем ext4), поэтому обязательно протестируйте его в непроизводственной среде, чтобы убедиться в отсутствии нехватки оперативной памяти во всех сценариях передачи.
решение2
Каждая запись будет обновлять ARC, если zfs primarycache = all (по умолчанию). Если задержка чтения не важна для данных, которые вы в данный момент записываете, я предлагаю установить zfs primarycache=meta.
решение3
В настоящее время у вас недостаточно оперативной памяти или ресурсов хранения для того, что вы ищете.
Проектируйте с учетом желаемых уровней пропускной способности ввода-вывода и их производительности в наихудшем случае.
Если вам необходима пропускная способность 1 ГБ/с при всех условиях для описываемого рабочего набора данных, то убедитесь, что количество шпинделей диска или пропускная способность интерфейса способны ее поддерживать.