Nous devons transférer 15TB
Des données d'un serveur à un autre aussi rapidement que possible. Nous utilisons actuellement rsync
mais nous n'obtenons qu'une vitesse d'environ 150Mb/s
, Lorsque notre réseau est capable de 900+Mb/s
(Testé avec iperf
). J'ai fait des tests sur les disques, le réseau, etc., et je me suis dit que rsync ne transfère qu'un fichier à la fois, ce qui provoque le ralentissement.
J'ai trouvé un script pour exécuter un rsync différent pour chaque dossier dans une arborescence de répertoires (ce qui vous permet de limiter à x nombre), mais je ne parviens pas à le faire fonctionner, il ne lance toujours qu'un rsync à la fois.
J'ai trouvé le script
ici (copié ci-dessous).
Notre arborescence de répertoires ressemble à ceci:
/main
- /files
- /1
- 343
- 123.wav
- 76.wav
- 772
- 122.wav
- 55
- 555.wav
- 324.wav
- 1209.wav
- 43
- 999.wav
- 111.wav
- 222.wav
- /2
- 346
- 9993.wav
- 4242
- 827.wav
- /3
- 2545
- 76.wav
- 199.wav
- 183.wav
- 23
- 33.wav
- 876.wav
- 4256
- 998.wav
- 1665.wav
- 332.wav
- 112.wav
- 5584.wav
Donc, ce que j'aimerais, c’est créer un rsync pour chacun des répertoires dans/main/files, jusqu’à un maximum de 5 à la fois. Donc, dans ce cas, 3 rsyncs seraient exécutés, pour /main/files/1
, /main/files/2
Et /main/files/3
.
J'ai essayé avec ça comme ça, mais ça ne marche que 1 rsync à la fois pour le dossier /main/files/2
:
#!/bin/bash
# Define source, target, maxdepth and cd to source
source="/main/files"
target="/main/filesTest"
depth=1
cd "${source}"
# Set the maximum number of concurrent rsync threads
maxthreads=5
# How long to wait before checking the number of rsync threads again
sleeptime=5
# Find all folders in the source directory within the maxdepth level
find . -maxdepth ${depth} -type d | while read dir
do
# Make sure to ignore the parent folder
if [ `echo "${dir}" | awk -F'/' '{print NF}'` -gt ${depth} ]
then
# Strip leading dot slash
subfolder=$(echo "${dir}" | sed 's@^\./@@g')
if [ ! -d "${target}/${subfolder}" ]
then
# Create destination folder and set ownership and permissions to match source
mkdir -p "${target}/${subfolder}"
chown --reference="${source}/${subfolder}" "${target}/${subfolder}"
chmod --reference="${source}/${subfolder}" "${target}/${subfolder}"
fi
# Make sure the number of rsync threads running is below the threshold
while [ `ps -ef | grep -c [r]sync` -gt ${maxthreads} ]
do
echo "Sleeping ${sleeptime} seconds"
sleep ${sleeptime}
done
# Run rsync in background for the current subfolder and move one to the next one
Nohup rsync -a "${source}/${subfolder}/" "${target}/${subfolder}/" </dev/null >/dev/null 2>&1 &
fi
done
# Find all files above the maxdepth level and rsync them as well
find . -maxdepth ${depth} -type f -print0 | rsync -a --files-from=- --from0 ./ "${target}/"
Cela semble plus simple:
ls /srv/mail | parallel -v -j8 rsync -raz --progress {} myserver.com:/srv/mail/{}
rsync
transfère les fichiers aussi vite que possible sur le réseau. Par exemple, essayez de l'utiliser pour copier un fichier volumineux qui n'existe pas du tout sur la destination. Cette vitesse est la vitesse maximale que rsync peut transférer des données. Comparez-le avec la vitesse de scp
(par exemple). rsync
est encore plus lent lors du transfert brut lorsque le fichier de destination existe, car les deux parties doivent avoir une conversation à double sens sur les parties du fichier qui ont été modifiées, mais se rentabilisent en identifiant les données inutiles. être transféré.
Une méthode plus simple pour exécuter rsync
en parallèle consisterait à utiliser parallel
. La commande ci-dessous pourrait exécuter jusqu'à 5 rsync
s en parallèle, chacun copiant un répertoire. Sachez que le goulot d’étranglement n’est peut-être pas lié à votre réseau, mais que la vitesse de vos processeurs et de vos disques, ainsi que l’exécution de tâches en parallèle, les ralentissent, pas plus rapidement.
run_rsync() {
# e.g. copies /main/files/blah to /main/filesTest/blah
rsync -av "$1" "/main/filesTest/${1#/main/files/}"
}
export -f run_rsync
parallel -j5 run_rsync ::: /main/files/*
Vous pouvez utiliser xargs
qui prend en charge l'exécution de plusieurs processus à la fois. Pour votre cas ce sera:
ls -1 /main/files | xargs -I {} -P 5 -n 1 rsync -avh /main/files/{} /main/filesTest/
Il existe un certain nombre d’outils et d’approches alternatives pour le faire énumérés sur le Web. Par exemple:
J'ai développé un paquet python appelé: parallel_sync
https://pythonhosted.org/parallel_sync/pages/examples.html
Voici un exemple de code pour l'utiliser:
from parallel_sync import rsync
creds = {'user': 'myusername', 'key':'~/.ssh/id_rsa', 'Host':'192.168.16.31'}
rsync.upload('/tmp/local_dir', '/tmp/remote_dir', creds=creds)
le parallélisme par défaut est 10; vous pouvez l'augmenter:
from parallel_sync import rsync
creds = {'user': 'myusername', 'key':'~/.ssh/id_rsa', 'Host':'192.168.16.31'}
rsync.upload('/tmp/local_dir', '/tmp/remote_dir', creds=creds, parallelism=20)
toutefois, notez que ssh a généralement la valeur 10 pour MaxSessions par défaut. Par conséquent, pour l'augmenter au-delà de 10, vous devrez modifier vos paramètres ssh.
Le plus simple que j'ai trouvé consiste à utiliser des tâches en arrière-plan dans le shell:
for d in /main/files/*; do
rsync -a "$d" remote:/main/files/ &
done
Attention, cela ne limite pas le nombre d'emplois! Si vous êtes lié au réseau, ce n'est pas vraiment un problème, mais si vous attendez pour tourner Rust), cela écrasera le disque.
Tu pourrais ajouter
while [ $(jobs | wc -l | xargs) -gt 10 ]; do sleep 1; done
dans la boucle pour une forme primitive de contrôle des travaux.