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 cd
ing 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?
Les étapes suivantes ont fait le travail pour moi:
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
cat transfer.log
à parallel
pour exécuter 5 rsync
s 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
).
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.
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.
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/
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/
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