Ответ 1
Это кажется более простым:
ls /srv/mail | parallel -v -j8 rsync -raz --progress {} myserver.com:/srv/mail/{}
Нам нужно как можно быстрее передавать 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}/"
Это кажется более простым:
ls /srv/mail | parallel -v -j8 rsync -raz --progress {} myserver.com:/srv/mail/{}
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/*
Существует целый ряд альтернативных инструментов и подходов для этого, перечисленных в Интернете. Например:
Вы можете использовать xargs
который поддерживает запуск множества процессов за раз. Для вашего дела это будет:
ls -1 /main/files | xargs -I {} -P 5 -n 1 rsync -avh /main/files/{} /main/filesTest/
Я разработал пакет 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.
Самое простое, что я нашел, это использование фоновых заданий в оболочке:
for d in /main/files/*; do
rsync -a "$d" remote:/main/files/ &
done
Остерегайтесь, это не ограничивает количество рабочих мест! Если вы подключены к сети, это не является проблемой, но если вы ожидаете появления ржавчины, это приведет к поломке диска.
Вы можете добавить
while [ $(jobs | wc -l | xargs) -gt 10 ]; do sleep 1; done
внутри цикла для примитивной формы контроля работы.