Подходит шардинг MySQL?

88

Каков наилучший подход для сегментирования таблиц MySQL. Я могу придумать следующие подходы:

  1. Шардинг на уровне приложения?
  2. Шардинг на уровне прокси MySQL?
  3. Центральный сервер поиска для шардинга?

Знаете ли вы какие-нибудь интересные проекты или инструменты в этой области?

Шеки
источник

Ответы:

116

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

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

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

Случай записи: а) частота операций записи приводит к постоянной перегрузке дисков этого сервера или б) выполняется слишком много операций записи, поэтому репликация постоянно отстает в этой иерархии репликации.

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

Вы делаете это только тогда, когда вам нужно осколить.


В момент создания шарда вы платите за это несколькими способами:

Большая часть вашего SQL больше не декларативна.

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

В сегментированной среде вы, вероятно, объединяете таблицу на узле A с данными на узле B, или у вас есть таблица размером больше, чем узел, на узлах A и B, и вы объединяете данные из нее с данными, которые находятся на узлах B и C. Вы начинаете писать разрешения соединения на основе хэшей на стороне приложения вручную, чтобы решить эту проблему (или вы заново изобретаете кластер MySQL), что означает, что вы получаете много SQL, который больше не декларативен, но выражает функциональность SQL процедурным способом (например, вы используете операторы SELECT в циклах).

У вас большая задержка в сети.

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

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

Но даже в лучшем случае это включает в себя намного больше сетевых обходов, чем локальная ситуация, и это более сложно. Тем более, что оптимизатор MySQL вообще ничего не знает о задержках в сети (хорошо, кластер MySQL постепенно улучшается в этом, но для ванильного MySQL вне кластера это все еще верно).

Вы теряете выразительную силу SQL.

Хорошо, это, вероятно, менее важно, но ограничения внешнего ключа и другие механизмы SQL для целостности данных не могут охватывать несколько сегментов.

MySQL не имеет API, который разрешает асинхронные запросы в рабочем состоянии.

Когда данные одного и того же типа находятся на нескольких узлах (например, пользовательские данные на узлах A, B и C), горизонтальные запросы часто необходимо разрешать для всех этих узлов («Найти все учетные записи пользователей, которые не входили в систему в течение 90 дней. или больше"). Время доступа к данным растет линейно с количеством узлов, если только несколько узлов не могут быть запрошены параллельно, а результаты агрегированы по мере их поступления («Map-Reduce»).

Предварительным условием для этого является асинхронный коммуникационный API, который не существует для MySQL в хорошей рабочей форме. Альтернативой является множество разветвлений и соединений в дочерних процессах, которые посещают мир suck по сезонному абонементу.


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

Вопрос в том, хотите ли вы автоматически сегментировать (определение того, какая строка входит в какой узел, например, путем хеширования первичных ключей) или если вы хотите функционально разделить вручную («Таблицы, относящиеся к пользовательской истории xyz, переходят к этому master, а таблицы, связанные с abc и def, переходят к этому мастеру ").

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

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

Функциональное сегментирование имеет то преимущество, что оно относительно легко выполняется с существующей кодовой базой с некоторыми изменениями, которые не являются слишком большими. http://Booking.com делал это несколько раз за последние годы, и у них это хорошо сработало.


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

Изотопп
источник
2
Это хороший ответ. Но я хочу отметить, что сегментирование действительно необходимо только для приложений большого объема и, скорее всего, они приносят какой-то доход. Стороннее приложение для сегментирования будет обрабатывать все ваши проблемы с соединениями, кросс-сегментными транзакциями и т. Д. И если вы получите хорошее приложение, оно будет поддерживать целостность «реляционной» базы данных. Другие приложения, вы правы, просто превратят вашу базу данных в пару «ключ-значение» и тем самым разрушат цель SQL.
chantheman
3
Мне еще предстоит встретить приложение для сегментирования, коммерческое или нет, которое успешно скрывает тот факт, что данные теперь разбросаны по сети и подвержены задержкам или несогласованности из-за отсутствия ожидания, вызванного задержкой. Если вы выполняете шардинг, ваше приложение заметит это и потребует изменений. С таким же успехом вы можете контролировать это сами. Серебряной пули нет, зато много змеиного масла.
Isotopp
1
Вам следует проверить dbShards. Он масштабируется лучше, чем линейно, в зависимости от количества добавленных «осколков». Вам потребуется очень мало изменений на стороне приложения, если они вообще потребуются, и да, ваше приложение не знает разницы. Он просто отправляет и получает транзакции так же, как с ODBC или JDBC. dbShards также позволяет использовать подсказки о сегментах, если вам нужен больший контроль над транзакцией. Вы можете точно указать dbShards, с какого шарда вы хотите читать или писать.
chantheman
1
@Gigala ну, тратить время на составление такого четко определенного ответа, независимо от его широты, тоже не обязательно, но я рад, что это было сделано, поскольку этот ответ оказался для меня полезным. Пожалуйста, не отговаривайте пользователей не «мыслить нестандартно» при ответе.
mewm
12
  1. Шардинг на уровне приложений: dbShards - единственный известный мне продукт, который выполняет «сегментирование с учетом приложений». На сайте есть несколько хороших статей. По определению, сегментирование с учетом приложений будет более эффективным. Если приложение точно знает, куда направить транзакцию, не просматривая ее или не перенаправляясь через прокси, это само по себе будет быстрее. И скорость часто является одной из основных, если не единственной проблемой, когда кто-то изучает шардинг.

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

  3. На самом деле это то же самое, что и №2.

Chantheman
источник
где-то в продакшене используется dbShards? также это не с открытым исходным кодом.
шеки
Также подходы 2 и 3 могут отличаться, если прокси ищет на основе хеша, а не БД или хранилища.
шеки
1
dbShards работает с множеством клиентов, но нет, это не открытый исходный код. Я не думаю, что вы найдете хороший продукт для сегментирования с открытым исходным кодом. И да, вы правы в том, что хеш можно использовать для поиска, но в этом случае вам все равно придется сделать еще одну «остановку», чтобы получить вашу транзакцию в базе данных. Вот почему сегментирование с учетом приложения почти всегда будет быстрее.
chantheman 06
Но, как я уже сказал, если вы сможете получить приложение для сегментирования, которое поддерживает целостность отношений, то вы будете в хорошей форме. Я упоминаю dbShards, потому что это единственный известный мне инструмент. И поскольку это так, он линейно масштабирует вашу скорость записи и чтения. Вы добавляете 4 «шарда» или разделяете свой сервер MySQL на 4, и он будет работать в 4 раза быстрее.
chantheman
7

Знаете ли вы какие-нибудь интересные проекты или инструменты в этой области?

Несколько новых проектов в этом пространстве:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/
btcbb
источник
5

Shard-Query - это решение для шардинга MySQL на основе OLAP. Он позволяет вам определять комбинацию сегментированных таблиц и нечетких таблиц. Нечеткие таблицы (например, таблицы поиска) могут свободно присоединяться к сегментированным таблицам, а сегментированные таблицы могут быть объединены друг с другом, пока таблицы соединены ключом сегментирования (нет перекрестных сегментов или самостоятельных соединений, пересекающих границы сегментов). Будучи решением OLAP, Shard-Query обычно имеет минимальное время ответа 100 мс или меньше, даже для простых запросов, поэтому он не будет работать для OLTP. Shard-Query предназначен для параллельного анализа больших наборов данных.

Решения для сегментирования OLTP существуют и для MySQL. Решения с закрытым исходным кодом включают ScaleDB , DBShards . Решение OLTP с открытым исходным кодом включает JetPants , Cubrid или Flock / Gizzard (инфраструктура Twitter).

Джастин Свонхарт
источник
3

Уровень приложения, конечно.

Лучший подход, который я когда-либо видел в этой книге

Высокопроизводительный MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

Краткое описание: вы можете разделить свои данные на несколько частей и хранить ~ 50 частей на каждом сервере. Это поможет вам избежать второй по значимости проблемы шардинга - перебалансировки. Просто перенесите некоторые из них на новый сервер и все будет хорошо :)

Я настоятельно рекомендую вам купить его и прочитать часть "масштабирование mysql".

Андрей Фролов
источник
Книге, которую вы порекомендовали, исполнилось 8 лет ... охватывает ли она сегментирование, имеющее отношение к сегодняшним технологиям?
raffian
1
Он охватывает некоторые базовые подходы к масштабированию mysql. AFAIK ничего не изменилось в масштабировании mysql. В наши дни широко используются те же методы сегментирования и репликации на уровне приложения.
Андрей Фролов
Я могу ошибаться, но за последнюю неделю я провел массу исследований по этому поводу, и похоже, что за последние 8 лет mySQL внес много изменений, особенно в отношении секционирования и кеширования. В этом году вышла новая версия: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/… Я не читал ее, но думаю, что она охватывает новые доступные модели репликации.
NateDSaint
4
Книги .. почему бы просто не объяснить это здесь.
DDD,
2

По состоянию на 2018 год, похоже, для этого существует собственное решение MySql. На самом деле их как минимум 2 - InnoDB Cluster и NDB Cluster (есть коммерческая и общественная версия).

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

Необходимо изменить синтаксис для создания таблиц, например:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(это только один из четырех типов разбиения )

Одно очень важное ограничение:

Внешние ключи InnoDB и разделение MySQL несовместимы. Секционированные таблицы InnoDB не могут иметь ссылок на внешние ключи, а также не могут иметь столбцы, на которые ссылаются внешние ключи. Таблицы InnoDB, которые имеют или на которые ссылаются внешние ключи, не могут быть секционированы.

Юранос
источник
Имейте в виду, что PARTITION BY HASH(YEAR...)будут сканироваться все разделы, если у вас есть диапазон дат. Фу.
Рик Джеймс