Проектирования высоко нагруженных систем. Часть 2

4.95 (2)

Одну проблему решили, но не до конца. Перед нами стоит вопрос, как хранить служебную информацию к этим файлам, а также данные, которые приходят с этими файлами. Сразу напрашивается база данных. Но не все так просто. Возникает проблема поиска и скорости доступа к хранимой информации. Хватит ли нам количества открытых соединений? Ведь это одно из узких мест, которые возникают при решении. Также не совсем удобно и не рационально бегать по миллионам записей и брать оттуда информацию или каждый раз блокировать таблицу, чтобы обновить данные.

В своих проектах мы зачастую работаем с базой данных MySql. У нее свои плюсы и минусы. Данная база данных является свободной, имеет большое комьюнити, всегда можно получить ответ на интересующий вопрос или же найти решения проблемы, которая может возникнуть при работе. Поэтому все дальнейшие рассуждения будут ориентированы на базу данных MySql.

На практике применяют различные технологии по разделению информации. Одна из техник масштабирования - шардинг. Его суть в том, что мы разделяем базы данных таким образом, чтобы потом вынести часть данных на отдельный сервер. Различают горизонтальный и вертикальный шардинг. У каждого есть свои плюсы и минусы. Процесс проектирования базы данных один из важных этапов, ведь правильно спроектированная база данных облегчит некоторые моменты.

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

схема получения данных database coordinator

Таким образом мы вынесли всю логику по работе с нашими данными в DatabaseCoordianator. Но как же разделить сами данные по серверам, чтобы у нас была масштабируемая система и при добавлении нового сервера не возникало затруднений? Тут приходит на помощь нодная система хранения. Давайте рассмотрим, что у нас возникло при построении данной ноды или же кластера.

Нода состоит из множество mysql серверов, на каждый из которых положена своя задача. В каждой ноде есть мастер-сервер, на который пишутся данные, и несколько слейв-серверов, в которых считываются данные.      

масштабируемая система хранения информации на базе mysql серверов

В зависимости от задачи, необходимо иметь как минимум 2 слейв-сервера. Дело в том, что такие операции, как добавление колонки в таблицу, очень тяжеловесные. И если в процессе работы поменяется бизнес-логика и нужно будет изменить таблицу, тогда один слейв-сервер приостанавливается на запись, модифицируется и потом в конфигурации указывается как мастер.

Между мастер и слейв-сервером есть задержка. Асинхронность операции означает, что данные могут быть записаны с некоторой задержкой. И если вы используете последовательные операции, тогда необходимо использовать чтения с мастера.

При необходимости, добавление нового кластера не составит труда. В DatabaseCoordianatorпрописывается информация о том, что на нем хранится.

С хранением информации немного разобрались. Но как теперь обстоят дела с архитектурой в целом и с запросами от наших клиентов и их обработкой?

Обычно новое приложение запускается на одном сервере, на котором работают различные компоненты системы. Но такой подход к решению задачи не подходит. Количество активных пользователей, которые будут в системе ежесекундно делать запросы  - сотни тысяч. С ними обычные решения не справятся. В системе должен присутствовать механизм балансировки нагрузки. В решение задачи такого рода ставят много бекендов, при этом желательно иметь одинаковую конфигурацию. Зачастую используют связку Apache+nginx, но для более сложных бизнес-логик реализуют самописные сервера.

Nginx умеет балансировать нагрузку между нашими серверами. Для этого необходимо выделить список бекендов и прописать в upstream. Если некоторые сервера более сильной конфигурации, то в ней можно указать вес этих серверов.

Пример такой конфигурации может выглядеть следующим образом:


upstream backend { 
    server 10.0.0.1 weight=10; 
    server 10.0.0.2 weight=2; 
    server 10.0.0.3 weight=4; 
    server 10.0.0.4 weight=4; 
    server 10.0.0.5 weight=4; 
    server 10.0.0.6 weight=4; 
} 
server { 
    server_name ruhighload.com; 
    root /var/www/ruhighload; 
    index index.php; 
    location ~* .(php)$ { 
        fastcgi_pass backend; 
        fastcgi_index index.php; 
        include fastcgi_params; 
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
    } 
}

При построении также используется балансировка на уровне DNS. Одним из решений является Round Robin балансировка. В таком случае указывается несколько адресов с фронтендами, которые могут принимать запросы. При каждом обращении мы будем получать другой адрес сервера, на который будет происходить запрос. Таким образом DNS будет отдавать разные IP адреса разным клиентам.

Увидеть этот механизм балансировки можно на различных высоко нагруженных ресурсах. Если мы воспользуемся утилитой hosts и ресурсом vk.com, увидим, что на каждый запрос нам выдается другой ip адрес, а сами адреса идут по цепочке по кругу.

 

dns балансировка на базе round robin

Одним из факторов при работе с любым приложением является время ответа на запрос. Ведь не хочется ждать результат кучу времени. При обычном монолитном подходе к разработке приложения, у нас может возникнуть проблема с каким-то запросом в базу данных. Или где-то еще что-то не будет функционировать и мы не сможем нормально работать. При монолитном подходе мы не отдадим клиенту данные, пока не пройдут все запросы в базу данных. Такой подход не совсем удобен для нашей системы. Более правильно использовать сервисную архитектору. Это означает, что все манипуляции с набором данных выносятся в отдельный сервис. При генерации страницы для клиента, мы запрашиваем каждый сервис в отдельности. И если у нас какой-то запрос не прошел, мы его просто по таймауту откидываем, а клиенту отдаем страницу без этого блока. В большинстве случаев клиент эту деталь может даже не заметить. Таким образом наше приложение имеет работоспособный вид, а не показывает белую страницу ожидания или какой-то непонятный клиенту код ошибки.

Комментарий (0)

Войдите с помощью соцсетей:
или
введите свои данные: