Мой сервер выполняет несколько заданий cron в полночь. Каждое задание создает резервную копию чего-либо, создавая архив и сжимая его с помощью xz
.
поскольку xz
это свинья ЦП и памяти, я добавил случайную задержку к каждому заданию, чтобы они «не затирали» друг друга. Но время от времени это случается и сильно нагружает сервер.
Предположения:
/etc/cron.d/
, и случайной задержки перед запуском задания обычно достаточно.tar ... | pv --rate-limit ... | xz ...
- но, хотя это снижает нагрузку на задание, оно также замедляет каждое задание и, таким образом, увеличивает вероятность одновременного выполнения нескольких заданий (что при сложении может потреблять 100% ЦП)Возможное решение - для каждого задания создать временный файл, сигнализирующий о его занятости, а затем удалить его. Проблема в том, что если задание обнаруживает этот файл, что оно делает? Спать? Как долго? Я мог бы заставить его спать на случайное время, используя at
, но если что-то пойдет не так с моими сценариями резервного копирования, у меня может возникнуть огромная очередь заданий, конкурирующих друг с другом. Еще одна головная боль обслуживания.
Итак, как обычно решают эту проблему? По сути, это простой способ планировать связанные задания cron, не позволяя им затирать друг друга и без необходимости точной настройки времени запуска.
Использовать операторы оболочки, например, чтобы запустить command1
затем command2
в полночь, независимо от результата первого, используйте:
0 0 * * * command1 ; command2
В качестве альтернативы вы можете запустить command2
только если command1
успешно завершается (возвращается с нулевым статусом выхода):
0 0 * * * command1 && command2
Последнее, возможно, более полезно, когда сбой command1
может указывать на основную ошибку, препятствующую успеху command2
.
Случайное распределение времени начала помогает избежать пиковых часов, и это легко сделать с помощью Ansible. Но на самом деле не гарантирует, что ресурсы будут доступны для поддержки нескольких одновременных заданий сжатия. Существует несколько методов создания резервных копий с низким уровнем воздействия, рассмотреть некоторые или все из них.
Запустите свой список команд с помощью программы, которая регулируется в зависимости от ЦП. Например, GNU parallel --limit 100%
будет работать только в том случае, если средняя загрузка ниже количества процессоров.
Каждое задание пытается получить одну из небольшого количества блокировок. Например, с flock
из util-linux, Python или Perl. Кажется простым, но поддержание некоторых из них будет раздражать. Я считаю команду оболочки со встроенным управлением заданиями более надежной, например GNU parallel.
Оцените свой алгоритм сжатия. zstd современный и быстрый, для чуть больше памяти.
Распределите задания резервного копирования на большее количество часов. Подумайте, приемлемо ли время с 00:00 до 03:00 для ваших требований к производительности и резервному копированию.
Добавьте CPU. Его размер может быть дорогостоящим для максимальной производительности, но он позволяет использовать больше потоков сжатия.
Полностью выгружайте резервные копии на другой хост. Сделайте массив хранения или облачный снимок дисков. Представить другому хозяину. Резервное копирование оттуда.
Взгляните на ответ @ JohnMahowald, чтобы получить отличный список вариантов, включая умную обработку разногласий.
Я решил вместо того, чтобы добавлять задания резервного копирования в /etc/cron.d
, Я добавлю их в собственный каталог cron, например /etc/cron.backupjobs/
.
Затем я добавлю "главную" работу в /etc/cron.d/
который работает в /etc/cron.backupjobs/
последовательно.