MAATRIX / Блог / Бэкап ужался в семь раз, а восстановление стало вдвое дольше

Бэкап ужался в семь раз, а восстановление стало вдвое дольше

MAATRIX

Кто-то на проекте включил максимальный уровень сжатия для ночных бэкапов — место на хранилище стало заканчиваться, а gzip -9 или xz дали красивую экономию в разы. Через месяц сервер лёг, и восстановление, которое по всем расчётам должно было занять сорок минут, растянулось на полтора часа. Дело не в сломанном архиве и не в медленном диске — дело в том, что сжатие и восстановление тянут ресурсы в разные стороны, а экономия места и скорость аварийного восстановления почти всегда конкурируют друг с другом.

Что на самом деле стоит за процентом сжатия

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

Формально компрессор экономит место за счёт того, что тратит больше процессорного времени на поиск повторяющихся паттернов и построение более эффективных таблиц кодирования. Чем агрессивнее уровень — тем больше вычислений на обеих сторонах, но не симметрично: у большинства алгоритмов (gzip, xz) рост уровня сильнее бьёт по скорости сжатия, чем по скорости распаковки, но у высоких уровней бьёт и по распаковке тоже, просто меньше. У части алгоритмов (наглядно — zstd) распаковка вообще устроена почти асимметрично: она остаётся быстрой почти на всех уровнях, а вот сжатие на верхних уровнях (-19 и выше) становится по-настоящему медленным.

Вывод из механики простой: сеть и диск — не единственные узкие места при восстановлении. Если у вас современный NVMe и гигабитный канал, а бэкап сжат агрессивным xz -9, то восстановление вполне может упереться не в диск и не в сеть, а в одно ядро CPU, которое разворачивает поток данных.

Почему семикратное сжатие обернулось вдвое более долгим восстановлением

Возьмём условный, но реалистичный сценарий (числа ориентировочные, у вас будут свои — это не результат конкретного бенчмарка, а иллюстрация масштаба эффекта). Дамп базы на 350 ГБ:

Уровень сжатияРазмер архиваВремя сжатия (ночью, не критично)Время восстановления
Без сжатия350 ГБ~0 (только запись)быстрее всего, но диск/сеть — узкое место
gzip -1 / zstd -3~110 ГБ (≈3×)умеренноебазовый уровень для сравнения
gzip -9~50 ГБ (≈7×)заметно дольшепочти вдвое дольше базового
xz -9~45 ГБ (≈8×)сильно дольшеещё дольше, чем gzip -9

Экономия места на хранилище от gzip -9 против gzip -1 реальна и заметна — это не миф. Проблема в том, что владелец сервера сравнивал уровни сжатия по единственному критерию (сколько гигабайт займёт архив), не проверив, во что это выльется на восстановлении. В момент аварии оказалось, что «сэкономленные» гигабайты стоили лишних 40–50 минут простоя — а простой почти всегда дороже места на диске.

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

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

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

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

Сжатие ради канала — отдельный частный случай

Если у вас узкий или дорогой канал (например, бэкапы уезжают в другую страну через VPN или у вас лимитированный трафик), сжатие экономит не только место, но и время передачи. Здесь расчёт немного другой: выигрыш от сжатия на передаче может перекрыть проигрыш на распаковке, особенно если канал — это минуты, а лишние секунды CPU на распаковку — это доли процента от общего RTO. Но это нужно именно посчитать для вашей пары «канал/CPU», а не предполагать по умолчанию. Разбор похожей темы с упором на диск, шифрование и канал — в статье про предел скорости бэкапа.

Уровни сжатия на практике: gzip, zstd, xz, lz4

Коротко о том, чем отличаются алгоритмы, которые реально стоят в дистрибутивах и в инструментах бэкапа:

  • gzip — стандарт де-факто, есть везде, декомпрессия быстрая и предсказуемая, но при высоких уровнях (-8, -9) сжатие становится ощутимо медленнее, а выигрыш в размере — небольшой по сравнению с -6. Однопоточный по умолчанию (есть многопоточная реализация pigz, она ускоряет именно сжатие, распаковка pigz многопоточная тоже, но выигрыш скромнее).
  • zstd — современный алгоритм с широким диапазоном уровней (1–19, plus --ultra -22), поддерживает многопоточность через -T0 (использовать все ядра) на сжатии и частично на распаковке, и держит быструю распаковку почти на всех уровнях — это его главное практическое преимущество для бэкапов, которые придётся восстанавливать быстро.
  • xz / lzma — даёт лучшее сжатие по размеру среди распространённых алгоритмов, но и сжатие, и распаковка ощутимо медленнее zstd на сопоставимом уровне компрессии. Хороший выбор для холодного архива, спорный — для операционных бэкапов.
  • lz4 — минимальное сжатие, зато самая быстрая распаковка из всех. Подходит, когда CPU в дефиците, а место не критично, или как «сжатие почти бесплатно».

Практический ориентир: если сравнивать zstd и gzip/xz на одинаковом «бюджете» размера файла, zstd почти всегда восстанавливается быстрее — за счёт архитектуры формата, а не только настроек. Это не значит «всегда используйте zstd», но если вы выбираете инструмент с нуля под новый проект — это разумная точка старта.

Как выбирать уровень для операционных бэкапов

Операционные бэкапы — это то, что должно подняться быстро: суточные/часовые дампы прод-базы, снапшоты Docker-томов, всё, на что у вас есть RTO (recovery time objective) в часах или минутах. Здесь приоритет — скорость восстановления, а не экономия места:

  • Берите умеренный уровень сжатия или не сжимайте вовсе, если хранилище позволяет. Разница в стоимости диска между «сжато втрое» и «сжато в семь раз» обычно куда меньше, чем стоимость лишнего часа простоя.
  • Для PostgreSQL — custom-формат дампа с zstd, если версия сервера/клиента поддерживает (pg_dump 16+ умеет compression method):
pg_dump -Fc --compress=zstd:3 -f dump.dump dbname
pg_restore -j4 -d dbname dump.dump

Если версия старше, гоните через пайп:

pg_dump dbname | zstd -T0 -3 -o dump.sql.zst
zstd -d -T0 --long=27 -c dump.sql.zst | psql dbname
  • Для BorgBackup — умеренный zstd прямо в репозитории:
borg init --encryption=repokey-blake2 --compression zstd,3 /path/to/repo
  • Для tar-архивов вместо tar czf (gzip) берите tar --zstd -cf backup.tar.zst ./data, а распаковку тестируйте с -T0, чтобы задействовать все ядра.
  • Restic с версии 0.16 сжимает автоматически (auto compression), уровень регулируется на этапе restic init --repository-version 2 — не нужно выбирать вручную, но полезно знать, что репозитории старого формата сжатия не имеют вовсе.

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

Как выбирать уровень для архивного и холодного хранения

Архивные бэкапы — это то, что вы храните месяцами и годами «на всякий случай», и по регламенту или по здравому смыслу вряд ли будете восстанавливать в срочном порядке (юридическое хранение, снепшоты для комплаенса, дальний холодный слой 3-2-1-схемы). Здесь приоритет разворачивается на 180 градусов — экономия места важнее скорости:

  • Можно и нужно сжимать сильнее: xz -9 или zstd --ultra -22 --long=31. Разница в стоимости хранения при годах ретеншена и десятках копий действительно накапливается и становится заметной строкой в бюджете.
  • CPU-цена такого сжатия оплачивается один раз, в фоне, не под давлением аварии — запускайте это как отдельную низкоприоритетную задачу, а не как часть основного бэкап-окна:
nice -n 19 ionice -c3 zstd --ultra -22 --long=31 -T0 -o archive.zst dump.sql
  • Если для архива когда-нибудь всё же понадобится восстановление — закладывайте в план аварийного восстановления отдельную, более длинную оценку RTO именно для этого слоя, а не общую цифру «как для прод-бэкапа». Экономический расчёт этой развилки — куда важнее хранение или RTO — подробно разобран в статье про цену восстановления против цены хранения.

Граница между «операционным» и «архивным» бэкапом — не техническая, а организационная: это вопрос из вашего DR-плана, а не из настроек компрессора. Если непонятно, к какой категории отнести конкретный бэкап — считайте его операционным, пока не докажете обратное: недооценённое RTO обходится дороже, чем переплата за диск.

Как измерить настоящее время восстановления, а не поверить документации

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

time (
  aws s3 cp s3://backups/dump.sql.zst - \
    | zstd -d -T0 --long=27 \
    | psql -h restore-test-host -U postgres dbname
)

Важно мерить весь конвейер целиком — скачивание из хранилища, распаковку и загрузку в СУБД, а не только «сколько секунд разворачивается архив». В проде узкое место может оказаться не там, где вы предполагали: например, скачивание из удалённого хранилища медленнее, чем распаковка, и тогда экономия на уровне сжатия вообще не играет роли — играет географическая близость хранилища к серверу восстановления.

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

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

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

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

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

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

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

Что в итоге важнее — сэкономить место на диске или ускорить восстановление?

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

Можно ли получить одновременно и сильное сжатие, и быстрое восстановление?

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

Как понять, что именно сжатие — узкое место при восстановлении, а не диск или сеть?

Во время тестового восстановления смотрите на загрузку CPU (top, htop) и на утилизацию диска/сети (iostat, iftop) одновременно. Если ядро, разворачивающее архив, пришпилено к 100%, а диск и сеть простаивают — узкое место в распаковке, есть смысл понизить уровень сжатия или сменить алгоритм.

Стоит ли сильно сжимать бэкапы уже сжатых данных — видео, JPEG, готовые архивы?

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

В каком порядке сочетать сжатие и шифрование бэкапа?

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

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

Да, это разумно: полный бэкап обычно попадает в «архивную» категорию по частоте обращения (нужен реже) и его можно жать сильнее, а инкременты чаще участвуют в цепочке быстрого восстановления — для них лучше умеренный уровень.

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

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

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