MAATRIX / Блог / Предел скорости бэкапа: диск, шифрование или канал — что тормозит именно у вас

Предел скорости бэкапа: диск, шифрование или канал — что тормозит именно у вас

MAATRIX

Бэкап, который раньше укладывался в час, вдруг тянется всю ночь — и первая реакция почти всегда одна: «диск не тянет, нужен NVMe». Но у резервного копирования четыре звена, каждое из которых может оказаться тем самым узким местом: чтение с диска-источника, работа CPU на сжатии и шифровании, сетевой канал до хранилища, запись на диск-приёмник. Апгрейд не того звена — это потраченные деньги без изменения скорости. Ниже — как за один прогон реального бэкапа развести эти четыре причины по разным цифрам и не гадать.

Четыре звена одной цепи бэкапа

Типичный бэкап — это конвейер, а не одна операция: данные читаются с диска источника, дальше (не всегда, но часто) сжимаются и шифруются процессором, затем передаются по сети до места хранения и в конце записываются на диск-приёмник. Если инструмент устроен как поток (tar | gzip | openssl enc | ssh), все четыре стадии работают одновременно, каждая обрабатывает свой кусок данных, пока предыдущая стадия уже готовит следующий. Итоговая скорость всей цепи определяется самым медленным звеном — точно как на сборочной линии: не важно, что три станка успевают за секунду обработать деталь, если четвёртый тратит на неё пять секунд.

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

Диск-источник: что показывает iostat

Первое подозреваемое звено — то, откуда бэкап читает данные. Во время работы бэкапа откройте отдельный терминал и запустите:

iostat -dx 2

Смотрите на три колонки применительно к устройству-источнику: %util (загрузка устройства), await (среднее время ожидания операции в миллисекундах) и r/s/rkB/s (операции чтения и объём в секунду). Если %util держится около 100%, а await заметно выше единиц миллисекунд — диск-источник действительно упирается в потолок и является узким местом.

Отдельно стоит различать два паттерна чтения. Бэкап одного большого файла или образа — это последовательное чтение, где важна пропускная способность в МБ/с. Бэкап каталога с миллионами мелких файлов (конфиги, почта, репозитории) — это случайное чтение мелкими блоками, где всё решают IOPS, а не мегабайты в секунду: пока диск ищет очередной маленький файл, скорость в МБ/с может быть смешной при честно загруженном на 100% устройстве. Разница между этими двумя режимами разобрана подробнее в статье про то, как отличить упор именно в IOPS — тот же принцип диагностики применим и к чтению для бэкапа.

Полезно заранее знать паспортные возможности своего диска — не по рекламным цифрам провайдера, а по честному замеру fio в спокойное время, чтобы потом сравнивать наблюдаемые во время бэкапа цифры с реальным потолком, а не с ожиданиями: методика такого замера — в статье про честный тест диска через fio. Если наблюдаемая скорость чтения во время бэкапа близка к этому замеренному потолку — диск действительно узкое место. Если далеко от него — смотрите дальше по цепи.

Отдельная и частая грабля: бэкап конкурирует за диск с самим приложением. Если бэкап идёт на боевом сервере одновременно с обслуживанием запросов, оба процесса делят одну и ту же очередь ввода-вывода, и медленным выглядит уже не бэкап, а сайт или база. Диагностируется тем же iostat, только вывод читается иначе: смотрите, растёт ли await у всех процессов на устройстве синхронно с запуском бэкапа. Лечится приоритетом ввода-вывода — подробности и готовые команды в статье про ionice и приоритет бэкапа.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

CPU: где шифрование и сжатие тратят такты

Если диск-источник не упирается в потолок, а скорость всё равно низкая — следующее подозреваемое звено CPU. Смотрите на загрузку по каждому ядру отдельно, а не на усреднённую цифру: в top нажмите 1, чтобы увидеть все ядра построчно, либо запустите mpstat:

mpstat -P ALL 2

Классический симптом CPU-упора при бэкапе — одно ядро загружено под 100% в пользовательском времени (%usr), а остальные простаивают. Это почти всегда означает однопоточный инструмент: обычный gzip, xz -9 или openssl enc без явного распараллеливания упираются в одно ядро вне зависимости от того, сколько их доступно на сервере. Диск и сеть в этот момент могут быть загружены на треть от возможностей — просто потому, что CPU не успевает готовить для них данные.

