Parallelise rsync à l'aide de GNU Parallel

18

J'utilise un rsyncscript 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'ai utilisé la rsynccommande 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 rsyncprocessus en parallèle (en utilisant &, xargsou 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 rsyncprocessus afin de réduire le temps d'exécution?

Mandar Shinde
la source
1
Êtes-vous limité par la bande passante du réseau? Disque iops? Bande passante du disque?
Ole Tange
Si possible, nous voudrions utiliser 50% de la bande passante totale. Mais, paralléliser plusieurs rsyncs est notre première priorité.
Mandar Shinde
Pouvez-vous nous faire connaître votre: bande passante réseau, iops de disque, bande passante de disque et bande passante réellement utilisée?
Ole Tange
En fait, je ne connais pas les paramètres ci-dessus. Pour l'instant, on peut négliger la partie optimisation. Plusieurs rsyncs en parallèle est désormais l'objectif principal.
Mandar Shinde
Inutile d'aller en parallèle si la limitation n'est pas le CPU. Cela peut / va même aggraver les choses (mouvements de bras de disque conflictuels sur le disque source ou cible).
xenoid

Réponses:

16

Les étapes suivantes ont fait le travail pour moi:

  1. Exécutez le rsync --dry-runpremier 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.logto parallelpour 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, l' --relativeoption ( lien ) garantit que la structure du répertoire des fichiers affectés, à la source et à la destination, reste la même ( /data/répertoire interne ), de sorte que la commande doit être exécutée dans le dossier source (par exemple, /data/projects).

Mandar Shinde
la source
5
Cela ferait une rsync par fichier. Il serait probablement plus efficace de diviser toute la liste de fichiers en utilisant splitet de mettre ces noms de fichiers en parallèle. Utilisez ensuite rsync --files-frompour extraire les noms de fichiers de chaque fichier et les synchroniser. sauvegardes rm. * split -l 3000 backup.list sauvegardes. ls sauvegardes. * | parallel --line-buffer --verbose -j 5 rsync --progress -av --files-from {} / LOCAL / PARENT / PATH / REMOTE_HOST: REMOTE_PATH /
Sandip Bhattacharya
1
Comment la deuxième commande rsync gère-t-elle les lignes de result.log qui ne sont pas des fichiers? ie receiving file list ... done created directory /data/.
Mike D
1
Sur les versions plus récentes de rsync (3.1.0+), vous pouvez utiliser --info=nameà la place de -v, et vous n'obtiendrez que les noms des fichiers et des répertoires. Vous pouvez également utiliser --protect-args pour le rsync de transfert «interne» si des fichiers peuvent contenir des espaces ou des métacaractères shell.
Cheetah
13

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 rsyncterminaisons et le dernier fera tout le travail seul.

Julien Palard
la source
Cela fonctionne très bien - difficile de savoir si cela fait quelque chose, donc un -v en parallèle le rend plus bavard. De plus, -j 30 en parallèle (c'est-à-dire avant la commande rsync) lui fait exécuter 30 tâches, pas seulement une par cœur de processeur, ce qui est la valeur par défaut.
Criggie
12

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. La performance a été évaluée en utilisant 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 rsyncprocessus:

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 core):

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.

Mikhail
la source
5

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/
Ole Tange
la source
Une autre alternative pour éviter find?
Mandar Shinde
1
Limitez la -maxdepth de find.
Ole Tange
Si j'utilise l' --dry-runoption dans rsync, j'aurais une liste de fichiers qui seraient transférés. Puis-je fournir cette liste de fichiers parallelafin de paralléliser le processus?
Mandar Shinde
1
fichiers de chat | parallel -v ssh fooserver mkdir -p / dest-dir / {//} \; rsync -s -Havessh {} fooserver: / dest-dir / {}
Ole Tange
Pouvez-vous expliquer la mkdir -p /dest-dir/{//}\;partie? Surtout, la {//}chose est un peu déroutante.
Mandar Shinde
1

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

ingopingo
la source
1

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 être installée 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.

-I %argument 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 le xargsnom du répertoire trouvé par find.

Supposons que j'ai deux répertoires dans /home: dir1et dir2. Je cours 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 comme deux processus (deux processus car /homea 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/
Sebastjanas
la source