Распараллеливание rsync

30

Я просто переехал и обнаружил после некоторой проб и ошибок, что где-то между моим домом и моим удаленным сервером происходит некоторое регулирование ... но регулирование не очень разумно. Это только душит отдельные связи. Поэтому, если я скопирую один файл размером 1 ГБ, он будет работать со скоростью 150 кбит / с. Но если я инициализирую 10 копий, каждая из них будет работать со скоростью 150 кбит / с (т. Е. Я получу гораздо более высокую совокупную пропускную способность по нескольким соединениям).

Я использую rsync довольно часто для синхронизации некоторых больших наборов данных с работы на дом (к счастью, в виде множества файлов). Есть ли способ сообщить rsync о загрузке, используя несколько соединений? Теоретически это должно быть возможно, поскольку, насколько я могу судить, rsync сначала делает проход, чтобы определить необходимые изменения, а затем выполняет фактическую передачу. Бонусные баллы, если есть волшебный способ сказать rsync нарезать отдельные файлы на N частей, а затем соединить их вместе. Я считаю, что CuteFTP на самом деле достаточно умен, чтобы справиться с этим.

stuyguy
источник

Ответы:

13

У меня просто была похожая проблема, связанная с переносом нескольких ТБ с одного NAS на другой NAS без возможности резервного копирования / восстановления, которая позволила бы мне просто передать 1 набор другому.

Поэтому я написал этот скрипт для запуска 1 rsync для каждого каталога, с которым он сталкивается. Это зависит от возможности составления списка исходных каталогов (будьте осторожны, избегая ARG 3), но я думаю, что вы могли бы установить этот этап с помощью нерекурсивного rsync, который просто копировал файлы и каталоги на соответствующий уровень.

Он также определяет, сколько Rsync нужно запустить, основываясь на количестве процессоров, но вы можете настроить его.

Еще одна возможная опция, которая приходит на ум: запустить rsync в режиме --list-only.

Это даст вам все файлы, которые нужно обновить. Затем запустите 1 rsync для каждого файла в вашем списке, если вы использовали xargs для управления количеством выполняемых rsyncs, это может быть очень элегантно. На самом деле, вероятно, более элегантное решение, чем мой маленький сценарий здесь ...

#! /bin/bash
SRC_DIR=$1
DEST_DIR=$2
LIST=$3
CPU_CNT=`cat /proc/cpuinfo|grep processor |wc -l`
#  pseudo random heuristic
let JOB_CNT=CPU_CNT*4
[ -z "$LIST" ] && LIST="-tPavW --exclude .snapshot --exclude hourly.?"
echo "rsyncing From=$SRC_DIR To=$DEST_DIR DIR_LIST=$LIST"
mkdir -p /{OLD,NEW}_NAS/home
[ -z "$RSYNC_OPTS" ] && RSYNC_OPTS="-tPavW --delete-during --exclude .snapshot --exclude hourly.?"
cd $SRC_DIR
echo $LIST|xargs -n1 echo|xargs -n1 -P $JOB_CNT -I% rsync ${RSYNC_OPTS} ${SRC_DIR}/%/ ${DEST_DIR}/%/
kkron
источник
2
Это работает - вы можете внести множество улучшений в его работу, но концепция использования xargs для распараллеливания вашего приложения довольно нова.
MattPark
6

У GNU Parallel есть решение

Я переместил 15 ТБ через 1 Гбит / с, и это может насытить канал 1 Гбит / с.

Следующее запустит один rsync для большого файла в src-dir для dest-dir на сервере fooserver:

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

Созданные каталоги могут иметь неправильные разрешения, а файлы меньшего размера не передаются. Чтобы исправить это, запустите rsync в последний раз:

rsync -Havessh src-dir/ fooserver:/dest-dir/
Оле Танге
источник
1
Не могли бы вы вставить в свой ответ раздел «ПРИМЕР: Распараллеливание rsync». На случай, если в будущем связь прекратится.
пикобит
3

Да. Такая особенность существует.

Существует утилита pssh, которая предоставляет описанную функциональность.

Этот пакет предоставляет параллельные версии инструментов openssh. Включено в дистрибутив:

  • Параллельный ssh ​​(pssh)
  • Параллельный scp (pscp)
  • Параллельный rsync (prsync)
  • Параллельная нукэ (pnuke)
  • Параллельный хлеб (пслурп)

Я не уверен, насколько легко это настроить, но это может помочь!

Тим Белава
источник
26
Утилиты pssh используются для распределения команд по нескольким серверам, а не для выполнения одной и той же команды несколько раз на одном сервере. В частности, prsync поддерживает отправку файла только с вашего локального компьютера на несколько внешних компьютеров. Он не поддерживает загрузку удаленного файла с несколькими подключениями.
Дерек Дамер
1
Учитывая комментарий @DerekDahmer, постер этого ответа может захотеть отозвать его?
mc0e
3

Я не могу комментировать, поэтому я добавил новый ответ с немного лучшим кодом, чем предыдущий (хороший и умный) код.

Проверьте rsyncстроку, потому что она содержит необязательный ioniceтвик.

#!/bin/bash
start_time=$(date +%s.%N)
# Transfer files in parallel using rsync (simple script)
# MAXCONN: maximum number "rsync" processes running at the same time:
MAXCONN=6
# Source and destination base paths. (not need to end with "/")
SRC_BASE=/home/user/public_html/images
DST_BASE=user@hostname.domain.local:/home/user/public_html/images
RSYNC_OPTS="-ah --partial"
# Main loop:
for FULLDIR in $SRC_BASE/*; do
    NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
    while [ $NUMRSYNC -ge $MAXCONN ]; do
        NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
        sleep 1
    done
    DIR=`basename $FULLDIR`
    echo "Start: " $DIR
    ionice -c2 -n5 rsync $RSYNC_OPTS $SRC_BASE/${DIR}/ $DST_BASE/${DIR}/ &
    # rsync $RSYNC_OPTS $SRC_BASE/${DIR}/ $DST_BASE/${DIR}/ &
    sleep 5
done

execution_time=$(echo "$(date +%s.%N) - $start" | bc)
printf "Done. Execution time: %.6f seconds\n" $execution_time
Widmo
источник
2

Похоже, кто-то написал эту утилиту для вас. Это разбивает передачу на параллельные куски. Это лучшая реализация, чем версия "параллельного большого файла", перечисленная в разделе GNU Parallel:

https://gist.github.com/rcoup/5358786

Кроме того, lftp может распараллелить передачу файлов через ftp, ftps, http, https, hftp, fish, sftp. Часто у lftp есть некоторые преимущества, потому что управление разрешениями, ограниченным доступом и т. Д. Для rsync может быть сложной задачей.

Эрик Аронесты
источник
Несмотря на то, что это работает, оно может быстро вызвать значительную фрагментацию диска, поскольку вы не просто используете несколько подключений для загрузки одного и того же файла.
bparker
1

Нет, такой функции не существует. Вы можете разделить синхронизацию на несколько вызовов, rsyncесли вы действительно этого хотите.

Я бы посоветовал вам найти все, что делает это ограничение скорости, и серьезно поговорить с тем, кто его поддерживает / управляет.

Дэвид Шварц
источник
4
Часто эти ограничения взяты у некоторых интернет-провайдеров, например Comcast. Удачи в разумном разговоре с ними.
Джеймс Мур
1

Я хотел перенести несколько каталогов (со многими файлами) одновременно, поэтому я создал этот небольшой скрипт:

#!/bin/bash
# Transfer files in parallel using rsync (simple script)
# MAXCONN: maximum number "rsync" processes running at the same time:
MAXCONN=10
# Source and destination base paths. (not need to end with "/")
SRC_BASE=/home/sites
DST_BASE=user@example.com:/var/www
RSYNC_OPTS="--stats -ilrtpog"
# Main loop:
for FULLDIR in $SRC_BASE/*/; do
    NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
    while [ $NUMRSYNC -ge $MAXCONN ]; do
        NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
        sleep 10
    done
    DIR=`basename $FULLDIR`
    rsync $RSYNC_OPTS $SRC_BASE/${DIR}/ $DST_BASE/${DIR}/ & 
    sleep 1 
done
echo "Done."

Я сделал этот скрипт довольно быстро, поэтому, пожалуйста, пересмотрите его и протестируйте перед использованием в производственной среде.

Лепе
источник
0

Я создал следующий скрипт для параллельной загрузки множества папок с изображениями. Вы запускаете его сначала с целью синхронизации, а затем со всеми именами папок для копирования.

#!/bin/sh

dest="$1"
shift

if [ "$dest" = "" ]; then
    echo "USAGE: $0 TARGET:/foo/bar <dir1> [dir2] [dir3]"
    exit 1
fi

RCol='\x1B[0m' # Text Reset
BYel='\x1B[1;33m';

for i in "$@"; do
    prefix=`printf "$BYel%50s:$RCol" "$i"`
    echo "$prefix * Starting $i"
    echo "$prefix -> syncing '$i/' to '$dest/$i/'"
    (rsync -rv "$i/" "$dest/$i/") 2>&1 | sed "s/^/$prefix /g" &
    sleep 0.5
done

echo "* Waiting for all to complete"
wait

Он добавляет префикс имени папки в желтом цвете ко всем выводам консоли rsync, чтобы он выглядел красиво.

Konrad
источник
-1

Aria2 - хорошая клиентская программа для загрузки данных с использованием множества соединений с множества зеркал. Он не поддерживает SFTP. Итак, я установил FTP-сервер - vsftpd . Мое 3g соединение работает на полную мощность с 5 подключениями к FTP-серверу.

puchu
источник
1
Не могли бы вы остановиться на этом, чтобы сделать ваш ответ полезным?
Tog