Paralelo a rsync usando GNU Paralelo

18

He estado usando un rsyncscript para sincronizar datos en un host con los datos en otro host. Los datos tienen numerosos archivos de pequeño tamaño que contribuyen a casi 1.2TB.

Para sincronizar esos archivos, he estado usando el rsynccomando de la siguiente manera:

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

Los contenidos de proj.lst son los siguientes:

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

Como prueba, tomé dos de esos proyectos (8,5 GB de datos) y ejecuté el comando anterior. Al ser un proceso secuencial, tiene 14 minutos y 58 segundos para completar. Entonces, para 1.2TB de datos tomaría varias horas.

Si pudiera hacer varios rsyncprocesos en paralelo (usando &, xargso parallel), me ahorraría tiempo.

Intenté con el siguiente comando con parallel(después cdde ir al directorio de origen) y tardé 12 minutos y 37 segundos en ejecutarse:

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

Esto debería haber tomado 5 veces menos tiempo, pero no fue así. Creo que me estoy equivocando en alguna parte.

¿Cómo puedo ejecutar múltiples rsyncprocesos para reducir el tiempo de ejecución?

Mandar Shinde
fuente
1
¿Está limitado por el ancho de banda de la red? Iops de disco? Ancho de banda de disco?
Ole Tange
Si es posible, nos gustaría utilizar el 50% del ancho de banda total. Pero, paralelizar múltiples rsyncs es nuestra primera prioridad.
Mandar Shinde
¿Puede decirnos su: ancho de banda de red, iops de disco, ancho de banda de disco y el ancho de banda realmente utilizado?
Ole Tange
De hecho, no sé sobre los parámetros anteriores. Por el momento, podemos descuidar la parte de optimización. Múltiples rsyncs en paralelo es el foco principal ahora.
Mandar Shinde
No tiene sentido ir en paralelo si la limitación no es la CPU. Incluso puede empeorar las cosas (movimientos conflictivos del brazo del disco en el disco de origen o de destino).
xenoid

Respuestas:

16

Los siguientes pasos hicieron el trabajo por mí:

  1. Ejecute el rsync --dry-runprimero para obtener la lista de archivos que se verían afectados.
$ rsync -avzm --stats --safe-links --ignore-existing --dry-run \
    --human-readable /data/projects REMOTE-HOST:/data/ > /tmp/transfer.log
  1. Alimenté la salida de cat transfer.loga parallelpara ejecutar 5 rsyncs en paralelo, de la siguiente manera:
$ cat /tmp/transfer.log | \
    parallel --will-cite -j 5 rsync -avzm --relative \
      --stats --safe-links --ignore-existing \
      --human-readable {} REMOTE-HOST:/data/ > result.log

Aquí, la --relativeopción ( enlace ) aseguró que la estructura de directorios para los archivos afectados, en el origen y el destino, permanezca igual (dentro del /data/directorio), por lo que el comando debe ejecutarse en la carpeta de origen (por ejemplo /data/projects).

Mandar Shinde
fuente
55
Eso haría un rsync por archivo. Probablemente sería más eficiente dividir toda la lista de archivos usando splity alimentar esos nombres de archivos en paralelo. Luego use rsync --files-frompara obtener los nombres de archivo de cada archivo y sincronizarlos. rm backups. * split -l 3000 backup.list backups. ls copias de seguridad. * | paralelo --line-buffer --verbose -j 5 rsync --progress -av --files-from {} / LOCAL / PARENT / PATH / REMOTE_HOST: REMOTE_PATH /
Sandip Bhattacharya
1
¿Cómo maneja el segundo comando rsync las líneas en result.log que no son archivos? es decir receiving file list ... done created directory /data/.
Mike D
1
En las versiones más recientes de rsync (3.1.0+), puede usar --info=nameen lugar de -v, y obtendrá solo los nombres de los archivos y directorios. Es posible que también desee usar --protect-args en la transferencia interna 'rsync' si algún archivo puede contener espacios o metacaracteres de shell.
Cheetah
13

Yo personalmente uso este sencillo:

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

Lo cual solo es útil cuando tienes más de unos pocos directorios no casi vacíos, de lo contrario terminarás teniendo casi cada rsyncterminación y el último haciendo todo el trabajo solo.

Julien Palard
fuente
Esto funciona muy bien, es difícil saber si está haciendo algo, por lo que un -v a paralelo lo hace más hablador. Además, -j 30 a paralelo (es decir, antes del comando rsync) hace que ejecute 30 trabajos, no solo uno por núcleo de CPU, que es el valor predeterminado.
Criggie
12

Desalentaría a cualquiera de usar la respuesta aceptada, una mejor solución es rastrear el directorio de nivel superior e iniciar un número proporcional de operaciones de sincronización.

Tengo un gran volumen zfs y mi fuente era un montaje cifs. Ambos están vinculados con 10G, y en algunos puntos de referencia pueden saturar el enlace. El rendimiento se evaluó usando zpool iostat 1.

La unidad fuente se montó como:

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

Usando un solo rsyncproceso:

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

el medidor io lee:

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

Esto en pruebas sintéticas (disco de cristal), el rendimiento para la escritura secuencial se acerca a 900 MB / s, lo que significa que el enlace está saturado. 130 MB / s no es muy bueno, y la diferencia entre esperar un fin de semana y dos semanas.

Entonces, construí la lista de archivos e intenté ejecutar la sincronización nuevamente (tengo una máquina de 64 núcleos):

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

y tuvo el mismo rendimiento!

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

Como alternativa, simplemente ejecuté rsync en las carpetas raíz:

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

Esto realmente aumentó el rendimiento:

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 conclusión, como mencionó @Sandip Bhattacharya, escriba un pequeño script para obtener los directorios y paralelos. Alternativamente, pase una lista de archivos a rsync. Pero no cree nuevas instancias para cada archivo.

Mikhail
fuente
5

Una forma probada de hacer el rsync paralelo es: http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Parallelizing-rsync

rsync es una gran herramienta, pero a veces no llena el ancho de banda disponible. Esto suele ser un problema al copiar varios archivos grandes a través de conexiones de alta velocidad.

Lo siguiente iniciará un rsync por archivo grande en src-dir a dest-dir en el servidor de búsqueda:

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

Los directorios creados pueden terminar con permisos incorrectos y no se transfieren archivos más pequeños. Para arreglar esos ejecute rsync por última vez:

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

Si no puede insertar datos, pero necesita extraerlos y los archivos se llaman digits.png (por ejemplo, 000000.png), puede hacer lo siguiente:

seq -w 0 99 | parallel rsync -Havessh fooserver:src/*{}.png destdir/
Ole Tange
fuente
¿Alguna otra alternativa para evitar find?
Mandar Shinde
1
Limite la profundidad máxima de find.
Ole Tange
Si uso la --dry-runopción en rsync, tendría una lista de archivos que serían transferidos. ¿Puedo proporcionar esa lista de archivos parallelpara paralelizar el proceso?
Mandar Shinde
1
archivos de gato | paralelo -v ssh fooserver mkdir -p / dest-dir / {//} \; rsync -s -Havessh {} servidor de acceso: / dest-dir / {}
Ole Tange
¿Puedes por favor explicar la mkdir -p /dest-dir/{//}\;parte? Especialmente la {//}cosa es un poco confusa.
Mandar Shinde
1

Para sincronizaciones de múltiples destinos, estoy usando

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

Sugerencia: todas las conexiones ssh se establecen con claves públicas en ~/.ssh/authorized_keys

ingopingo
fuente
1

Siempre busco en Google para rsync paralelo, ya que siempre olvido el comando completo, pero ninguna solución me funcionó como quería, ya sea que incluye varios pasos o necesita instalarse parallel. Terminé usando este one-liner para sincronizar múltiples carpetas:

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

-P 5 es la cantidad de procesos que desea generar: use 0 para ilimitado (obviamente no recomendado).

--bwlimit para evitar usar todo el ancho de banda.

-I %argumento proporcionado por find (directorio encontrado en dir/)

$(echo dir/%/ host:/dir/%/)- imprime directorios de origen y destino que rsync lee como argumentos. % es reemplazado por el xargsnombre del directorio encontrado por find.

Supongamos que tengo dos directorios en /home: dir1y dir2. Corro find /home -type d|xargs -P 5 -I % sh -c 'rsync -a --delete --bwlimit=50000 $(echo /home/%/ host:/home/%/)'. Entonces, el comando rsync se ejecutará como dos procesos (dos procesos porque /hometiene dos directorios) con los siguientes argumentos:

rsync -a --delete --bwlimit=50000 /home/dir1/ host:/home/dir1/
rsync -a --delete --bwlimit=50000 /home/dir1/ host:/home/dir1/
Sebastjanas
fuente