Шардирование
Начинаем 6-ю главу кабанчика.
Репликация — это наличие на нескольких узлах одних и тех же данных (копий).
Шардирование (partitioning) — это разбиение большого объема данных на несколько узлов, то есть на каждом узле лежат свои данные. Этот подход используется для масштабирования.
Шардирование обычно совмещают с репликацией для отказоустойчивости: каждая запись может храниться на нескольких узлах, но один узел для этой записи будет лидером, а другие — репликами.
Цель шардирования — равномерно распределить данные и нагрузку от запросов. Если доли всех шардов примерно равны, то теоретически 10 узлов будут иметь в 10 раз большую пропускную способность по чтению и записи, чем один узел.
Если на одни шарды приходится значительно больше данных или запросов, чем на другие, то шардирование выполнено неравномерно и называется асимметричным (skewed). Ассиметричность снижает эффективность шардирования: нагруженный шард становятся узким местом системы. Шард с непропорционально высокой нагрузкой называют горячим (hot spot).
Рассмотрим данные типа «ключ — значение».
Как распределять по шардам данные
📌 Определять шард для размещения новой записи случайным образом
➕ просто
➕ равномерное распределение
➖ при чтении неизвестно, в каком шарде находится конкретная запись, поэтому придется параллельно опрашивать все узлы
📌 По ключу
Назначить шардам диапазоны значений ключа и определять шард для размещения новой записи по тому, в какой диапазон попадает ее ключ
➕ при чтении легко определить, в каком шарде находится запись
➕ в пределах шарда ключи могут храниться отсортировано, что позволяет легко извлечь сразу набор данных
➖ может приводить к образованию горячих шардов, если ключом является метка времени: все операции записи будут приходиться на шард за текущий день (месяц), а остальные будут простаивать
Диапазоны, назначенные шардам, могут быть разного размера, чтобы данные были распределены равномерно. Например, делим пользователей по шардам по возрасту. Если взять шаг 10 лет, то шард 0-10 окажется мало нагруженным, а шард 20-30 перегруженным. Нужно подобрать разный размер диапазонов, чтобы выровнять шарды по количеству пользователей.
📌 По хэшу ключа
Назначить шардам диапазоны хэшей и определять шард для размещения новой записи по тому, в какой диапазон попадает хэш ключа
Хорошая хэш-функция получает на входе асимметричные данные и возвращает равномерно распределенные значения.
➕ при чтении легко определить, в каком шарде находится запись
➕ равномерное распределение
➖ теряем возможность эффективно выполнять запросы по диапазонам, потому что рядом стоящие ключи оказываются разбросаны по разным шардам, и порядок их сортировки теряется
В Cassandra можно сделать первичный ключ, состоящий из нескольких полей. Тогда для определения шарда берется хэш только первой части такого ключа, а остальные используются для сортировки данных. Например, в соцсети один пользователь пишет много постов. Если выбрать в качестве первичного ключа для постов связку (user_id, update_timestamp), то по user_id будет определен шард, и все посты одного пользователя будут удобно сохранены на одном шарде, а update_timestamp будет использован для сортировки. Это даст возможность легко получить все посты пользователя за определенный промежуток времени.
Ассиметричные нагрузки и разгрузка горячих шардов
Хэширование ключа для определения шарда помогает равномерному распределению, но не всегда. Это не поможет, когда все запросы на чтение и запись относятся к одной и той же записи, а значит приходят на один шард. Почему эта запись так популярна? Обычно приводят в пример соцсети знаменитостей, тот же твиттер Илона Маска. Шард с последним твитом Маска окажется горячим.
Разруливают такие ситуации не на уровне БД, а на уровне приложения. Например, добавляют в начало или конец горячего ключа user_id случайное число. Это позволяет распределить записи по разным шардам. Однако при чтении придется совершать дополнительные действия по объединению данных. Поэтому делать разбивку имеет смысл только для небольшого числа горячих ключей.
#кабанчик #сисдиз
Post #75
2.89K

- 👍 10
- ❤ 6
- 🔥 4