Вопрос или проблема
Предположим, у меня есть большое дерево директорий с большими файлами на диске A. Я делаю резервную копию этого дерева с помощью rsync -a --delete /A /B
. Все хорошо. Между резервными копиями добавляются некоторые файлы, некоторые переименовываются, в общем, всё как обычно.
Интересно то, что A регулярно реорганизуется: файлы перемещаются (переименовываются, меняются директории или оба варианта). Поэтому rsync
в конечном итоге удаляет файлы на B, чтобы снова скопировать их с A, и с большими файлами через сеть это занимает вечность.
Существует ли какой-нибудь параметр rsync, который я мог бы использовать? Я перечитал список параметров и не смог ничего найти, что могло бы подойти, что-то связанное с --size-only
мне было бы вполне приемлемо (малый риск коллизий).
Я думаю, что решение, скорее всего, заключается в том, чтобы использовать сценарий, который проверяет размер файла + контрольную сумму и перемещает файлы на B перед запуском rsync, но это тоже не так просто. Есть идеи?
Существует два основных подхода:
- параметр
--fuzzy
, вместе с--compare-dest
для указания дополнительных директорий для поиска эталонных файлов. - директория, полная жестких ссылок на большие файлы, которая передается первой и инициирует обнаружение жестких ссылок.
Первый подход не требует изменений в дереве файлов, которое вы передаете, но требует от вас составления списка директорий, из которых файлы обычно копируются, я не уверен, насколько хорошо алгоритм будет работать, если у вас длинный список эталонных директорий.
Более надежный подход требует специальной директории, которая передается первой и содержит жесткие ссылки на все файлы, которые стоит оптимизировать. Я бы сделал что-то вроде
find files -type f -size +2G | (while read f; do ln -f "$f" _links/`sha256sum "$f" | cut -d\ -f1`; done)
а затем передал _links
перед files
— вот так.
Ни один из этих вариантов не является особенно хорошим.
Когда файлы перемещаются в пределах одной и той же файловой системы, они обычно сохраняют тот же номер инода. Вы можете, таким образом, создать список пар инода и имени файла на диске A сразу после резервной копии, а затем сформировать новый список перед новой резервной копией. Сравнив два списка, вы можете создать список команд перемещения, сопоставив иноды, где имена файлов различаются. Примените этот список перемещений к диску B перед выполнением резервного копирования. Вам, конечно, может понадобиться сначала создать новые директории. Вот объясняющий сценарий:
#!/bin/bash
list(){
find A -type f -printf "%i %P\n" | # инод и путь не включая A
sort
}
list >after
#... несколько дней спустя, перед резервной копией:
list >before
join -j 1 -o 1.2 2.2 after before | # один и тот же инод, старое и новое имя файла
awk '{if($1!=$2)printf "mv %s %s\n",$1,$2}' >cmds
(cd A; find . -type d -print0) |
(cd B; xargs -0 mkdir -p )
(cd B; sh -x ) <cmds
# теперь делаем резервную копию, и в конце:
mv before after
Это явно только для простых случаев. Он не обрабатывает директории или имена файлов с пробелами и специальными символами, и оставляет старые имена директорий. Возможно, его можно применить только к аккуратно названным огромным файлам (find ... -size +10M ...
).
Ответ или решение
Оптимизация rsync при перемещении крупных файлов
Когда вы осуществляете бэкап большой структуры каталогов с помощью rsync
, переименование и перемещение файлов может значительно увеличить время, необходимое для выполнения операций. Это происходит из-за того, что rsync
будет удалять файлы на целевом диске (/B
) и копировать их заново из исходного (/A
). Однако существует несколько стратегий, которые могут помочь оптимизировать этот процесс и минимизировать объем передаваемых данных.
1. Использование параметров rsync
Первый вариант – это использование параметров rsync
, таких как --delete
, --size-only
, и --compare-dest
. К примеру:
-
--size-only
: Этот параметр позволитrsync
игнорировать разницу в содержимом файлов и учитывать только их размеры. Это может быть полезно, если вероятность изменения содержимого файла невелика, но следует помнить, что это не всегда надежно из-за возможности изменения файла с одинаковым размером. -
--compare-dest
: Этот параметр может быть использован вместе с--fuzzy
для поиска файлов, которые могли быть перемещены или изменены. Это требует предварительного создания списка каталогов, где ваши файлы могут находиться, однако он не требует изменений в вашей структуре каталогов.
2. Использование жёстких ссылок
Другим подходом является создание каталога с жёсткими ссылками на большие файлы, которые нужно оптимизировать. Вы можете перенести файлы, используя метод, который будет выявлять уже существующие файлы и делать ссылки на них, а не копировать. Пример команды на Bash:
find files -type f -size +2G | while read f; do ln -f "$f" _links/$(sha256sum "$f" | cut -d\ -f1); done
Затем передайте каталог _links
перед основной передачей файлов. Это гарантирует, что уже существующие файлы будут связаны. Это требует создания специального каталога и предварительной работы.
3. Сравнение инодов для определения перемещённых файлов
В этом подходе вы можете использовать иноды для выявления перемещённых файлов. Этот метод подразумевает создание списка пар инодов и соответствующих файлов на источнике. После этого, перед следующим бэкапом вы создаёте новый список и сравниваете его со старым:
#!/bin/bash
list(){
find A -type f -printf "%i %P\n" | sort
}
list >after
# ... через несколько дней, перед бэкапом:
list >before
join -j 1 -o 1.2 2.2 after before | awk '{if($1!=$2)printf "mv %s %s\n",$1,$2}' >cmds
(cd A; find . -type d -print0) | (cd B; xargs -0 mkdir -p)
(cd B; sh -x ) <cmds
# Теперь производим бэкап
mv before after
Этот скрипт позволяет переименовывать файлы на диске B
, если их иноды совпадают, минимизируя необходимость в повторном копировании.
Заключение
Правильная оптимизация передачи данных с помощью rsync
может существенно ускорить процесс создания резервных копий при работе с большими файлами и частыми изменениями структуры каталогов. Использование таких методов, как сравнение инодов, использование жёстких ссылок и правильная настройка опций rsync
, позволяет уменьшить объем передаваемой информации и сэкономить время. Таким образом, вы сможете добиться значительной эффективности в процессе резервного копирования вашего файла.