web-dev-qa-db-fra.com

Parallelise rsync en utilisant GNU Parallel

J'utilise un script rsync pour synchroniser les données d'un hôte avec les données d'un autre hôte. Les données contiennent de nombreux fichiers de petite taille qui contribuent à près de 1,2 To.

Afin de synchroniser ces fichiers, j'utilise la commande rsync comme suit:

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

Le contenu de proj.lst est le suivant:

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

Comme test, j'ai récupéré deux de ces projets (8,5 Go de données) et j'ai exécuté la commande ci-dessus. Étant un processus séquentiel, il nécessite 14 minutes 58 secondes pour terminer. Ainsi, pour 1,2 To de données, cela prendrait plusieurs heures.

Si je pouvais plusieurs processus rsync en parallèle (en utilisant &, xargs ou parallel), cela me ferait gagner du temps.

J'ai essayé avec la commande ci-dessous avec parallel (après cding dans le répertoire source) et cela a pris 12 minutes 37 secondes pour s'exécuter:

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

Cela aurait dû prendre 5 fois moins de temps, mais ce ne fut pas le cas. Je pense que je me trompe quelque part.

Comment puis-je exécuter plusieurs processus rsync afin de réduire le temps d'exécution?

20
Mandar Shinde

Les étapes suivantes ont fait le travail pour moi:

  1. Exécutez le rsync --dry-run d'abord afin d'obtenir la liste des fichiers qui seraient affectés.
$ rsync -avzm --stats --safe-links --ignore-existing --dry-run \
    --human-readable /data/projects REMOTE-Host:/data/ > /tmp/transfer.log
  1. J'ai alimenté la sortie de cat transfer.log à parallel pour exécuter 5 rsyncs en parallèle, comme suit:
$ cat /tmp/transfer.log | \
    parallel --will-cite -j 5 rsync -avzm --relative \
      --stats --safe-links --ignore-existing \
      --human-readable {} REMOTE-Host:/data/ > result.log

Ici, --relative option ( link ) garantit que la structure du répertoire des fichiers affectés, à la source et à la destination, reste la même (à l'intérieur de /data/), la commande doit donc être exécutée dans le dossier source (par exemple, /data/projects).

19
Mandar Shinde

Je découragerais fortement quiconque d'utiliser la réponse acceptée, une meilleure solution consiste à explorer le répertoire de niveau supérieur et à lancer un nombre proportionnel d'opérations de rync.

J'ai un grand volume zfs et ma source était une monture cifs. Les deux sont liés à 10G, et dans certains cas-tests peuvent saturer le lien. Les performances ont été évaluées à l'aide de zpool iostat 1.

Le lecteur source a été monté comme suit:

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

En utilisant un seul processus rsync:

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

le compteur io indique:

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

Ceci dans les benchmarks synthétiques (disque cristal), les performances d'écriture séquentielle approchent 900 Mo/s ce qui signifie que le lien est saturé. 130 Mo/s n'est pas très bon, et la différence entre attendre un week-end et deux semaines.

J'ai donc construit la liste des fichiers et essayé de relancer la synchronisation (j'ai une machine à 64 cœurs):

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

et il avait les mêmes performances!

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

Comme alternative, j'ai simplement exécuté rsync sur les dossiers racine:

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

Cela a en fait amélioré les performances:

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

En conclusion, comme l'a évoqué @Sandip Bhattacharya, écrivez un petit script pour obtenir les répertoires et parallèlement. Vous pouvez également transmettre une liste de fichiers à rsync. Mais ne créez pas de nouvelles instances pour chaque fichier.

15
Mikhail

J'utilise personnellement ce simple:

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

Ce qui n'est utile que lorsque vous avez plus de quelques répertoires non vides, sinon vous finirez par avoir presque tous les rsync se terminant et le dernier faisant tout le travail seul.

15
Julien Palard

Une façon testée de faire la rsync parallélisée est: http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Parallelizing-rsync

rsync est un excellent outil, mais parfois il ne remplira pas la bande passante disponible. C'est souvent un problème lors de la copie de plusieurs gros fichiers sur des connexions à haut débit.

Ce qui suit démarrera un rsync par gros fichier dans src-dir vers dest-dir sur le serveur fooserver:

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

Les répertoires créés peuvent se retrouver avec des autorisations incorrectes et les fichiers plus petits ne sont pas transférés. Pour corriger ceux qui exécutent rsync une dernière fois:

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

Si vous ne parvenez pas à envoyer des données, mais que vous devez les extraire et que les fichiers s'appellent digits.png (par exemple 000000.png), vous pourrez peut-être:

seq -w 0 99 | parallel rsync -Havessh fooserver:src/*{}.png destdir/
5
Ole Tange

Je recherche toujours Google pour la synchronisation parallèle car j'oublie toujours la commande complète, mais aucune solution n'a fonctionné pour moi comme je le souhaitais - soit elle comprend plusieurs étapes ou doit installer parallel. J'ai fini par utiliser ce one-liner pour synchroniser plusieurs dossiers:

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

-P 5 Est la quantité de processus que vous souhaitez générer - utilisez 0 pour illimité (évidemment non recommandé).

--bwlimit Pour éviter d'utiliser toute la bande passante.

Argument -I % Fourni par find (répertoire trouvé dans dir/)

$(echo dir/%/ Host:/dir/%/) - affiche les répertoires source et de destination qui sont lus par rsync comme arguments. % est remplacé par xargs avec le nom du répertoire trouvé par find.

Supposons que j'ai deux répertoires dans /home: dir1 Et dir2. J'exécute find /home -type d|xargs -P 5 -I % sh -c 'rsync -a --delete --bwlimit=50000 $(echo /home/%/ Host:/home/%/)'. La commande rsync s'exécutera donc en deux processus (deux processus car /home A deux répertoires) avec les arguments suivants:

rsync -a --delete --bwlimit=50000 /home/dir1/ Host:/home/dir1/
rsync -a --delete --bwlimit=50000 /home/dir1/ Host:/home/dir1/
1
Sebastjanas

Pour les synchronisations multi-destinations, j'utilise

parallel rsync -avi /path/to/source ::: Host1: Host2: Host3:

Astuce: toutes les connexions ssh sont établies avec des clés publiques dans ~/.ssh/authorized_keys

1
ingopingo