Как организовать синхронизацию файлов для собственного CDN?
Потребовалось раздавать среднего объема статику(250-500TB/месяц). Реализовали свой "cdn"в виде N-количества серверов Nginx с синхронизацией данных по Rsync. Нам очень важно, чтобы при обновлениях контент быстро разлетался по серверам, поэтому реализовали в виде master-slave, где master - это центральный сервер куда заливаются данные, работает в пассивном режиме: на каждом slave работает rsync по крону и забирает данные.
Плюсы из этой схемы следующие:
- если мастер упадет, то на каждом сервере есть копия всех данных
- мастер сервер ничего не знает о slave'ах, легко добавлять новый сервер в группу.
- для инициации обновления серверов достаточно просто залить новый контент (не требуется дополнительного активного действия)
Минус получается следующий:
Хотя, объем статики не большой (5-6гб), но 10 серверов, каждую минуту дергая мастер-сервер rsync'ом - очень неплохо его грузят.
Есть желание сохранить все плюсы и как-то разобраться с минусом, я так понимаю RSYNC вынужден каждый раз на каждый запрос сканировать файлы и это что-то неплохо ест CPU, хотя 99% времени файлы не меняются(обновления происходят 2-3 раза в день).
Как можно переработать схему? Каким ПО воспользоваться?
Master-slave структура под нагрузкой часто подразумевает, что на мастер идут запросы только на запись-обновление, а мастер пушит изменения на слейвы
Можно воспользоваться встроенным функционалом nginx - настроить проксирование с кешированием
Те запрос поступает на слейв, если у него в кеше есть контент, то он отдает, если нет, то идет на мастер, забирает контент, кеширует и отдает клиенту
В таком случае, тебе не нужно ничего копировать, просто добавить его имя в список серверов для статики
Возможно, стоит изменить схему распространения с "слейвы тянут с мастера" на "мастер пушит слейвам", чтобы уменьшить число сканирований изменений файлов (оно будет производится единожды, в момент обновления данных мастера), а так же использоваться пакетный режим rsync serverfault.com/questions/137119/rsync-to-multiple...
Если url при обновлении меняются (если новый контент только добавляется и старый удаляется) или есть возможность их менять (при обновлении), то можно попробовать nginx + proxy_pass + кеширование nginx.
Ну или если url не меняются то же самое, но сброс кеша у обновленных файлов скриптом по списку.
К сожалению URL не всегда меняется, CDN используется для нескольких проектов и в одном, очень старом ПО настроено на простую заливку по ФТП и не просто этот процесс изменить.
Рассматривали вариант с proxy_pass, но:
1) нужно дублировать мастер (для надежности)
2) появляется необходимость пробежаться по всем серверам и сбросить кэш
Скинуть кеш нужно только у изменившихся файлов, на всех cdn, это да.
Но я не вижу в этом проблему, или как часто и сколько обновляется файлов?
Мастер дублировать, в принципе, можно тем же способом, на нем в первую очередь обновить кеш у измененных файлов, а затем разослать запросы на cdn.
Примерно по такой схеме - joxi.ru/DrlOkeGC4643RA.png
Где зеленое - заливка по ftp, синие - запросы proxy_pass, красное - запросы к nginx для сброса кеша.
странно, даже при наличии 50к файлов rsync проц у меня не грузит при поиске, да и отрабатывает очень быстро... возможно проблема в медленной дисковой подсистеме на сервере?
просто предлагаю очередной вариант, а никак не решение вашей проблемы)
если файлов очень много и никак не избавиться от текущей схемы, то есть такой вариант:
делаем на сервере спец файл (пусть данные хранятся в нем в виде таблицы) - в нем номер залитого файла и путь к нему. для примера:
...
9 /var/www/backup/2016-05-15.tar
10 /etc/postfix/main.cf
и еще один файл который содержит номер последнего обновления.
клиент подключается, и сверяет свой номер с номером последнего обновления на сервере, для примера на клиенте последний залитый файл: 8.
8<10, поэтому качаем файлы 9 и 10 с сервера, запрашиваем их путь (awk в помощь) и копируем обычным scp)
думаю мысль понятна?