Шард Всемогущий: Как Масштабировать Субд Для Высоконагруженной Системы

Весной 2021 года во французском Страсбурге произошло яркое событие: Дата-центр одного из крупнейших европейских хостинг-провайдеров полностью сгорел (ОВХ).

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

Одна из вероятных причин – человеческий фактор.

В результате под угрозой оказался не только сам дата-центр, но и весь бизнес провайдера.

Кстати, дата-центры в России тоже горят. К сожалению, пожар — не единственная проблема больших данных.

Не менее опасны высоконагруженные системы.

Это когда, например, приложение уже не справляется с непосредственной нагрузкой, а вся инфраструктура работает на пределе и не имеет места для роста.

Забегая вперед, скажу, что для каждой из перечисленных проблем есть решение.

Но обо всем по порядку.



Шард всемогущий: как масштабировать СУБД для высоконагруженной системы



Что делать, если объем и нагрузка на СУБД продолжают расти, а все возможности мы уже исчерпали?

Совсем недавно в своей статье «Большие данные со сливками от LinkedIn: инструкция, как правильно построить архитектуру системы» Я затронул очень важный аспект: проектирование и эксплуатацию высоконагруженных информационных систем — речь шла об узких местах в архитектуре таких программных решений.

Рекомендую прочитать эту «вводную» часть, чтобы лучше погрузиться в суть вопросов, обсуждаемых в этой статье.

Дело в том, что традиционно узким местом в архитектуре любой системы является система управления базами данных (СУБД).

Можно сколько угодно оптимизировать прикладное программное обеспечение (программное обеспечение), но вы все равно столкнетесь с ограничениями по производительности запросов к СУБД.

Мы уже говорили о том, что можно отказаться от традиционных СУБД в пользу NoSQL, пожертвовав строгой согласованностью, но при этом мы нашли компромиссный вариант — эвентуальную согласованность.

Но что делать, если объемы и нагрузка на СУБД продолжают расти, а все возможности вертикального масштабирования мы уже исчерпали? Пожалуй, оптимальное решение — шардинг( английский шардинг ).

Это подход, предполагающий разделение базы данных и ее отдельных объектов на независимые сегменты, каждый из которых управляется отдельным экземпляром сервера базы данных, обычно расположенным на отдельном вычислительном узле.

В отличие от разделения ( разделение ), что предполагает раздельное хранение частей объектов базы данных под управлением одного экземпляра СУБД, сегментация позволяет использовать методы распределенных вычислений.

Однако реализовать это сложнее, так как требуется координация нескольких экземпляров — и взаимодействие должно осуществляться со всем набором сегментов, как с единой базой данных.

Техника шардинга широко используется в СУБД NoSQL ( такие как Кассандра, Couchbase, MongoDB ), аналитическая СУБД ( База данных Teradata, Netezza, Greenplum ), поисковые системы ( Elasticsearch, Солр ).

Этот метод также реализован в некоторых традиционных реляционных СУБД ( Опция шардинга в базе данных Oracle ).

Для СУБД, не поддерживающих сегментацию, маршрутизация запросов к нескольким экземплярам СУБД организуется на стороне приложения.

Чтобы было понятнее, рассмотрим архитектуру на шардированной СУБД на примере MongoDb:

Шард всемогущий: как масштабировать СУБД для высоконагруженной системы

Давайте рассмотрим каждый элемент архитектуры отдельно: Приложение это наше приложение.

Для простоты я нарисовал типичное микросервисное приложение, но его архитектуру в этой статье мы не рассматриваем.

Нам важно, чтобы приложение работало с СУБД; монгосы — маршрутизатор запросов от приложения к конкретному узлу СУБД.

Количество роутеров может быть любым и зависит от профиля нагрузки и особенностей самого приложения; Конфигурационные серверы — сервер конфигурации (кластер) самой СУБД.

Отвечает за хранение метаданных шардированного кластера СУБД.

