Ребалансировка данных при шардинге

admin

При шардинге неизбежно возникает необходимость перебалансировать данные. Точно предсказать рост объема и формы данных практически невозможно. Поэтому ребалансировка данных – такая же систематическая операция, как и хранение данных. Ее нужно планировать на этапе проектирования, а не на этапе администрирования.

Пусть данные распределены между 5 серверами. Например, это таблица личных сообщений:

**messages**: id | user_id | time | message | sender

Данные в этой таблице распределяются путем проверки user_id (остаток от деления на 5):

12345

Остаток от деления user_id % 5 == 1 user_id % 5 == 2 user_id % 5 == 3 user_id % 5 == 4 user_id % 5 == 0
Номер сервера с данными

Т.е. для получения списка личных сообщений пользователя с id = 47, необходимо выполнить такие операции:

$user_id = 47;

$server = $user_id % 5 ? : 5;

# подключаемся к нужному серверу

**$connection = connect($server);**

# выполняем обычный запрос (в рамках подключения)

$messages = query(**$connection**, “SELECT * FROM messages WHERE user_id = {$user_id}”); # без инъекций

## Выбор сервера БД под конкретного пользователя при шардинге

Подготовка к ребалансированию

Если текущие сервера заняты на 70…80% это признак того, что пора расширять их количество. Сколько ставить новых серверов? Прикинуть можно очень просто:

  • Количество занятого места на диске (на всех серверах) не должно быть более 50%, иначе готовность к взрывным нагрузкам очень низкая.
  • Скорость роста данных не должна приводить к повторной ребалансировке быстрее, чем вы успеете подготовить новое железо. От нескольких дней до недели обычно. Но тут ясно, что лучше обеспечить запас (например, месяц).

Допустим мы поставили еще 5 серверов и теперь их у нас 10. Если говорим о записи новых данных, то тут ничего делать не нужно – просто изменить логику шардинга (остаток от деления нужно теперь считать от 10). Но для правильного получения ранее сохраненных данных, необходимо выполнить ребелансировку данных со старых серверов на новые.

Например, в старой схеме с 5 серверами сообщения пользователя с id = 47 лежали на сервере:

[**5** серверов]: user_id = 47, server_id = **2**

## остаток от деления 47 на 5 = 2

В новой схеме с 10 серверами, данные должны лежать тут:

[**10** серверов]: user_id = 47, server_id = **7**

## остаток от деления 47 на 10 = 7

Проведение ребалансировки

Есть две стратегии. Синхронная и асинхронная.

Асинхронная ребалансировка

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

foreach ( $users as $id )

{

# вычисляем номера серверов в старой и новой схеме

$old_server = $id % 5 ? : 5;

$new_server = $id % 10 ? : 10;

if ( $old_server != $new_server )

{

# получаем все сообщения со старого сервера

$all_messages = get_messages($old_server, $id);

# сохраняем все сообщения на новый сервер

save_messages($new_server, $id, $all_messages);

}

}

После перемещения всех данных, приложение начнет работать с новым набором серверов.

Ясно, что на время перемещения необходимо как-то знать, кто из пользователей уже обработан, а кто еще нет.
Это можно сделать путем добавления флага в табличку пользователей и сброса его перед началом перебалансирования:

**users**: id | email | ... | messages_rebalanced

Тогда, при перабалансировке необходимо будет обновлять этот флажок:

}

В приложении это позволит обеспечить нормальную работу прямо во время перемещения данных:

$user_id = 47;

if ( $user[‘messages_rebalanced’] )

{

# данные уже перемещены, читаем с нового сервера

$server = $user_id % 10 ? : 10;

}

else

{

# данные еще не перемещены, читаем со старого сервера

$server = $user_id % 5 ? : 5;

}

## по флажку мы узнаем, с какого сервера стоит читать данные для пользователя

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

Синхронная ребалансировка

Синхронная ребалансировка подразумевает, что мы ничего не делаем с данными, пока к ним не прийдет запрос. Например, данные пользователя c id = 47 будут лежать на 2м сервере, хотя серверов уже будет 10.

Итак, добавляем новые сервера и сразу же включаем их в работу.

Если приходит запрос на запись, мы записываем данные на нужный сервер в новой схеме.

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

Допустим мы хотим прочитать данные пользователя с user_id = 47, данные которого пока еще лежат на старом сервере (это мы тоже узнаем по флажку messages_rebalanced). Тогда перед получением данных, мы выполним их перемещение:


}

# читаем все сообщения с нового сервера

$server = $user_id % 10 ? : 10;

$messages = get_messages($server, $user_id);

## перед первым чтением в новой схеме, данные будут перемещены со старого на новый сервер

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

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

<h2>TL;DR

Ребалансировка – часть проектирования. Ее придется делать. Готовьтесь к тому, чтобы иметь удобный механизм ребалансировки до первой необходимости. Проще использовать синхронный метод. Однако, при больших объемах перемещаемых данных стоит выбрать асинхронный.

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023