Здесь стоит различать вклад сжатия и вклад шифрования — это разные по стоимости операции. Современное шифрование AES на процессоре с аппаратной поддержкой AES-NI обходится дёшево: проверить наличие поддержки — lscpu | grep -i aes, а подробный разбор того, почему шифрование перестало быть тяжёлой операцией на современном железе, — в статье про AES-NI и цену шифрования. Сжатие — совсем другая история: чем выше степень сжатия (gzip -9, xz -9, высокие уровни zstd), тем больше тактов CPU тратится на поиск повторов в данных, и именно оно, а не шифрование, чаще всего оказывается настоящим виновником загруженного под сто процентов ядра.

Практическая проверка — прогнать сжатие и шифрование по отдельности на реальном куске данных и посмотреть на пропускную способность каждого шага:

# скорость только сжатия
time zstd -c bigfile.tar > /dev/null
# скорость только шифрования (без сжатия)
time openssl enc -aes-256-gcm -pbkdf2 -in bigfile.tar -out /dev/null -pass pass:test

Если сжатие ощутимо медленнее шифрования на том же объёме данных — узкое место в компрессоре, и решение в первую очередь там: снизить уровень сжатия, перейти на многопоточный инструмент (pigz вместо gzip, zstd -T0 для использования всех ядер) или вовсе отключить сжатие для уже сжатых данных (видео, изображения, архивы) — повторное сжатие таких данных почти не уменьшает объём, но исправно грузит CPU.

Канал: сеть до места хранения

Если и диск, и CPU не в потолке, а скорость всё равно ниже ожидаемой — дело в сети между сервером-источником и местом хранения бэкапа. Диагностика та же, что и для любой передачи данных: iftop показывает трафик по каждому соединению в реальном времени, nload — суммарный график по интерфейсу, sar -n DEV из пакета sysstat — накопленную статистику за период:

iftop -i eth0 -n -P
nload eth0
sar -n DEV 1 10

Сравнивайте наблюдаемую скорость с номинальной пропускной способностью порта: 1 Гбит/с — это около 118 МБ/с полезной нагрузки, 10 Гбит/с — около 1,18 ГБ/с, в обоих случаях с поправкой на накладные расходы протокола. Если скорость передачи бэкапа стабильно упирается в это значение — канал заполнен, и дальше апгрейд диска или CPU ничего не даст. Полный алгоритм разбора «сеть или диск» с таблицами симптомов и разбором соединений — в статье про то, как отличить упор в канал от упора в диск; повторять его здесь целиком не буду, но два момента отдельно важны именно для бэкапа.

Первый — число параллельных потоков. Один поток rsync или один TCP-стрим через межконтинентальный канал (например, из RU-сервера в US-хранилище) часто не выбирает всю номинальную полосу из-за размера TCP-окна и задержки на маршруте, даже если сам канал шире. Инструменты для бэкапа, которые умеют параллелить передачу (rclone --transfers N, восстановление по частям вместо одного потока), часто дают прирост скорости без единого апгрейда канала — если причина именно в окне, а не в реальной ширине полосы, разбор физики этого эффекта — в статье про TCP-окно и тормоза канала через океан.

Второй момент — конкуренция бэкапа с боевым трафиком за один и тот же канал. Если бэкап идёт днём и сеть общая с сайтом, который отдаёт трафик пользователям, оба процесса делят одну полосу, и медленным становится либо бэкап, либо сайт, в зависимости от приоритета. Решение — шейпинг: ограничить исходящую скорость бэкапа через tc или встроенный лимит инструмента (rclone --bwlimit, borg с внешним ограничением), либо просто перенести окно бэкапа на ночные часы с низкой боевой нагрузкой.

Диск-приёмник и как проверить конвейер целиком

Четвёртое звено регулярно забывают: диск, на который бэкап пишется на другом конце. Если источник читает быстро, CPU не в потолке, канал не заполнен, а скорость всё равно ниже ожидаемой — вероятная причина в том, что принимающая сторона не успевает записывать. Это особенно частая ситуация, когда хранилище бэкапов — старый VPS с медленным диском, сетевое хранилище с ограниченными IOPS или S3-совместимый бакет с собственными лимитами на запись. Проверяется так же, как и источник: iostat -dx 2 на принимающей стороне (если это ваш собственный сервер, доступный по SSH), с тем же вниманием к %util и await.