Представляет типичный кластер MongoDb в конфигурации ReplicaSet; Осколок - шард Кластер СУБД, отвечающий за хранение сегмента данных.

Представляет типичный кластер MongoDb в конфигурации ReplicaSet. Количество шардов может быть любым и зависит от профиля нагрузки, объемов данных и требований к производительности и отказоустойчивости.

По сути, каждый шард — это отдельный экземпляр СУБД.



Как выбрать шардирующий ключ?

Горизонтальное масштабирование предполагает распределение набора данных и нагрузки по нескольким узлам СУБД.

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

Как это работает: сущности, связанные одним и тем же значением шардирующего ключа, группируются в набор данных по заданному ключу.

Этот набор данных хранится в одном физическом шарде, что существенно облегчает обработку данных.

Таким образом, если известен шардинговый ключ какого-либо объекта, то Всегда вы можете ответить на вопросы:

  • Где следует сохранять данные?
  • Где я могу найти запрошенные данные?
Возникает резонный вопрос: как выбрать шардирующий ключ? Замечу, что хороший ключ имеет несколько характеристик: кардинальность и неизменяемость, причем вторая широко используется в частых запросах.

Естественным выбором ключа сегментирования является идентификатор объекта.

Если оно у вас есть, используйте его! Лучше всего, если этот идентификатор будет из семейства UUID (от англ.

универсальный уникальный идентификатор — универсальный уникальный идентификатор).

По сути, UUID — это стандарт идентификации, используемый при создании программного обеспечения.

Основная цель UUID — позволить распределенным системам однозначно идентифицировать информацию без координационного центра.

Таким образом, любой может создать UUID и использовать его для идентификации чего-либо с разумной степенью уверенности в том, что этот идентификатор никогда не будет случайно использован для чего-то другого.

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

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

И я надеюсь, что все прекрасно помнят, что процесс балансировки чанков далеко не бесплатный! «Из коробки» СУБД MongoDb предлагает два типа ключей:

  • Дальний бой — разделение данных на непрерывные диапазоны;
  • Хэшированный — разделение данных на основе хеш-функции.

Выбор за вами, но в большинстве случаев я бы рекомендовал использовать хешированное распределение ( хешированный осколочный ключ ).

Причина проста — хэш-функция позволяет превратить даже плохой с точки зрения формальных характеристик ключ в хороший.

Если говорить еще проще, задача хеш-функции — равномерно распределить сущности по шардам.

Я мог бы углубиться в сложную математику и поговорить о критерии Пирсона и других интересных вещах, но это не обязательно, так как инженеры MongoDb Inc. за нас уже все продумали и выбрали хорошую хеш-функцию для задачи шардинга.

.

Поэтому нам остаётся только пользоваться всем этим и получать от этого удовольствие.



«Игры» разума: как избежать «паразитного» трафика в дата-центре?

С ключами мы разобрались, а теперь перейдем к «горючим» терминам: географическая резервация И устойчивость к стихийным бедствиям .

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

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

В это трудно поверить, но даже сейчас на электросетях происходят масштабные аварии, причем уже давно.

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

Рассмотрим пример катастрофоустойчивого решения на базе СУБД MongoDb в активно-пассивной конфигурации.

На схеме ниже показана топология СУБД, распределенной по двум центрам обработки данных (NOC).

Давайте разберемся, как это работает!

Шард всемогущий: как масштабировать СУБД для высоконагруженной системы

По сути, мы делим каждый шард на две части — одна часть работает в NOC1, вторая — в NOC2. Активный дата-центр содержит ПЕРВИЧНЫЙ узел шарда СУБД и половину вторичных узлов.

С одного из вторичных узлов СУБД в активном дата-центре (NOC1), а не с PRIMARY, как мы привыкли, данные реплицируются в сторону NOC2. Более того, вы можете заметить, что этот узел базы данных помечен как «скрытый» ( скрытый ).

