Бэкап большого количества мелких файлов

Рано или поздно настройкой резервного копирования рабочих файлов озадачивается любой уважающий себя современный IT специалист. После ряда опечаток/ошибок программистов нашлось время для этого и у меня. Специфика веб-приложения такова, что рабочий каталог занимает более 50ГБ на жестких дисках, включая в себя около 900 тысяч мелких файлов (картинки, превьюшки, …). Поэтому в лоб решить задачу с помощью tar и аналогов не вышло. Да и хотелось бы иметь некоторую вариативность хранимых данных, а в случае с полным бэкапом реализация требовала больших затрат на хранение по сути одинаковых данных с небольшими изменениями. Плюс неплохо было бы дублировать копии на удаленном сервере бэкапов для снижения риска потери критической информации в результате краха железа. После скрупулезного анализа поисковых выдач и отбрасывания заведомо неподходящих мне методов, остановился на паре вариантов, навязываемых чаще всего в комментариях к самописным shell-велосипедам энтузиастов.

rdiff-backup

rdiff-backup показался с виду более подходящим и удобным. Написанный на python, он хранит данные инкрементально, позволяя получить состояние файла или директории в любой момент времени (в обозримом прошлом, учитывая время хранения снимков). Гибкое управление из консоли дает полную свободу действий и предоставляет полный контроль за ситуацией. Автоматическое создание бэкапов требует добавления в планировщик пары команд (вторая для подчистки старых снимков, не несущих какой-либо ценности в силу давности изменений). Но тестирование показало, что утилита весьма прожорлива и справляется с моей задачей крайне неохотно. Дело в том, что ежедневно изменяется небольшой объем данных (300МБ), но изменения затрагивают около 30 тысяч файлов. На выявление измененных файлов, судя по всему, тратится бОльшая часть времени работы программы. После часа наблюдений на увеличившийся до неприличных 20% iowait во время очередного запуска скрипта было принято решение попробовать другой софт и сравнить их между собой.

rsnapshot

rsnapshot, написанный на Perl, базируется на rsync. В рабочей директории программы (назовём так место, куда складываются бэкапы), создается ряд папок с индексом, который при каждом следующем запуске программы увеличивается до указанного в конфигурации значения. Затем устаревшая копия удаляется. Если пройти в любую из созданных папок, то внутри можно найти полную копию резервируемых данных. На это указывает и общий размер папки (при просмотре стандартными средствами Midnight Commander, например) — он равен сумме всех папок. На самом деле это не так. Программа создает жесткие ссылки между одинаковыми данными в пределах рабочего каталога. Таким образом, последняя актуальная копия является самой «тяжелой», а размер всех остальных составляет разницу в измененных данных.

Тестирование

Так, как оба варианта используют приблизительно одинаковый размер для хранения, пришло время проверить скорость выполнения заданий по созданию резервных копий. Для тестов была взята случайная папка проекта размером 11ГБ, содержащая 593 подкаталога разной степени вложенности и 230911 файлов. Размер файлов плавает от 4 до 800КБ, как указано выше, это в графический материал. Обе утилиты тестировались поочередно, внешние факторы практически полностью отсутствовали (нет других пользователей, нагрузки и тяжелых процессов). С помощью утилиты time было подсчитано время выполнения каждого из тестовых заданий, а также для сравнения копирование всего каталога средствами cp:

Первый бэкап — полное копирование в место бэкапа 11090МБ

real user sys
cp 6m30.885s 0m1.068s 0m24.554s
rsnapshot 7m53.879s 1m57.299s 1m22.441s
rdiff-backup 10m50.314s 3m26.073s 1m0.928s

Повторный запуск (в папке не было изменений)

real user sys
rsnapshot 0m10.129s 0m4.936s 0m6.708s
rdiff-backup 1m3.969s 1m0.616s 0m2.048s

Внутри каталога одна случайная папка дублируется (общий размер увеличивается до 13267МБ)

real user sys
rsnapshot 0m31.175s 0m22.001s 0m17.365s
rdiff-backup 27m53.517s 1m58.819s 0m19.005s

Повторный запуск после увеличения размера каталога (с последнего выполнения изменений нет)

real user sys
rsnapshot 0m11.477s 0m5.748s 0m7.368s
rdiff-backup 1m16.366s 1m13.713s 0m1.912s

Удаляем сдублированную папку, уменьшая размер каталога до первоначального

real user sys
rsnapshot 0m13.885s 0m6.388s 0m9.077s
rdiff-backup 52m55.794s 2m1.560s 0m21.941s

Контрольный повторный запуск без внесения изменений

real user sys
rsnapshot 0m11.250s 0m5.132s 0m7.068s
rdiff-backup 1m2.380s 1m0.088s 0m1.792s

Итоги

Как видно из таблиц сравнительного тестирования, rdiff-backup тяжело переваривает изменение большого количества мелких файлов, следовательно, рентабельнее использовать rsnapshot, дабы не тратить бОльшую часть времени работы сервера на пустое ковыряние в файловой системе. Возможно кому-то будет полезным увидеть результат тестирования и сэкономить затраченное мною время на поиск оптимального для описанных в статье случаев резервного копирования файлов.