Бэкап перестал влезать в ночное окно: считаем, сколько часов у вас ещё осталось
Полгода назад полный бэкап укладывался в три часа с солидным запасом до конца ночного окна низкой нагрузки. Сейчас он занимает пять с половиной, и на графике видно, что линия уверенно ползёт вверх — с тем же темпом через несколько месяцев бэкап будет заканчиваться уже после того, как утренний трафик наберёт обороты, и грузить диск ровно тогда, когда он нужнее всего. Ниже — как посчитать текущий запас в часах, спрогнозировать, когда он закончится, и какие меры реально его продлевают, а не просто откладывают проблему на пару недель.
Содержание
- Симптом: как понять, что окно уже не резиновое
- Считаем скорость роста данных и текущую скорость бэкапа
- Прогноз: сколько часов у вас реально осталось
- Первая мера — уйти от полного бэкапа каждую ночь: инкремент и дифференциал
- Вторая мера — снапшоты уровня ФС/тома вместо копирования файлов
- Третья и четвёртая меры — сжатие, распараллеливание и отдельный канал
Симптом: как понять, что окно уже не резиновое
Пока бэкап укладывается в окно с запасом, на его длительность обычно никто не смотрит — он просто «работает». Проблема в том, что первый явный сигнал часто приходит уже поздно: жалоба, что сайт по утрам «подтормаживает», или алерт мониторинга о высокой нагрузке на диск в 8:50, когда бэкап должен был закончиться в 6:00.
Признаки, что окно уже трещит по швам, стоит ловить раньше жалоб:
- Длительность бэкапа растёт быстрее, чем объём данных. Данные выросли на 20% за квартал, а бэкап стал занимать на 40% дольше — значит, дело не только в объёме, но и в деградации самого процесса (фрагментация, рост числа мелких файлов, конкуренция за диск с продакшеном).
- Окончание бэкапа сдвигается ближе к началу рабочего дня. Если раньше бэкап стабильно завершался к 4 утра, а теперь к 6:30 — до столкновения с реальным трафиком остаются недели, а не «когда-нибудь потом».
- Следующий запуск бэкапа стартует, пока предыдущий ещё не закончился. Это уже не риск, а факт: два процесса бэкапа одновременно борются за один и тот же диск, и оба идут медленнее, чем поодиночке. Если планировщик не проверяет блокировку — это тихо происходит прямо сейчас.
Первый шаг — не гадать по ощущениям, а начать логировать факты. Простая обёртка вокруг существующего бэкапа, которая пишет время старта, длительность и итоговый размер в CSV:
#!/bin/bash
# backup-wrapper.sh — обёртка для сбора метрик поверх существующего скрипта бэкапа
LOGFILE=/var/log/backup-metrics.csv
START=$(date +%s)
/usr/local/bin/run-actual-backup.sh
END=$(date +%s)
DURATION=$(( END - START ))
SIZE_BYTES=$(du -sb /backup/latest | cut -f1)
echo "$(date -Iseconds),${DURATION},${SIZE_BYTES}" >> "$LOGFILE"
Замените вызов в планировщике на эту обёртку, и через 4-8 недель у вас будет достаточно точек, чтобы считать тренд, а не гадать по последним двум запускам — единичные замеры слишком шумные из-за случайных факторов (соседняя нагрузка, фоновые задачи, разница в изменённых данных за конкретную ночь).
Считаем скорость роста данных и текущую скорость бэкапа
Из накопленного лога нужны всего два числа: как быстро растёт объём данных и с какой реальной скоростью бэкап их копирует. Оба считаются по одному и тому же CSV.
Скорость роста данных (g, ГБ/сутки) — это наклон линии по колонке размера за последние 4-8 недель, а не разница между двумя соседними запусками (случайная ночь с массовой загрузкой файлов исказит картину). Быстрый способ прикинуть тренд без специальных инструментов:
# среднесуточный прирост объёма бэкапа за последние N дней
awk -F',' '
NR==1 {first=$3; t1=$1}
{last=$3; t2=$1}
END {print "рост суммарно (байт):", last-first}
' /var/log/backup-metrics.csv
Дальше делите итог на число суток в выборке — получаете g в байтах/сутки, переведите в ГБ. Если под рукой есть Python или таблица — правильнее прогнать через линейную регрессию (numpy.polyfit по колонкам «дата → размер»), это меньше зависит от случайных выбросов на концах интервала.
Эффективная скорость бэкапа (S, ГБ/час) — это фактическая скорость, с которой ваш процесс копирует данные *на этом конкретном сервере с этой конкретной нагрузкой*, а не паспортная скорость диска или сети из спецификации провайдера. Она всегда ниже теоретического максимума — из-за конкуренции с продакшен-нагрузкой, накладных расходов на чтение метаданных при большом числе файлов, сжатия на лету и так далее. Посчитать просто: текущий объём бэкапа делите на его текущую длительность из того же лога.
Важная оговорка: S — не константа. По мере роста числа файлов и фрагментации она может незаметно снижаться сама по себе, независимо от роста объёма данных — тогда длительность бэкапа растёт быстрее, чем можно было бы объяснить одним только приростом байтов. Если видите именно такую картину — это отдельный симптом (часто — миллионы мелких файлов вместо сравнимого объёма в крупных), а не повод пересчитывать g.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПрогноз: сколько часов у вас реально осталось
Дальше — арифметика, которая переводит два измеренных числа в конкретный прогноз.
V0 — текущий объём бэкапа, ГБ
g — среднесуточный прирост объёма, ГБ/сутки (из тренда за 4-8 недель)
S — эффективная скорость бэкапа, ГБ/час (по факту, не по спецификации)
W — длина ночного окна, часов
Текущая длительность бэкапа: T0 = V0 / S
Запас в окне сейчас: M0 = W - T0
Прирост длительности бэкапа в сутки: dT = g / S
Дней до исчерпания окна: N ≈ M0 / dT
Пример на условных числах (именно как иллюстрация метода, не как норматив для вашего сервера): объём бэкапа сейчас 800 ГБ, эффективная скорость 220 ГБ/час, окно — 5 часов. Текущая длительность: 800 / 220 ≈ 3,6 часа. Запас: 5 − 3,6 = 1,4 часа. Если прирост данных составляет 25 ГБ/сутки, прирост длительности в сутки: 25 / 220 ≈ 0,11 часа. Дней до исчерпания окна: 1,4 / 0,11 ≈ 12-13 дней. Дальше уже вопрос не «есть ли проблема», а «что вы делаете за эти 12 дней».
Три оговорки, без которых прогноз вводит в заблуждение:
- Рост редко строго линеен. Сезонные пики, разовая загрузка большого архива, новый модуль с активным логированием — всё это ломает прямую линию. Пересчитывайте прогноз раз в 2-4 недели по свежим данным, а не полагайтесь на разовый расчёт.
Sможет упасть внезапно, а не толькоVвырасти. Смена диска на более медленный тариф, дополнительная нагрузка на тот же сервер, шифрование бэкапа без учёта его CPU-стоимости — всё это снижаетSрезче, чем растёт объём данных.- Окно «лопается» не в одну ночь, а постепенным наползанием на рабочие часы. Диск начинает делить IOPS между бэкапом и продакшеном именно тогда, когда продакшен просыпается — сайт «тормозит по утрам без видимой причины». Похожая картина по симптому, но с другой причиной — разбор чужого бэкапа, забивавшего общий канал: там источником была не собственная инфраструктура, а сосед по узлу.
Если запас M0 уже отрицательный или измеряется минутами — откладывать нечего, переходите к мерам ниже в порядке от «дёшево и быстро» к «дороже, но фундаментально».
Первая мера — уйти от полного бэкапа каждую ночь: инкремент и дифференциал
Самый прямой способ вернуть запас в окно — перестать копировать весь объём данных каждую ночь. Полный бэкап каждый раз читает и пишет весь V0 целиком; инкрементальный или дифференциальный — только то, что изменилось с прошлого раза.
Разница между ними — не техническая тонкость, а конкретный компромисс между временем создания бэкапа и временем восстановления, разобранный подробно в статье про разницу инкрементального, дифференциального и полного бэкапа в цифрах. Коротко для контекста прогноза выше:
| Схема | Что копируется каждую ночь | Эффект на T0 | Цена |
|---|---|---|---|
| Полный каждый раз | Весь объём V0 | Не меняется | Простое восстановление (один файл) |
| Дифференциальный | Всё с момента последнего *полного* | Падает, но растёт к концу цикла | Восстановление: полный + один дифференциальный |
| Инкрементальный | Только с момента *последнего любого* бэкапа | Минимальная и стабильная длительность | Восстановление: вся цепочка по порядку |
Инкрементальная схема даёт наибольший выигрыш по времени в окне, но переносит риск на другую сторону: цепочка восстановления растёт, и повреждение одного звена может обесценить всё, что накоплено после него. На практике это лечится периодической синтетической полной копией (пересборкой «полного» состояния из цепочки без повторного чтения исходных данных) и ограничением длины цепочки — например, полный бэкап раз в неделю, инкременты между ними, а не бесконечная цепочка на месяцы вперёд.
Вторая мера — снапшоты уровня ФС/тома вместо копирования файлов
Файловый бэкап (tar, rsync, копирование через приложение) тратит время на две вещи: обход дерева файлов и собственно копирование байтов. Снапшот на уровне файловой системы или тома убирает первую часть почти полностью — точка состояния фиксируется атомарно и почти мгновенно (LVM, ZFS, снапшот облачного диска у провайдера), а фактическая передача данных наружу может идти уже *после* создания снапшота, вне ночного окна.
Ключевая идея для расчёта из раздела выше: в само окно попадает только момент создания снапшота (секунды — единицы минут), а не весь процесс выгрузки данных на удалённое хранилище. Выгрузку можно растянуть на весь день на отдельном, менее нагруженном канале — тогда T0 для *окна* резко падает, даже если суммарное время «снапшот + передача» не сократилось.
# LVM: мгновенная точка состояния тома без остановки сервиса
lvcreate --size 5G --snapshot --name backup_snap /dev/vg0/data
# дальше: копируете со снапшота уже не торопясь
rsync -a /mnt/backup_snap/ /backup/latest/
# после успешной передачи снапшот можно убрать
lvremove -f /dev/vg0/backup_snap
Для ZFS та же логика ещё естественнее — снапшоты дешевле по накладным расходам, а zfs send/receive позволяет передавать только дельту между снапшотами, что дополнительно снижает объём передачи. Подробный разбор механики снапшотов в ZFS и того, чем они принципиально отличаются от бэкапа (это не взаимозаменяемые вещи — снапшот на том же носителе не спасает при отказе самого носителя), — в статье про снапшоты ZFS против бэкапа.
Есть и обратная сторона: снапшоты не бесплатны для продакшен-нагрузки на копирование-при-записи (copy-on-write) — чем дольше живёт снапшот и чем активнее запись поверх него, тем больше накладных расходов несёт каждая операция записи на исходном томе. Снапшот, который держат живым слишком долго вместо того, чтобы выгрузить и удалить, — частая причина деградации, которая на первый взгляд выглядит как «диск вдруг стал медленнее без причины».
Третья и четвёртая меры — сжатие, распараллеливание и отдельный канал
Когда схема копирования уже оптимальна (инкремент/дифференциал плюс снапшоты), но запаса всё равно не хватает, остаются меры, которые ужимают не объём данных, а время их передачи и обработки.
Сжатие снижает объём, который нужно передать и записать, но стоит CPU. zstd обычно даёт лучший баланс скорость/степень сжатия, чем классический gzip, и поддерживает многопоточность:
tar -cf - /data | zstd -T4 -3 -o /backup/data-$(date +%F).tar.zst
Флаг -3 — умеренная степень сжатия ради скорости; -19 сожмёт плотнее, но на порядок медленнее и съест больше CPU — конкретный баланс для вашего сервера подбирается опытным путём, единой правильной цифры нет. Если бэкап и так конкурирует с продакшеном за CPU, агрессивное сжатие может решить проблему места, но создать проблему процессора — здесь помогает nice, ограничивающий приоритет CPU так же, как ionice ограничивает приоритет ввода-вывода. Подробно о том, почему ionice не всегда работает так, как ожидается, и какие классы (realtime, best-effort, idle) реально разводят бэкап и продакшен по приоритету диска, — в статье про приоритет ввода-вывода и то, как ночной бэкап душит сайт.
Распараллеливание помогает только если узкое место — не сам диск. Если бэкап упирается в последовательное однопоточное чтение при свободных IOPS и CPU — несколько параллельных потоков (по базам данных, по томам, по каталогам) действительно сократят T0. Если же узкое место — общая пропускная способность диска или сети, параллельные потоки просто поделят между собой ту же пропускную способность, и суммарное время не изменится, а нагрузка на продакшен в моменте станет выше. Перед тем как распараллеливать, стоит понять, во что вы упираетесь на самом деле, а не угадывать.
Отдельный канал под бэкап — самая радикальная и самая надёжная мера: снять сам бэкап-трафик с общей сетевой и дисковой подсистемы, которую использует продакшен. Это может быть выделенный сетевой интерфейс до отдельного хранилища, отдельный физический диск под бэкапы вместо общего с рабочими данными, или вовсе отдельный сервер, назначение которого — только принимать и хранить бэкапы, без другой нагрузки. Тогда рост времени бэкапа перестаёт напрямую конкурировать с ресурсами, которые нужны сайту или приложению в момент, когда бэкап всё же перелезает через границу ночного окна.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Что делать в первую очередь, если запас уже почти нулевой?
Быстрее всего помогает переход с полного бэкапа на инкрементальный или дифференциальный — это снижает T0 без изменения инфраструктуры, буквально в рамках существующего скрипта. Снапшоты и отдельный канал дают больший запас, но требуют больше подготовки.
Можно ли просто раздвинуть ночное окно?
Формально да, если у сервиса действительно есть достаточно тихий интервал большей длины. Но это временная мера того же типа, что и «просто взять диск побольше» — она отодвигает момент, когда прогноз снова упрётся в границу, а не убирает саму причину роста длительности бэкапа.
Нужно ли пересчитывать прогноз после каждой меры?
Да, обязательно — и по той же методике из раздела с формулой. После смены схемы бэкапа S и сама природа T0 меняются, старые числа из лога метрик становятся неприменимы, и нужен новый ряд измерений за несколько недель на новой схеме.
А если рост данных резко ускорился и линейный прогноз перестал работать?
Значит, линейная модель для вашего случая больше не годится — переходите на более короткий скользящий период пересчёта (например, тренд за последние 2 недели вместо 8) и относитесь к прогнозу как к ориентиру на ближайший месяц, а не на квартал вперёд.
Сжатие и инкремент можно сочетать?
Да, и обычно так и делают: инкрементальный или дифференциальный бэкап снижает объём, который нужно обработать, а сжатие поверх него дополнительно снижает объём, который нужно передать и записать. Эффекты складываются, но каждый стоит своей доли CPU — считайте суммарную нагрузку, а не только выигрыш по времени.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →