Синхронизация очень больших структур папок

14

У нас есть структура папок в нашей интрасети, которая содержит около 800 000 файлов, разделенных на около 4000 папок. Нам нужно синхронизировать это с небольшим кластером машин в наших DMZ. Глубина конструкции очень мала (она никогда не превышает двух уровней глубины).

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

Очевидно, что из-за того, что очень немногие файлы меняются на регулярной основе, мы можем значительно выиграть от инкрементного копирования. Мы попробовали Rsync, но это может занять от восьми до двенадцати часов, только чтобы завершить операцию «создание списка файлов». Понятно, что мы быстро перерастаем то, на что способен rsync (12-часовой период слишком длинный).

Мы использовали другой инструмент под названием RepliWeb для синхронизации структур, и он может выполнять поэтапную передачу примерно за 45 минут. Однако, кажется, что мы превысили его предел, он начал видеть, что файлы отображаются как удаленные, когда их нет (возможно, какая-то внутренняя структура памяти исчерпана, мы не уверены).

Кто-нибудь еще сталкивался с масштабным проектом синхронизации такого рода? Есть ли что-то, предназначенное для обработки массивных файловых структур, подобных этой, для синхронизации?

MightyE
источник
Вы пытались разделить работу на несколько экземпляров rsync, запущенных одновременно? У меня не очень хорошая картина структуры каталогов, но вы можете разделить ее по имени каталога или имени файла.
Сцепление
Мы думали об этом, но с такой плоской структурой трудно найти хорошие разделительные линии, по которым можно разделить работу. Это усложняется тем фактом, что папки по большей части имеют очень одинаковые имена (существует соглашение об именах, при котором большинство папок начинаются с одинакового начального набора из 6 символов).
MightyE
Вы когда-нибудь находили хорошее решение, Дейв? Я рассматриваю lsyncd для каталога с 65535 вложенными каталогами, каждый из которых может иметь 65 ^ 16 файлов.
Майк Дин,
1
@MikeDiehn Я так и не нашел инструмент, которым был полностью доволен. Мы получили этот проприетарный инструмент RepliWeb для исправления ошибки, когда они видели файлы как удаленные файлы, которых не было, это была переполненная внутренняя структура. Я оставил эту работу много лет назад, я полагаю, они все еще используют это. Для ваших целей, если ваши каталоги разумно распределены, вы можете использовать что-то вроде решения Райана. Он не заметит удаления верхнего уровня, но 65535 подкаталогов подсказывает мне, что у вас их, вероятно, нет.
MightyE

Ответы:

9

Если вы можете доверять меткам времени последней модификации файловой системы, вы можете ускорить процесс, комбинируя Rsync с утилитой UNIX / Linux 'find'. 'find' может собрать список всех файлов, которые показывают время последнего изменения за прошедший день, и затем направить ТОЛЬКО этот сокращенный список файлов / каталогов в Rsync. Это намного быстрее, чем Rsync сравнивает метаданные каждого файла в отправителе с удаленным сервером.

Короче говоря, следующая команда выполнит Rsync ТОЛЬКО в списке файлов и каталогов, которые изменились за последние 24 часа: (Rsync НЕ будет проверять любые другие файлы / каталоги.)

find /local/data/path/ -mindepth 1 -ctime -0 -print0 | xargs -0 -n 1 -I {} -- rsync -a {} remote.host:/remote/data/path/.

Если вы не знакомы с командой 'find', она рекурсивно просматривает определенное поддерево каталога, ища файлы и / или каталоги, которые соответствуют любым заданным вами критериям. Например, эта команда:

find . -name '\.svn' -type d -ctime -0 -print

начнется в текущем каталоге (".") и будет проходить по всем подкаталогам в поисках:

  • любые каталоги ("-type d"),
  • с именем ".svn" ("-name '.svn'"),
  • с метаданными, измененными за последние 24 часа ("-ctime -0").

Он выводит полное имя пути ("-print") чего-либо, соответствующего этим критериям, в стандартный вывод. Параметры '-name', '-type' и '-ctime' называются «тестами», а опция «-print» называется «действием». Страница man для 'find' содержит полный список тестов и действий.

Если вы хотите быть действительно умным, вы можете использовать тест '-cnewer' команды 'find' вместо '-ctime', чтобы сделать этот процесс более отказоустойчивым и гибким. '-cnewer' проверяет, были ли метаданные каждого файла / каталога в дереве модифицированы более недавно, чем какой-либо справочный файл. Используйте «touch», чтобы создать справочный файл СЛЕДУЮЩЕГО запуска в начале каждого запуска, прямо перед «find ... | Команда rsync ... 'выполняется. Вот основная реализация:

#!/bin/sh
curr_ref_file=`ls /var/run/last_rsync_run.*`
next_ref_file="/var/run/last_rsync_run.$RANDOM"
touch $next_ref_file
find /local/data/path/ -mindepth 1 -cnewer $curr_ref_file -print0 | xargs -0 -n 1 -I {} -- rsync -a {} remote.host:/remote/data/path/.
rm -f $curr_ref_file

