![]() |
![]() |
![]() |
|||||
![]() |
Горизонтальное масштабирование базы данных. Репликация. Партицирование. Шардирование |
||||||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2025-01-28 11:51 В современном мире данных нагрузка на базы данных стремительно растёт. Когда один сервер перестаёт справляться с объёмом запросов, встаёт вопрос о масштабировании: как эффективно распределить нагрузку, сохранив высокую производительность и доступность? Можно конечно попытаться сделать наш единственный сервер идеальным и мощным — вертикально масштабировать его. Но сегодня мы поговорим о горизонтальном масштабировании — будем брать не мощностью сервера, а количеством узлов. Существует множество стратегий решения указанной проблемы. Сегодня мы разберем самые популярные из них — репликацию, партициривание и шардирование. Рассмотрим их принципы, плюсы и минусы, а также лучшие практики применения. Понимание этих техник поможет разработчикам и архитекторам строить отказоустойчивые, масштабируемые и высокопроизводительные системы хранения данных. Репликация (Replication) Репликация базы данных — это процесс автоматического копирования и синхронизации данных между несколькими серверами (узлами). При репликации изменения, внесённые в одну копию базы (основной узел), автоматически передаются на другие узлы (реплики), которые могут использоваться для балансировки нагрузки, резервного копирования или аналитики. Суть репликации заключается в существовании множества копий базы, имеющих весь набор данных. В случае выхода из строя или большой нагрузки на один узел, запросы перенаправляются на другой. Не всегда все реплики имеют равные права. Существует 2 сценария: Master-Slave и Master-Master.
Master — Slave Master-Slave репликация — это способ организации базы данных, где есть один главный сервер (Master) и один или несколько подчинённых (Slave). Master принимает все запросы на запись (добавление, изменение, удаление данных), а Slaves только читают данные и получают обновления от Master. ![]() Как это работает?
Плюсы:
Минусы:
Master — Master Master-Master репликация — это когда у базы данных есть два (или больше) главных сервера, и каждый из них может одновременно принимать и обрабатывать запросы на запись и чтение. Данные между серверами автоматически синхронизируются, чтобы оставаться одинаковыми. ![]() Плюсы:
Минусы:
В некоторых сценариях, репликация не решит все ваши проблемы, а иногда только создаст дополнительные. Второй популярной стратегией масштабирования БД является партицирование. Партицирование (Partitioning) Партицирование базы данных — это метод разбиения большой таблицы в рамках единой базы на более мелкие, логически связанные части (партиции). Каждая партиция хранится отдельно,но логически объединяется в одну таблицу, а база автоматически направляет запросы в нужные партиции. Существует 2 способа партицировать таблицу — горизонтально и вертикально. Вертикальное партицирование — не самый популярный, но заслуживающий упоминания вариант. При данном подходе таблица разделяется на партиции по принципу выбранных колонок. Например, если у вас есть таблица users с полями id, name, age, fav_sport, fav_food, то можно разделить её на партиции users_identity с полями id, name, age и users_preferences с полями id, fav_sport и fav_food. Важно грамотно выбрать ключевые колонки дробления, чтобы равномерно распределить нагрузку. Ведь если программа 90% запросов будет направлять в партицию 1, а лишь оставшиеся 10% в партицию 2, то значит мы партицировали таблицу неправильно, и следовательно, теряем производительность. ![]() Горизонтальное партицирование — более распространённый метод, заключающийся в делении таблицы по строкам. Например, таблицу consumers с полями city, name, и age можно разбить на таблицы по типу users_russia, users_ukraine, users_monaco. Однако опять же, важно помнить про равномерность распределения. Если предположить, что наш сервис распространен и в России и в Монако, то распределение на users_russia и users_monaco будет нерациональным, и не приведет к желаемому результату(потому что кол-во запросов из России очевидно будет много выше, так что проблема с большой нагрузкой от этой страны останется нерешенной). Кейс был приведен исключительно для наглядности, а конкретно в таком случае лучше будет выбрать другой принцип партицирования, чем регион. ![]() P.S. методы шардирования Key-Based, Range-Based и Directory-Based о которых мы поговорим ниже, могут также применяться для выбора метода партицирования. Шардирование (Sharding) Шардирование — это метод горизонтального масштабирования базы данных, при котором данные разделяются на независимые части (шарды) и хранятся на разных серверах. Каждый шард содержит только часть общей информации, но вместе они образуют полную базу. Это позволяет распределять нагрузку и увеличивать производительность системы, так как запросы к данным могут выполняться параллельно на разных узлах. Основная задача шардирования — определить, каким образом данные будут распределяться между шардами. Чаще всего используются хеш-функции, диапазоны значений или географическое разделение. Однако шардирование добавляет сложность в администрирование, так как требует балансировки данных, управления кросс-шардовыми запросами и обеспечения целостности транзакций. ![]() Способы шардирования 1. Range-Based (Диапазонное) В этом методе данные распределяются по шардам на основе определённых диапазонов значений. Например, если у нас есть база с пользователями, можно распределить их по шардам в зависимости от ID:
Плюсы:
Минусы:
2. Key-Based (Хеширование) В этом методе для распределения данных используется хеш-функция. Зачастую принцип такой — выбираем колонку таблицы, которую отдадим в хеш-функцию. Затем полученный хеш делим на количество шардов, и остаток от деления и будет номером шарда, на который стоит записать или с которого запросить данные. Если например как pivot поле взять user_id, то формула будет выглядеть так: Плюсы:
Минусы:
3. Directory-Based (Каталожное) В этом методе существует специальный каталог (Directory), который отслеживает, в каком шарде находятся данные. Мы условно «хардкодим» значения в некий список, по типу Вася — Шард1, Никита — Шард2, Ольга — Шард3. При запросе к данным сначала обращаются к каталогу, который указывает нужный шард. Плюсы:
Минусы:
Routing: Как понять, в какой шард отправить запрос? 1. Клиентский метод Клиент сам знает, где лежат данные, и направляет запрос сразу в нужный шард. Плюсы:
Минусы:
2. Proxy Все запросы идут через прокси-сервер, который определяет, куда их направлять. Он не содержит сложной логики, а просто знает, в какой шард направить какой запрос. Плюсы:
Минусы:
3. Coordinator Координатор — это тот же прокси, но с логикой внутри. Мало того что он направляет каждый запрос в нужный шард, он также способен делать довольно сложные SQL запросы, декомпозировать на под-запросы к разным шардам с последующим объединением и т д. Плюсы:
Минусы:
Перебалансировка данных: Как перенести данные из одного шарда на другой? 1. Только чтение. Отклонение запросов на запись Допустим нам нужно перенести данные с шарда А на шард Б. Одним из возможных решений может быть временно отклонять все запросы на запись, обрабатывая только запросы на чтение. Параллельно тому, постепенно перекидывать данные на нужный шард. Данный метод хорошо подходит для использования ночью, если мы знаем что большинство наших пользователей находятся в одном часовом поясе. 2. Неизменяемые данные Если же данные, которыми мы управляем - неизменны(например логи, история покупок и т д), то можно организовать следующий флоу: запросы на запись мы отправляем исключительно на новый шард, а чтение адресуем в оба - старый и новый шард. 3. Логическая репликация Ждем полной синхронизации, работая только со сторым шардом. Затем отключаем старый шард и переключаемся на новый, адресуя все запросы исключительно ему. 4. Смешанный подход Зачастую, на реальных проектах комбинируют различные подходы, беря лучшее от каждого из них. Resharding: перераспределение данных Resharding — это процесс перераспределения данных при добавлении или удалении серверов. Основные причины:
Давайте вспомним вышеупомянутую проблему, которая возникает при решардинге, если мы выбрали способ шардирования - Key-Based:
Т.к. количество шардов может меняться хоть каждый день (сегодня мы хотим повысить производительность — докупили 5 узлов, завтра поняли, что излишние шарды наоборот замедляют нашу систему — сократили их до 3), делаем вывод, что обычного хеширования будет недостаточно. Нужна некая улучшенная версия данного подхода. Давайте рассморим наиболее популярные варианты. Методы хеширования
Консистентное хеширование можно представить как круг, на котором равномерно распределены сервера (или шарды). Каждый ключ (например, ID пользователя) тоже хешируется и помещается на этот круг. Запросы направляются на ближайший сервер по часовой стрелке. Это позволяет легко добавлять или удалять сервера: вместо перераспределения всех данных, достаточно переместить только те, которые попадали на изменённый участок круга. Например, если добавить новый сервер, он возьмёт часть данных у ближайшего соседа, но остальные сервера останутся нетронутыми. Как понять где на кругу разместить запись? — Принцип циферблата. Пусть наша хеш-функция возращает значения от 1 до 12. Это и станет указателем на кругу. ![]() Если сервер выходит из строя, его нагрузку берут на себя ближайшие. Однако, при малом количестве серверов распределение может быть неравномерным, но это решается виртуальными узлами (виртуальные шарды — это искусственные копии одного физического сервера, которые распределяются по кольцу хеширования, имитируя большее количество узлов. Это помогает равномернее распределять нагрузку и избежать ситуации, когда один сервер получает слишком много запросов). Также такой подход сложнее классического модульного хеширования (
При данном подходе, наша хеш-функция принимает 2 аргумента - pivot поле и номер шарда. Комбинация, при которой хеш будет наибольшим и будет указывать нужный шард. После указанных команд, в переменной shard будет хранится номер нужного нам узла. Если сервер выходит из строя или добавляется новый, только те ключи, которые были привязаны к нему, перераспределяются, а все остальные остаются на месте. Это делает систему устойчивой к изменениям и снижает нагрузку при решардинге. ![]() Главный плюс рандеву-хеширования — минимальные перестановки данных при изменениях в кластере. В отличие от консистентного хеширования, где ключи могут сильно «прыгать» при добавлении/удалении узлов, здесь перераспределяется только минимально необходимая часть данных. Это делает его удобным для распределённых систем, балансировки нагрузки и кэширующих прокси. Однако есть и минусы: алгоритм сложнее в реализации, чем обычное хеширование, и требует вычисления хешей для всех серверов перед выбором лучшего, что может немного замедлять процесс при большом количестве серверов. Виртуальные бакеты (Virtual Buckets) Чтобы лучше понять что такое виртуальные бакеты и чем они полезны, вспомним известную цитату:
Виртуальные бакеты решают проблему необходимости перераспределения данных при изменении количества шардов, добавляя дополнительный уровень абстракции. Вместо того, чтобы сразу привязывать данные к конкретным серверам, мы сначала распределяем их по виртуальным бакетам — маленьким контейнерам или группам. Эти бакеты, в свою очередь, уже привязываются к серверам. Если сервер выходит из строя, его бакеты просто перераспределяются между оставшимися серверами, а не все данные сразу. Это делает систему гибче и снижает нагрузку при изменениях. Главное преимущество виртуальных бакетов — это равномерное распределение данных и минимальные перестановки при добавлении/удалении серверов. Однако есть и минусы: появляется дополнительный уровень управления, что требует памяти и вычислений. Но в большинстве случаев эта плата за стабильность и предсказуемость вполне оправдана. Заключение Масштабирование базы данных — ключевой аспект построения высоконагруженных систем. Репликация повышает отказоустойчивость и распределяет нагрузку на чтение, партиционирование и шардирование помогают эффективно управлять большими объемами данных, а выбор стратегии хеширования и методов перераспределения критически важен для минимизации даунтайма при решардинге. Источник: habr.com Комментарии: |
||||||