Ускорить rsync с одновременными/параллельными передачами файлов?

Нам нужно как можно быстрее передавать 15 15TB данных с одного сервера на другой. В настоящее время мы используем rsync но мы получаем скорость около 150Mb/s, когда наша сеть способна 900+Mb/s (протестирована с помощью iperf). Я тестировал диски, сеть и т.д., И понял, что rsync переносит только один файл за раз, что вызывает замедление.

Я нашел сценарий для запуска другого rsync для каждой папки в дереве каталогов (позволяя вам ограничить число x), но я не могу заставить его работать, он по-прежнему просто запускает один rsync за раз.

Я нашел script здесь (скопирован ниже).

Дерево нашей каталогов выглядит так:

/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

Поэтому я хотел бы создать rsync для каждого из каталогов в /main/files, максимум до 5, за раз. Таким образом, в этом случае будет запущено 3 rsyncs для /main/files/1, /main/files/2 и /main/files/3.

Я пробовал с этим так, но он просто запускает 1 rsync за один раз для папки /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 '[email protected]^\./@@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}/"

Ответы

Ответ 1

Это кажется более простым:

ls /srv/mail | parallel -v -j8 rsync -raz --progress {} myserver.com:/srv/mail/{}

Ответ 2

rsync передает файлы так быстро, как может по сети. Например, попробуйте использовать его для копирования одного большого файла, который вообще не существует в пункте назначения. Эта скорость - это максимальная скорость rsync, которая может передавать данные. Сравните его со скоростью scp (например). rsync еще медленнее при необработанном переносе, когда файл назначения существует, поскольку обе стороны должны иметь двухсторонний чат о том, какие части файла изменены, но оплачивает сам себя, идентифицируя данные, которые не нужно переносить.

Более простой способ параллельного запуска rsync - использовать parallel. Приведенная ниже команда запускает до 5 rsync параллельно, каждый из которых копирует один каталог. Имейте в виду, что узким местом может быть не ваша сеть, но скорость ваших процессоров и дисков и параллельная работа с ними просто делают их все медленнее, а не быстрее.

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/*

Ответ 3

Существует целый ряд альтернативных инструментов и подходов для этого, перечисленных в Интернете. Например:

  • NCSA Блог имеет описание с помощью xargs и find распараллелить Rsync без необходимости устанавливать новое программное обеспечение для большинства * NIX систем.

  • И parsync предоставляет многофункциональную оболочку Perl для параллельного rsync.

Ответ 4

Вы можете использовать xargs который поддерживает запуск множества процессов за раз. Для вашего дела это будет:

ls -1 /main/files | xargs -I {} -P 5 -n 1 rsync -avh /main/files/{} /main/filesTest/

Ответ 5

Я разработал пакет python под названием: parallel_sync

https://pythonhosted.org/parallel_sync/pages/examples.html

Вот пример кода, как его использовать:

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)

параллелизм по умолчанию - 10; вы можете увеличить его:

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)

однако обратите внимание, что в ssh обычно устанавливается MaxSessions по умолчанию 10, чтобы увеличить его до 10, вам придется изменить свои настройки ssh.

Ответ 6

Самое простое, что я нашел, это использование фоновых заданий в оболочке:

for d in /main/files/*; do
    rsync -a "$d" remote:/main/files/ &
done

Остерегайтесь, это не ограничивает количество рабочих мест! Если вы подключены к сети, это не является проблемой, но если вы ожидаете появления ржавчины, это приведет к поломке диска.

Вы можете добавить

while [ $(jobs | wc -l | xargs) -gt 10 ]; do sleep 1; done

внутри цикла для примитивной формы контроля работы.