Этот скрипт автоматически знает, когда он был запущен в последний раз, и он передает только файлы, измененные с момента последнего запуска. Хотя это более сложно, оно защищает вас от ситуаций, когда вы могли пропустить выполнение задания более 24 часов из-за простоя или другой ошибки.

Райан Б. Линч
источник
Это очень умное решение! Я думаю, что вы имеете в виду touch $next_ref_fileв конце? Тем не менее, мы не можем справиться с удаленными путями (даже эти статические архивные отчеты со временем становятся достаточно старыми, чтобы их можно было архивировать и удалять). Это не могло бы быть выставочным ограничителем все же.
MightyE
Я обнаружил, что даже find . -ctime 0эта структура каталогов работает довольно медленно (все еще ожидая завершения, чтобы сообщить время). Это на самом деле меня немного обескураживает, потому что кажется, что это может быть довольно низкоуровневая операция, которая, вероятно, устанавливает планку для максимально быстрой, которую мы могли бы ожидать, чтобы эта работа была выполнена. Это может быть случай, когда дисковый ввод-вывод является ограничивающим фактором.
MightyE
Что касается этого сценария, да, я допустил ошибку. Я имел в виду запустить 'touch' для 'next_ref_file' (НЕ 'curr_ref_file') прямо перед запуском 'find ... | rsync ... 'команда. (Я исправлю свой ответ.)
Райан Б. Линч
3
Что касается медленной команды 'find': какую файловую систему вы используете? Если вы используете Ext3, вы можете рассмотреть два твика FS: 1) Запустите 'tune2fs -O dir_index <DEVICE_NODE>', чтобы включить функцию Ext3 'dir_index', чтобы ускорить доступ к директориям с большим количеством файлов. 2) Запустите 'mount -o remount, noatime, nodiratime', чтобы отключить обновления времени доступа, что в целом ускоряет чтение. 'dumpe2fs -h <DEVICE_NODE> | grep dir_index 'говорит вам, если dir_index уже включен (на некоторых дистрибутивах это по умолчанию), и' mount | grep <DEVICE_NODE> 'сообщает вам об обновлениях времени доступа.
Райан Б. Линч
К сожалению, это NTFS - Windows 2003 Server, использующий Cygwin для команды find. Я запомню эти параметры настройки (отличный совет) для ext3 на случай, если мы когда-нибудь столкнемся с чем-то похожим на одном из наших кластеров Debian.
MightyE
7

Попробуйте unison , он был специально разработан для решения этой проблемы, сохраняя списки изменений (создавая список файлов) локально для каждого сервера, ускоряя время для вычисления дельты и уменьшая количество, которое впоследствии отправляется по проводам.

Дейв Чейни
источник
Я даю Унисону попытку. Сейчас он работает около 2 часов на этапе «Поиск изменений», и, основываясь на файлах, над которыми он в данный момент работает, похоже, что он сделан примерно наполовину (так что, может быть, всего 4 часа до начала передачи). Похоже, что это будет лучше, чем rsync, но все еще за пределами желаемого операционного окна.
MightyE
2
При первом создании индекса с обеих сторон время перестройки аналогично rsync, поскольку он должен хэшировать каждый файл. Как только это будет сделано, Unison использует время последнего изменения каталога, чтобы определить, когда файл был изменен, и ему нужно только просканировать этот файл на наличие изменений.
Дейв Чейни
К сожалению, я стал жертвой чрезмерно усердного администратора операций, который принудительно завершил мой сеанс до того, как был завершен процесс создания каталога (мы ограничиваем количество одновременных входов в систему на производственных серверах). Я потерял прогресс, достигнутый в создании первоначального каталога, поэтому я должен начать все сначала. Я дам вам знать, как это происходит.
MightyE
Теперь требуется около 2 часов, чтобы начальный каталог был создан для поиска изменений. Я очень удивлен, сколько оперативной памяти Unison использует для этого. Для нашей коллекции файлов исходный сервер использует 635M, а удаленный клиент использует 366M. Синхронизация нескольких машин в кластере была бы довольно трудоемкой задачей, особенно для исходного сервера!
MightyE
1
Вы можете структурировать свои данные таким образом, чтобы можно было легко идентифицировать данные, которые изменились за последнее время? Т.е. хранить его в формате год / месяц / день / ...?
Дейв Чейни
2

Если вы используете ключ -z на rsync, попробуйте запустить без него. По какой-то причине я видел, как это ускоряет даже первоначальное перечисление файлов.

Крис Торп
источник
Мы пробовали с и без флага -z. Похоже, что это не повлияло на продолжительность выполнения «списка файлов сборки».
MightyE
2

Удаление команды -z из команды rsync, которая не является сжатием, сделало «список принимаемых файлов» намного быстрее, и нам пришлось перенести около 500 ГБ. Прежде чем это заняло день с ключом -z.

ryand32
источник