Производительность систем хранения файлов: как найти узкое место и ускорить хранилище | AdminWiki

Производительность систем хранения файлов: как найти узкое место и ускорить хранилище

14 сентября 2026 14 мин. чтения

Почему хранилище тормозит: четыре источника ограничений

Скорость файлового хранилища ограничивает тот слой, который первым упёрся в предел: диски, контроллер и шина PCIe, сеть, файловая система с её параметрами. В конкретный момент узкое место одно. Апгрейд любого другого слоя не даёт прироста и съедает бюджет.

Проверка, которая занимает десять минут. Снимите локальную скорость прямо на сервере хранения. Если массив отдаёт 500 МБ/с локально, а NFS-клиент получает 80 МБ/с, ограничение сидит в сети или в настройках протокола. Обратная картина: канал держит гигабит, но iowait выше 30%, а await растёт под нагрузкой, значит упёрлись диски.

Порядок работы такой: измеряем и фиксируем baseline, локализуем слой, который первым достиг предела, и только после этого ускоряем. Менять диски, когда причина в MTU или recordsize, - самая дорогая ошибка в этой теме.

Как отличить дисковое узкое место от сетевого

Разделяйте слои прямыми замерами. Локальный тест с обходом кэша показывает предел накопителя, сетевой тест показывает предел канала, а замер на клиенте показывает результат их совместной работы. Таблица ниже помогает сузить круг за минуту.

СимптомВероятный слойЧто проверить первым
Локально быстро, по сети медленноСеть, протоколethtool, iperf3, параметры монтирования
Высокий iowait, await растёт под нагрузкойДиски, массивiostat -x, состояние пула, SMART
Скорость вдвое ниже паспортнойШина, контроллер, выравниваниеPCIe lanes, режим кэша контроллера, разметка
Приложение пишет медленно, диск свободенФайловая система, sync-записьrecordsize, ZIL/SLOG, режим sync
Скорость падает со временемДеградация носителейSMART, результат scrub, тип дисков

Пример из практики: NFS-клиент показывает 80 МБ/с на записи, а локальный тест на том же массиве даёт 500 МБ/с последовательной записи. Массив тут не при чём. Сначала проверьте линк командой ethtool eth0: скорость и duplex. Затем запустите iperf3 между сервером и клиентом. Если канал выдаёт 9,4 Гбит/с, а NFS всё равно 80 МБ/с, копайте rsize/wsize, nconnect и размер TCP-окна.

Когда картина размыта и непонятно, на каком слое искать, помогает методика разбора bottleneck по метрикам: она позволяет подтвердить причину деградации, а не угадать её. Такой подход описан в материале как найти узкое место в системе и повысить производительность без лишних затрат.

Типичные ошибки при поиске узкого места

  • Замер на прогретом кэше. Свободная оперативная память и page cache отдают данные быстрее любого накопителя. Перед тестом сбросьте кэш: echo 3 > /proc/sys/vm/drop_caches. Для ZFS дополнительно используйте direct I/O в fio, иначе ARC отдаст данные из памяти и результат ничего не покажет.
  • Один поток вместо реальной нагрузки. Синхронный dd с глубиной очереди 1 показывает максимум для одной операции, а не для базы данных с 64 одновременными запросами. Тестируйте с iodepth 32-128 и несколькими задачами (numjobs).
  • Игнорирование queue depth. У SATA SSD очередь 32 команды, у NVMe - тысячи. Один и тот же диск на глубине 1 и на глубине 64 выдаёт разные цифры, и сравнивать результаты с разной глубиной нельзя.
  • Сравнение разного типа нагрузки. Sequential и random на HDD расходятся в десятки раз. Для архивов важна последовательная скорость, для баз данных и виртуалок - 4K random.

После каждого изменения снимайте новый замер и записывайте рядом с baseline. История цифр за месяц объясняет деградацию быстрее, чем интуиция.

Как измерить реальную производительность хранилища

Набор инструментов минимален: fio для нагрузки, ioping для задержки, iostat -x для наблюдения, iperf3 и sar -n DEV для сети. Всё есть в стандартных репозиториях и не требует остановки сервисов.

  1. Baseline диска. Случайное чтение 4K при глубине 32: fio --name=randread --ioengine=libaio --direct=1 --rw=randread --bs=4k --iodepth=32 --numjobs=4 --size=4G --runtime=60 --group_reporting. Далее то же для randwrite, затем последовательные 1M: --rw=read --bs=1M. Смотрите три числа: IOPS, МБ/с и среднюю латентность.
  2. Задержка отклика. ioping -c 20 -i 1 /mnt/data показывает latency без нагрузки. Полезно сравнить с latency под нагрузкой: рост в 5-10 раз говорит о перегрузке очереди.
  3. Текущая нагрузка. iostat -x 1 в течение 60 секунд под рабочим трафиком. Средние значения по всем дискам важнее пиковых.
  4. Сеть. iperf3 -s на сервере, iperf3 -c 10.0.0.10 -t 30 -P 4 на клиенте, повторите с ключом -R для обратного направления. Пропускную способность интерфейса проверьте через sar -n DEV 1.

Ориентиры, с которыми стоит сравнивать свои цифры. HDD 7200 rpm: 80-120 IOPS на 4K random, 150-220 МБ/с последовательно, latency 8-15 мс. SATA SSD: 50-90 тыс. IOPS, 500-550 МБ/с, latency 0,1-0,3 мс. Потребительский NVMe: 200-500 тыс. IOPS, 2-3,5 ГБ/с. Серверный NVMe с PCIe 4.0: от 1 млн IOPS, 6-7 ГБ/с, latency ниже 0,1 мс. Реальный массив из нескольких дисков показывает сумму с поправкой на накладные расходы RAID.

Измеряйте под нагрузкой, близкой к рабочей. Синтетический тест на пустом хранилище и тест на массиве, занятом на 80%, дадут разную картину, особенно на ZFS и на SSD без TRIM.

Метрики производительности дисков: что смотреть в iostat

Утилита iostat -x 1 выводит десятки полей, но решения принимаются по пяти: r/s и w/s (число операций), rkB/s и wkB/s (объём), await (средняя задержка одной операции с учётом очереди), %util (доля времени, когда устройство занято).

Devicer/sw/srkB/swkB/sawait, мс%util
sda (HDD)12340961360018,499,2
nvme0n1820003280000,0812,4

Читается так: HDD загружен полностью (%util 99), очередь накопилась, await 18 мс при потоке 340 записей в секунду. Диск работает на пределе, дальше расти некуда. NVMe при 8200 операций чтения имеет await 0,08 мс и загрузку 12%, у него большой запас.

Пороги для быстрой реакции: await выше 20 мс для SSD и выше 50 мс для NVMe - сигнал тревоги, %util выше 90% на всех дисках массива означает насыщение. Поле svctm встречается в выводе, но его значения недостоверны на современных устройствах с параллельной обработкой очереди, опирайтесь на await. Для NVMe и многодисковых массивов %util тоже теряет смысл: устройство обрабатывает команды параллельно, и 100% загрузки не означают предела. Ориентируйтесь на latency и глубину очереди.

Тестирование сети: iperf3 и проверка пропускной способности

Запуск: на сервере хранения iperf3 -s, на клиенте iperf3 -c 10.0.0.10 -t 30 -P 4. Несколько потоков нужны, потому что одно TCP-соединение часто упирается в возможности одного ядра. Затем замерьте в обратную сторону: iperf3 -c 10.0.0.10 -R -t 30.

Ориентиры по каналам в одну сторону: 1 GbE даёт около 110-117 МБ/с, 10 GbE около 1,1-1,18 ГБ/с, 25 GbE около 2,8 ГБ/с, 100 GbE около 11 ГБ/с. Если iperf3 показывает 940 Мбит/с на десятигигабитном линке, проблема в драйвере, кабеле, коммутаторе или в настройках offload.

Проверка MTU выполняется так: ping -M do -s 8972 10.0.0.10. Для кадра 9000 байт полезная нагрузка ICMP составляет 8972 байта. Прошло без фрагментации - jumbo frames работают на всём пути. Получили ошибку вида "message too long" - где-то в цепочке MTU остался 1500.

Если iperf3 даёт норму, а NFS медленный, узкое место в настройках протокола, в синхронной записи или в дисках. Сеть тут уже не при чём.

Кэширование в системах хранения: что реально ускоряет

Уровней кэша несколько, и каждый ускоряет свой тип операций. page cache Linux держит недавно прочитанные данные в свободной RAM и управляется параметрами vfs_cache_pressure, dirty_ratio, dirty_background_ratio и размером readahead (blockdev --setra в секторах). В ZFS ту же работу делает ARC. Отдельно существуют L2ARC для чтения с SSD и SLOG для синхронной записи. Кэш контроллера RAID работает на уровне блоков и тоже влияет на результат.

Разумные значения для Linux-сервера хранения с большим объёмом RAM: vfs_cache_pressure от 50 до 80 (чем выше, тем агрессивнее ядро освобождает кэш inode и dentry), vm.dirty_ratio 10-20, vm.dirty_background_ratio 5-10. Большой dirty_ratio на медленных дисках приводит к долгим всплескам записи и росту latency.

Настройка ARC и L2ARC в ZFS

ARC по умолчанию забирает до 50% оперативной памяти. На выделенном хранилище этот лимит поднимают до 75-80% через параметр zfs_arc_max. На Linux его задают в файле /etc/modprobe.d/zfs.conf строкой options zfs zfs_arc_max=<значение в байтах>, на FreeBSD через sysctl, в TrueNAS через раздел tunables. Пример: 64 ГБ RAM и рабочий набор 500 ГБ - под ARC отдаём 48 ГБ, остальное оставляем ОС и сервисам.

L2ARC помогает, когда рабочий набор данных превышает доступную RAM. Кэш ставится на быстрый SSD или NVMe, а в датасете включается использование второго уровня: zfs set secondarycache=all pool/data. Плата за это - оперативная память под индексацию: ориентировочно 1 ГБ RAM на каждые 100 ГБ L2ARC. На слабой машине с 16 ГБ памяти L2ARC только навредит, потому что отнимет память у основного ARC.

L2ARC ускоряет чтение и не влияет на запись. Если нагрузка на 90% состоит из записи, кэш второго уровня бесполезен. Практические сценарии выбора SSD под кэш и оценки его эффективности по hit ratio разобраны в руководстве настройка кэширования в TrueNAS.

SLOG и ZIL: когда синхронная запись тормозит

ZFS пишет синхронно, когда этого требует вышестоящее приложение: NFS с опцией sync, базы данных с fsync, виртуалки с включённым кэшированием записи. Каждая такая операция должна дойти до стабильного носителя, и задержка определяет итоговую скорость. SLOG (Separate Log Device) переносит журнал ZIL с медленных дисков пула на быстрый SSD.

Добавление: zpool add pool log nvme0n1. Для защиты от потери данных SLOG ставят в зеркало (zpool add pool log mirror nvme0n1 nvme1n1) либо берут диск с конденсаторами и защитой от отключения питания. Дешёвый потребительский SSD без power-loss protection приведёт к потере подтверждённых записей при сбое питания.

SLOG не кэширует данные, он ускоряет фиксацию транзакций и освобождает пул от случайной записи по журналу. Без синхронных операций (sync=standard при обычной записи или sync=disabled) устройство простаивает. Ставить SLOG под нагрузкой из одних последовательных копирований смысла нет.

Кэш контроллера RAID работает по своим правилам. Режим write-back с батареей даёт кратный прирост на случайной записи, режим write-through без батареи тормозит всё. Об этом ниже, в разделе про ловушки конфигурации.

Уровни хранения SSD и HDD: как правильно разделить данные

Смысл разделения простой: горячие данные живут на быстрых носителях, холодные на дешёвых. Реализаций три. Первая - ручное разделение по датасетам: база данных на NVMe, архивы и бэкапы на HDD. Вторая - special vdev в ZFS для метаданных и мелких блоков. Третья - блочный кэш bcache или dm-cache, который ставит SSD перед медленным устройством.