Когда доступа к метрикам приёмника нет (например, это управляемое облачное хранилище), помогает трюк с pv (pipe viewer), вставленным между стадиями конвейера — он показывает живую скорость прохождения данных через каждый этап отдельно:

tar cf - /data \
  | pv -N read -s "$(du -sb /data | cut -f1)" \
  | zstd -T0 \
  | pv -N compress \
  | openssl enc -aes-256-gcm -pbkdf2 -pass pass:test \
  | pv -N encrypt \
  | ssh backup-host "cat > /backups/data.tar.zst.enc"

Каждый pv в цепочке печатает свою текущую скорость с подписанным именем (-N). Стадия, чья цифра стабильно ниже и не растёт, пока остальные явно способны на большее (видно по тому, что перед ней скапливается непереданный объём) — и есть узкое место. Это надёжнее, чем гадать по общему времени выполнения, потому что показывает картину именно там, где данные реально застревают, причём во время настоящего бэкапа, а не изолированного теста одной стадии.

Что ускорять, когда нашли виновника

Диагностика без действия бессмысленна, а действие не по адресу — потраченный бюджет. Сводка по звеньям:

Узкое местоСимптом в диагностикеЧто помогает
Диск-источник%util ~100%, высокий await в iostat на источникеСнизить конкуренцию через ionice, перейти на снапшот вместо чтения живой ФС, более быстрый диск (NVMe)
CPU (сжатие)Одно ядро на 100% %usr, диск и сеть недогруженыМногопоточный компрессор (pigz, zstd -T0), ниже уровень сжатия, не сжимать уже сжатые данные
CPU (шифрование)То же самое, но исчезает без openssl enc/аналогаПроверить флаг aes в lscpu, использовать AES-GCM вместо старых шифров
СетьСкорость близка к номиналу порта в iftop/nload/sarПараллельные потоки передачи, шейпинг конкурирующего трафика, хранилище ближе географически
Диск-приёмникВсё остальное не в потолке, но скорость всё равно низкаяБолее быстрое хранилище бэкапов, проверка лимитов управляемого хранилища

Важный общий принцип: если снапшот файловой системы недоступен, а бэкап читает данные с живого диска приложения, само чтение уже создаёт конкуренцию за I/O с рабочей нагрузкой — в этом случае граница между «диск не тянет» и «диск устал делить очередь между бэкапом и приложением» стирается, и первым шагом стоит попробовать ionice -c3 для процесса бэкапа, а не сразу апгрейд тарифа. И наоборот: если после диагностики видно, что упор действительно физический — в диск, канал или CPU конкретного тарифа — дальше решает только более быстрое железо. Для бэкапов и архивов имеет смысл держать отдельный сервер под эту задачу: на NVMe-хранилище и с адекватным каналом до источника у MAATRIX это снимает сразу два из четырёх узких мест — и диск-приёмник, и сеть, если хранилище держать в той же локации, что и источник данных, из RU, US или UK, с оплатой из России картой или криптой.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

С чего начинать диагностику, если непонятно, где узкое место?

С iostat -dx 2 на источнике во время реального бэкапа — это самая быстрая проверка, и если диск явно упирается в потолок (%util ~100%, высокий await), можно на этом остановиться. Если нет — по порядку: CPU через mpstat/top, сеть через iftop/nload, приёмник через iostat на другом конце или pv в конвейере.

Шифрование сильно замедляет бэкап само по себе?

На современном CPU с AES-NI — почти никогда, если используется AES-GCM. Гораздо чаще тормозит именно сжатие, особенно с высоким уровнем степени сжатия у однопоточного инструмента. Проверьте оба этапа по отдельности через time, прежде чем винить шифрование.

Почему после перехода на NVMe скорость бэкапа не выросла?

Значит, диск не был узким местом с самого начала — деньги ушли не туда. Проверьте CPU и сеть тем же способом: если одно ядро было загружено на 100% сжатием или канал был близок к номиналу порта, апгрейд диска физически не мог ничего изменить.

Можно ли ускорить бэкап, не трогая инфраструктуру вообще?

Часто да. Многопоточный компрессор вместо однопоточного, несколько параллельных потоков передачи вместо одного, ionice для снижения конкуренции с боевой нагрузкой — все три меры бесплатны и решают конкретные узкие места без апгрейда сервера.

Нужно ли проверять все четыре звена каждый раз или можно один раз и забыть?

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

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →