Параллелизировать rsync с помощью GNU Parallel

18

Я использую rsyncскрипт для синхронизации данных на одном хосте с данными на другом хосте. Данные содержат множество небольших файлов, размер которых составляет почти 1,2 ТБ.

Для синхронизации этих файлов я использовал rsyncкоманду следующим образом:

rsync -avzm --stats --human-readable --include-from proj.lst /data/projects REMOTEHOST:/data/

Содержимое proj.lst выглядит следующим образом:

+ proj1
+ proj1/*
+ proj1/*/*
+ proj1/*/*/*.tar
+ proj1/*/*/*.pdf
+ proj2
+ proj2/*
+ proj2/*/*
+ proj2/*/*/*.tar
+ proj2/*/*/*.pdf
...
...
...
- *

В качестве теста я выбрал два из этих проектов (8,5 ГБ данных) и выполнил команду выше. Будучи последовательным процессом, он занимает 14 минут 58 секунд. Таким образом, для 1,2 ТБ данных это займет несколько часов.

Если бы я мог несколько rsyncпараллельных процессов ( с использованием &, xargsили parallel), это позволит сэкономить свое время.

Я попытался с помощью команды ниже parallel(после cdвхода в исходный каталог), и это заняло 12 минут 37 секунд для выполнения:

parallel --will-cite -j 5 rsync -avzm --stats --human-readable {} REMOTEHOST:/data/ ::: .

Это должно было занять в 5 раз меньше времени, но это не так. Я думаю, я где-то не так.

Как я могу запустить несколько rsyncпроцессов, чтобы сократить время выполнения?

Мандар Шинде
источник
1
Вы ограничены пропускной способностью сети? Дисковые iops? Пропускная способность диска?
Оле Танге
Если возможно, мы бы хотели использовать 50% общей пропускной способности. Но распараллеливание множественных rsyncs является нашей первоочередной задачей.
Мандар Шинд
Можете ли вы сообщить нам свои: пропускная способность сети, число дисковых шлейфов, пропускная способность диска и фактически используемая пропускная способность?
Оле Танге
На самом деле, я не знаю о вышеупомянутых параметрах. В настоящее время мы можем пренебречь оптимизацией. Несколько rsyncпараллелей - это основное внимание сейчас.
Мандар Шинд
Нет смысла идти параллельно, если ограничение не в процессоре. Это может / даже усугубит ситуацию (конфликт движений диска на исходном или целевом диске).
ксеноид

Ответы:

16

Следующие шаги сделали эту работу за меня:

  1. Запустите rsync --dry-runпервый, чтобы получить список файлов, которые будут затронуты.
$ rsync -avzm --stats --safe-links --ignore-existing --dry-run \
    --human-readable /data/projects REMOTE-HOST:/data/ > /tmp/transfer.log
  1. Я выдал вывод cat transfer.logto parallel, чтобы запустить 5 rsyncс параллельно, следующим образом:
$ cat /tmp/transfer.log | \
    parallel --will-cite -j 5 rsync -avzm --relative \
      --stats --safe-links --ignore-existing \
      --human-readable {} REMOTE-HOST:/data/ > result.log

Здесь --relativeопция ( ссылка ) гарантировала, что структура каталогов для затронутых файлов, в источнике и в месте назначения, останется неизменной (внутри /data/каталога), поэтому команда должна быть запущена в исходной папке (например, /data/projects).

Мандар Шинде
источник
5
Это сделало бы rsync для файла. Вероятно, было бы более эффективно разделить весь список файлов, используя splitи передать эти имена файлов параллельно. Затем используйте rsync, --files-fromчтобы получить имена файлов из каждого файла и синхронизировать их. rm резервных копий. * split -l 3000 резервных копий. резервные копии ls. * | параллельный --line-buffer --verbose -j 5 rsync --progress -av --files-from {} / ЛОКАЛЬНЫЙ / РОДИТЕЛЬ / ПУТЬ / REMOTE_HOST: REMOTE_PATH /
Сандип Бхаттачарья
1
Как вторая команда rsync обрабатывает строки в result.log, которые не являются файлами? то есть receiving file list ... done created directory /data/.
Майк Д
1
В более новых версиях rsync (3.1.0+) вы можете использовать --info=nameвместо них -v, и вы получите только имена файлов и каталогов. Возможно, вы захотите использовать --protect-args для «внутренней» передачи rsync, если в любых файлах могут быть пробелы или метасимволы оболочки.
Гепард
13

Я лично использую этот простой:

ls -1 | parallel rsync -a {} /destination/directory/

Что полезно, только если у вас есть несколько непустых каталогов, в противном случае вы получите почти все rsyncзавершающие, а последний будет выполнять всю работу в одиночку.

Жюльен Палар
источник
Это прекрасно работает - трудно понять, если он что-то делает, поэтому параллель -v делает его более разговорчивым. Кроме того, от -j 30 к параллельному (то есть до команды rsync) заставляет запускать 30 заданий, а не только одно на ядро ​​ЦП, что является значением по умолчанию.
Кригги
12

Я категорически не рекомендую никому использовать принятый ответ. Лучшее решение - это сканировать каталог верхнего уровня и запускать пропорциональное количество операций rync.

У меня большой том zfs, и моим источником был cifs mount. Оба связаны с 10G, и в некоторых тестах можно насыщать ссылку. Производительность оценивалась с помощью zpool iostat 1.

Исходный диск был смонтирован так:

mount -t cifs -o username=,password= //static_ip/70tb /mnt/Datahoarder_Mount/ -o vers=3.0

Используя один rsyncпроцесс:

rsync -h -v -r -P -t /mnt/Datahoarder_Mount/ /StoragePod

IO метр читает:

StoragePod  30.0T   144T      0  1.61K      0   130M
StoragePod  30.0T   144T      0  1.61K      0   130M
StoragePod  30.0T   144T      0  1.62K      0   130M

Это в синтетических тестах (кристаллический диск), производительность для последовательной записи приближается к 900 МБ / с, что означает, что связь насыщена. 130МБ / с это не очень хорошо, а разница между ожиданием выходных и двух недель.

Итак, я собрал список файлов и попытался снова запустить синхронизацию (у меня 64-ядерный компьютер):

cat /home/misha/Desktop/rsync_logs_syncs/Datahoarder_Mount.log | parallel --will-cite -j 16 rsync -avzm --relative --stats --safe-links --size-only --human-readable {} /StoragePod/ > /home/misha/Desktop/rsync_logs_syncs/Datahoarder_Mount_result.log

и у него была такая же производительность!

StoragePod  29.9T   144T      0  1.63K      0   130M
StoragePod  29.9T   144T      0  1.62K      0   130M
StoragePod  29.9T   144T      0  1.56K      0   129M

В качестве альтернативы я просто запустил rsync для корневых папок:

rsync -h -v -r -P -t /mnt/Datahoarder_Mount/Mikhail/Marcello_zinc_bone /StoragePod/Marcello_zinc_bone
rsync -h -v -r -P -t /mnt/Datahoarder_Mount/Mikhail/fibroblast_growth /StoragePod/fibroblast_growth
rsync -h -v -r -P -t /mnt/Datahoarder_Mount/Mikhail/QDIC /StoragePod/QDIC
rsync -h -v -r -P -t /mnt/Datahoarder_Mount/Mikhail/sexy_dps_cell /StoragePod/sexy_dps_cell

Это фактически повысило производительность:

StoragePod  30.1T   144T     13  3.66K   112K   343M
StoragePod  30.1T   144T     24  5.11K   184K   469M
StoragePod  30.1T   144T     25  4.30K   196K   373M

В заключение, как вспомнил @Sandip Bhattacharya, напишите небольшой скрипт, чтобы получить каталоги и параллельно с ним. Также можно передать список файлов в rsync. Но не создавайте новые экземпляры для каждого файла.

Михаил
источник
5

Проверенный способ выполнения параллельной rsync: http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Parallelizing-rsync.

rsync - отличный инструмент, но иногда он не заполняет доступную полосу пропускания. Это часто проблема при копировании нескольких больших файлов по высокоскоростным соединениям.

Следующее запустит один rsync для большого файла в src-dir для dest-dir на сервере fooserver:

cd src-dir; find . -type f -size +100000 | \
parallel -v ssh fooserver mkdir -p /dest-dir/{//}\; \
  rsync -s -Havessh {} fooserver:/dest-dir/{} 

Созданные каталоги могут иметь неправильные разрешения, а файлы меньшего размера не передаются. Чтобы исправить это, запустите rsync в последний раз:

rsync -Havessh src-dir/ fooserver:/dest-dir/ 

Если вы не можете отправить данные, но вам нужно их извлечь, и файлы называются digits.png (например, 000000.png), вы можете сделать следующее:

seq -w 0 99 | parallel rsync -Havessh fooserver:src/*{}.png destdir/
Оле Танге
источник
Любая другая альтернатива, чтобы избежать find?
Мандар Шинд
1
Ограничить -maxdepth нахождения.
Оле Танге
Если я использую --dry-runопцию в rsync, у меня будет список файлов, которые будут переданы. Могу ли я предоставить этот список файлов parallel, чтобы распараллелить процесс?
Мандар Шинд
1
кошачьи файлы | параллельный -v ssh fooserver mkdir -p / dest-dir / {//} \; rsync -s -Havessh {} fooserver: / dest-dir / {}
Оле Танге
Можете ли вы объяснить mkdir -p /dest-dir/{//}\;часть? Особенно {//}это немного смущает.
Мандар Шинд
1

Для многоцелевой синхронизации я использую

parallel rsync -avi /path/to/source ::: host1: host2: host3:

Подсказка: все соединения SSH устанавливаются с открытыми ключами в ~/.ssh/authorized_keys

ingopingo
источник
1

Я всегда гуглю на параллельную rsync, так как всегда забываю полную команду, но ни одно решение не сработало для меня так, как я хотел - оно включает несколько шагов или требует установки parallel. В итоге я использовал эту однострочную синхронизацию для нескольких папок:

find dir/ -type d|xargs -P 5 -I % sh -c 'rsync -a --delete --bwlimit=50000 $(echo dir/%/ host:/dir/%/)'

-P 5 это количество процессов, которые вы хотите порождать - используйте 0 для неограниченного (очевидно, не рекомендуется).

--bwlimit чтобы избежать использования всей полосы пропускания.

-I %аргумент предоставлен find (каталог найден в dir/)

$(echo dir/%/ host:/dir/%/)- печатает каталоги источника и назначения, которые rsync читает как аргументы. % заменяется на xargsимя каталога, найденное с помощью find.

Предположим, у меня есть две директории /home: dir1и dir2. Я бегу find /home -type d|xargs -P 5 -I % sh -c 'rsync -a --delete --bwlimit=50000 $(echo /home/%/ host:/home/%/)'. Поэтому команда rsync будет работать как два процесса (два процесса, потому что /homeимеет два каталога) со следующими аргументами:

rsync -a --delete --bwlimit=50000 /home/dir1/ host:/home/dir1/
rsync -a --delete --bwlimit=50000 /home/dir1/ host:/home/dir1/
Sebastjanas
источник