От кого он прячется? Разумеется, из нашего приложения, иначе на этот узел ложилась бы дополнительная нагрузка по чтению.

Каскадная репликация настраивается в самом дата-центре.

За что? Все дело в том, что между NOC1 и NOC2 существует канал связи и поскольку они географически разделены, канал имеет задержку в несколько десятков миллисекунд. Если бы репликация шла с основного (PRIMARY) узла активного шарда в NOC1, то мы бы замедлили работу кластера СУБД на этом дата-центре.

Дело в том, что при записи PRIMARY узел ждёт подтверждения от кворума реплик (SECONDARY) о завершении записи, а так как у нас задержка на канале, то подтверждение от реплик, находящихся в NOC2, пришло бы с задержкой.

Кроме того, мы бы просто засорили канал связи между дата-центрами «паразитным» трафиком от репликации.

Поэтому репликация в NOC2 происходит с выделенного узла в том же дата-центре, который, в свою очередь, реплицируется из источника, расположенного в NOC1. Ух, я наверное всех запутал.

Чтобы понять, что происходит, советую перечитать этот абзац несколько раз.

Итак, с репликацией шардов мы разобрались.

С конфиг-сервером еще проще — это единый распределенный ReplicaSet для двух дата-центров.

Далее, маршрутизаторы запросов — Mongo. С ними тоже все просто.

Они, как и само приложение, просто дублируются в двух дата-центрах.

Взаимодействия между этими компонентами нет. Они работают совершенно независимо друг от друга.

Что будет, если в NOC1 произойдет катастрофа, когда он вдруг превратится в пепел или «тыкву»? Алгоритм здесь следующий:

  1. Исключение узлов, расположенных в NOC1, из набора реплик для шард-серверов и серверов конфигурации.

  2. Изменение роли основного узла - источника репликации в NOC2 на PRIMARY
  3. Измените роль одного из вторичных серверов конфигурации в NOC2 на PRIMARY.
  4. Удаление скрытых со всех узлов в NOC2
  5. Все работает, данные сохраняются.

    Хотя, конечно, требовалось вмешательство инженера, которому после такой суматошной беготни наверняка потребовался бы день отдыха за счет компании.



Даже у шардинга есть недостатки

Конечно, у каждой самой замечательной вещи на свете, включая шардированную СУБД, есть и недостатки, о которых не следует забывать:
  • Прежде всего, шардированный кластер стоит дорого! Согласитесь, что иметь кластер из 3 физических серверов дешевле, чем кластер из 30 узлов.

    Давайте посчитаем: обычный (не шардированный) кластер СУБД, т.е.

    типичный ReplicaSet — это первичный + пара вторичных.

    Итого: 3 узла.

    Шардированный кластер — это уже как минимум 2 шарда, обычно больше (каждый по три ноды) + набор реплик для конфиг-серверов + серверы для монго.

  • Во-вторых, операция не всегда работает в сегментированных коллекциях.

    считать .

    Он может вернуть больше документов, чем на самом деле.

    Причина — балансировщик, который в фоновом режиме «переливает» документы из одного шарда в другой.

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

    Важно отметить, что при задании конкретного запроса операция подсчет ({запрос}) будет работать правильно.

    Также в новых версиях СУБД появилась возможность получать общее количество документов в коллекции с помощью оцениваемыйDocumentsCount() .

    Подробнее об этом читайте на сайте продавец .

  • В-третьих, шардированный кластер сложнее администрировать.

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

    Следует ли отказаться от шардинга из-за его дороговизны и сложности администрирования? Вопрос, пожалуй, риторический, ведь на кону не столько деньги и время, сколько репутация и развитие вашей компании.

Теги: #центр обработки данных #ИТ-инфраструктура #отказоустойчивость #Хранилище данных #база данных #NoSQL #highload #mongodb #sharding #mongodb sharding #geo-reservation
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.