Special vdev ускоряет операции с метаданными и мелкими блоками, перенося их на SSD. Задаётся при создании: zpool add pool special mirror nvme0n1 nvme1n1. Ориентир по объёму: 1-2% ёмкости пула обычно достаточно, но всё зависит от среднего размера файлов. Важное предупреждение: special vdev без зеркала превращается в точку отказа. Его потеря означает потерю всего пула, а не отдельного диска.

bcache и dm-cache работают на уровне блочных устройств и не зависят от файловой системы. Включают их там, где нужен SSD-кэш перед ext4 или XFS, а ZFS не используется. Настройка сложнее, чем кажется: при неверном режиме (writethrough вместо writeback) прирост исчезает.

Разделение уровней добавляет эксплуатационную сложность. Если горячий набор уже целиком помещается в ARC и L2ARC, отдельный tiering не нужен. Для расчёта требований по IOPS, латентности и запасу на рост пригодится методика из статьи как выбрать систему хранения данных: она помогает посчитать реальную нагрузку до закупки железа, а не после.

Часть холодных данных иногда дешевле держать вне собственного массива. Облачный провайдер закрывает эту задачу без закупки дисков и контроллеров: Timeweb Cloud предоставляет серверы с NVMe, блочное хранилище и готовую инфраструктуру под бэкапы, вынос архивов или тестовый стенд для замеров.

Настройка NFS и SMB: параметры, которые влияют на скорость

Для NFS на клиенте Linux 5.3 и новее ключевой параметр - nconnect. Одно TCP-соединение ограничено размером окна, задержкой и возможностями одного ядра, поэтому несколько каналов дают кратный прирост. Пример строки монтирования: mount -t nfs -o vers=4.2,rsize=1048576,wsize=1048576,nconnect=8,noatime 10.0.0.10:/pool/data /mnt/data. На 10 GbE связка vers=4.2 плюс nconnect=8 превращает 300-400 МБ/с в 900-1100 МБ/с на одном клиенте.

Дополнительно проверьте число потоков сервера nfsd: на сервере с 32 ядрами значение RPCNFSDCOUNT в пределах 64-128 покрывает нагрузку. На клиентах с ядром старше 5.3 вместо nconnect увеличивают sunrpc.tcp_slot_table_entries до 128.

Для SMB (Samba) важны версия протокола, multichannel и socket options. Минимум, который стоит выставить в smb.conf: server min protocol = SMB3, server multi channel support = yes, socket options = TCP_NODELAY IPTOS_LOWDELAY. Для клиентов macOS добавляют vfs objects = fruit и catia, иначе метаданные и права обрабатываются медленно.

iSCSI и NVMe-oF чувствительны к задержке сильнее, чем к пропускной способности. Для них имеет смысл RDMA (iSER) и отдельная сеть без общей нагрузки. Jumbo frames (MTU 9000) включайте только тогда, когда все устройства на пути поддерживают этот размер: сервер, коммутатор, клиент, а также хранилище. Ошибка в одном звене даёт фрагментацию, рост задержки и падение скорости ниже исходной.

Тюнинг ZFS под конкретную нагрузку

Набор параметров ZFS невелик, но каждый влияет на результат заметно. recordsize определяет размер блока и лучшее совпадение с профилем нагрузки. ashift фиксирует размер сектора и задаётся один раз при создании пула. compression=lz4 сжимает почти бесплатно и часто ускоряет запись за счёт меньшего объёма данных на диск. atime=off убирает лишние операции записи. sync выбирает режим подтверждения.

Нагрузкаrecordsize / volblocksizesyncДополнительно
PostgreSQL, MySQL16Kstandardlogbias=throughput при SLOG, atime=off
Виртуальные машины64Kstandardxattr=sa, compression=lz4
Медиа, бэкапы1Mstandardcompression=lz4, atime=off
Общий SMB/NFS128Kstandardatime=off, secondarycache=all

ashift=12 выставляйте всегда для дисков с сектором 4K, включая те, что отдают 512e. Ошибка ashift=9 на 4K-диске режет производительность записи и увеличивает износ. Исправить ashift после создания пула нельзя, только пересоздать пул и перелить данные.

Изменение recordsize применяется только к новым данным. Существующие файлы и блоки сохраняют прежний размер, пока запись не перезапишет их. Для смены профиля помогает копирование датасета: zfs send и zfs receive на новый датасет с нужными параметрами.

Не отключайте scrub ради производительности: регулярная проверка целостности выявляет ошибки чтения раньше, чем они превратятся в потерю данных. Ставьте scrub на ночные часы и следите за нагрузкой во время его работы.

Когда апгрейд железа не помогает: конфигурационные ловушки

Замена дисков не даст прироста, если ограничение лежит в другом месте. Ниже список причин, которые встречаются чаще всего.

  • SMR-диски в массиве. Черепичная запись даёт провалы скорости в десятки раз при переполнении внутреннего кэша и сильно замедляет resilver в ZFS. Проверяйте модель диска перед покупкой, а не после.
  • Невыровненные разделы. Раздел, начинающийся не на границе 1 МиБ, заставляет каждый блок записи читаться и переписываться заново. Проверка: parted -l показывает выравнивание разделов.
  • Неверный размер страйпа RAID. Страйп 64K под 4K-запись даёт лишние операции. Для баз данных страйп подбирают под размер блока приложения.
  • Контроллер в режиме write-through. Без кэша записи и без батареи контроллер подтверждает каждую запись физически. Переключение в write-back с BBU даёт кратный прирост на случайной записи.
  • Нехватка линий PCIe. NVMe в слоте x4 при физическом подключении через чипсет с общей линией теряет половину скорости. Проверьте lspci -vv: скорость и ширина линка указаны в поле LnkSta.
  • Неподходящий recordsize. База данных на датасете с recordsize 1M пишет в разы медленнее, чем на 16K.
  • Сетевой потолок. Классика: массив из восьми NVMe работает, а клиенты подключены через 1 GbE и получают 110 МБ/с. Никакие настройки не превысят физическую пропускную способность линка.

Чек-лист перед апгрейдом. Проверьте загрузку линка и MTU. Снимите iostat -x под реальной нагрузкой. Убедитесь, что кэш контроллера включён и работает от батареи. Сверьте выравнивание разделов и ashift. Посчитайте, какой слой упирается первым, и только потом выбирайте, что менять.

Мониторинг производительности хранилища и предотвращение деградации

Разовая диагностика решает текущую проблему, но деградация накапливается незаметно. Дешёвый и надёжный стек: node_exporter для метрик системы, zfs_exporter или встроенные средства ZFS для пулов, smartctl_exporter для SMART, Prometheus как хранилище и Grafana как дашборды. Графики по iostat, hit ratio ARC, latency и свободному месту показывают динамику, которую не видно в отдельный момент времени.

Пороговые значения для алертов, которые хорошо работают на практике:

  • await выше 50 мс (или выше 20 мс для SSD) в течение 5 минут подряд.
  • ARC hit ratio ниже 90% на постоянной основе - рабочий набор не помещается в память.
  • Свободное место ниже 20% на пуле: ZFS теряет возможность эффективно размещать блоки, SSD теряют резерв под перезапись.
  • iowait выше 20% и растущая длина очереди запросов.
  • SMART: рост Reallocated_Sector_Ct, Pending_Sector, ошибки CRC на интерфейсе.
  • Ошибки и предупреждения ZED, а также ошибки проверки scrub.

ZED следит за событиями ZFS и сообщает о деградации пула, ошибках записи и провале проверок целостности. Утилита smartctl -a по расписанию даёт историю состояния дисков. После каждого изменения настроек фиксируйте новый baseline: без него вы не отличите замедление после правки от фонового роста нагрузки.

Пошаговые сценарии настройки сбора метрик, дашбордов и алертов собраны в руководствах мониторинг систем хранения: ключевые метрики и система мониторинга и проактивного обслуживания дисковых массивов.

Начните с одного действия прямо сейчас: снимите baseline на рабочем хранилище и запишите цифры в отдельный файл с датой. Когда через месяц приложение начнёт жаловаться на медленную запись, у вас будет с чем сравнивать, и вы найдёте узкое место за минуты, а не за дни.

Поделиться:
Сохранить гайд? В закладки браузера