В этой статье я расскажу о собственном опыте настройки кластера MySQL, вернее почему это не получилось сделать, а также о недостатках кластерного решения, предлагаемого MySQL и вообще о том, что желающим работать с кластером MySQL стоит сильно подумать - стоит ли это вообще делать! Несмотря на обилие статей о настройке кластера MySQL на русском языке, о недостатках и ограничениях кластера, авторы этих статей предпочитают умалчивать, что наводит на мыль о том, что либо они просто переводили английский оригинал документации по кластеру MySQL, либо запускали свой кластер на такой базе данных, которая может называться лишь тестовой, а не используемой в продуктивных системах с большим объёмом данных, разнообразной структурой и высокой нагрузкой. Автор: Виктор Вислобоков Итак, дано: существует БД, дамп которой, выполненный через mysqldump, составляет 2.5Gb. В общем довольно крупная БД, хотя и не сказать, чтобы очень. Нагрузка на MySQL сервер довольно велика, в связи с чем необходимо создать кластер и распределить эту нагрузку на вычислительную мощность двух серверов. Установка пакетов для кластера MySQLИтак, здесь вроде бы всё просто. У меня на серверах стоит CentOS 5.x, но вот незадача - пакета mysql-cluster ни в одном репозитарии для CentOS 5.x нет! Воспользовавшись поисковиками, я понял, что здесь удачи мне не видать - все занимались самосбором, версии какие-то древние, половина ссылок идёт в никуда. Разумеется первым делом, я зашёл на сайт MySQL, где раздаются как уже собранные пакеты под разные дистрибутивы, так и пакеты с исходными текстами. Собранного пакета под CentOS разумеется не было, был только пакет с исходными текстами для Red Hat Enterprise Linux 5 (почему? читайте маленькое пояснение ниже). Я взял эти исходники, но собираться под CentOS они не захотели с чем я поздравляю компанию Sun, которая теперь владеет MySQL! Поэтому я сделал так, как обычно делаю в случаях, когда мне чего-либо не хватает в CentOS и когда нужных мне пакетов нигде не найти - я просто попытался собрать готовый пакет из исходных текстов для дистрибутива Fedora. Если кто не знает, то поясню, что CentOS - это свободный клон Red Hat Enterprise Linux (RHEL), собирается из тех же исходников, с удалением логотипов Red Hat и коммерческих инструментов. В свою очередь, дистрибутив Fedora по факту является тестовой площадкой для будущих версий RHEL. Именно поэтому, в большинстве случаев, пакеты для Fedora прекрасно собираются в дистрибутивах RHEL и CentOS без каких-либо доводок и исправлений. Итак, на одном из зекал Fedora я нашёл исходник пакета mysql-5.0.77-1.fc10.src.rpm. И что характерно, что качество создания пакета в свободном дистрибутиве оказалось много выше, чем у коммерческой компании Sun - пакет для Fedora собрался в CentOS без каких-либо проблем, за что отдельное спасибо как сопровождающему данный пакет, так и всей команде Fedora. Сборка пакета из исходных текстов осуществляется командой: rpmbuild --rebuild mysql-5.0.77-1.fc10.src.rpm Разумеется, у вас должны быть установлены при этом все пакеты, которые необходимы для собственно сборки пакетов (rpmbuild, rpm-devel, компиляторы, auto* и т.д.), а также и те пакеты, сообщение о необходимости установке которых, вы получите при запуске сборки. После сборки вы получите следующие бинарные пакеты: mysql-5.0.77-1.i386.rpm mysql-bench-5.0.77-1.i386.rpm mysql-cluster-5.0.77-1.i386.rpm mysql-debuginfo-5.0.77-1.i386.rpm mysql-devel-5.0.77-1.i386.rpm mysql-embedded-5.0.77-1.i386.rpm mysql-embedded-devel-5.0.77-1.i386.rpm mysql-libs-5.0.77-1.i386.rpm mysql-server-5.0.77-1.i386.rpm mysql-test-5.0.77-1.i386.rpm Насколько я понял документацию, очень рекомендуется, чтобы все элементы кластера MySQL были одной версии. Более того, для организации устойчивой работы кластера в MySQL 5.0.x, необходимо ТРИ сервера: два кластерных узла и арбитр. Вы, конечно, можете использовать в качестве арбитра один из узлов кластера MySQL, но в случае отказа этого узла (содержащего также и арбитр), весь кластер рушится. Это одно из ограничений кластера MySQL 5.0.x. Как опять же было прочитано в документации на сайте MySQL: в версиях 6.x, можно будет создавать кластер и без арбитра, но к сожалению ветка 6.x - это даже не бета, а крайне экспериментальная альфа и ни о каком продуктивном использоваии этой версии и речи идти не может! Оцените комичность ситуации: для кластера из двух серверов нам надо три! К счастью, нужное количество серверов нашлось, учитывая, к тому же, что для арбитр - это фактически просто процесс, который не оказывает никакого влияния на MySQL, установленный на той же машине, т.е. вы можете смело запускать арбитр на машине, где уже настроен и работает какой-либо другой MySQL сервер - конфликтовать они друг с другом не будут как и зависеть друг от друга. Итак, на все три сервера ставим, получившиеся после сборки пакеты: mysql, mysql-cluster, mysql-libs, а на два сервера, которые будут узлами ставим ещё и пакет mysql-server. Установка пакетов как вы помните выполняется командой rpm -i <имя пакета>. Если же у вас уже был установлен mysql, то вместо ключа -i, воспользуйтесь ключём -U, чтобы обновить существующую версию. На этом этап установки закончен! Переходим к настройке... Настройка кластера MySQLИтак, сервер, на котором я устанавливаю арбитр имеет IP адрес: 10.1.1.2, узлы кластера, где будут работать экземпляры сервера MySQL имеют IP адреса: 10.1.1.13 и 10.1.1.3. Создаём файлы конфигурации. Файл конфигурации для арбитра вы должны создать сами. По умолчанию, после установки пакета у вас будет создан каталог /var/lib/mysql-cluster. Вот в этом каталоге вы и создаёте файл config.ini следующего содержания: [NDBD DEFAULT] NoOfReplicas=2 DataMemory=702M IndexMemory=160M RedoBuffer=32M MaxNoOfOrderedIndexes=8196 MaxNoOfUniqueHashIndexes=2048 MaxNoOfAttributes=9600 TimeBetweenLocalCheckpoints=10 [MYSQLD DEFAULT] [NDB_MGMD DEFAULT] [TCP DEFAULT] [NDB_MGMD] # IP этого сервера (арбитра) HostName=10.1.1.2 # Узлы кластера [NDBD] # IP первого сервера HostName=10.1.1.3 DataDir= /var/lib/mysql-cluster [NDBD] # IP второго сервера HostName=10.1.1.13 DataDir=/var/lib/mysql-cluster # Здесь можно задать некие параметры для клиентов MySQL (тех двух узлов кластера) # Но лучше этого не делать и задавать параметры непосредственно на самих серверах [MYSQLD] [MYSQLD] Некоторые пояснения по конфигу. На самом деле, вы можете пока смело закомментировать все директивы в секции [NDBD DEFAULT] кроме первых трёх. Остальные параметры по тонкой настроке кластера, даны тут скорее для примера - в реальности их намного больше, чем в этом конфигурационном файле и я оставил их, чтобы показать, что они вообще-то есть, потому что в упоминаемых мной статьях приводятся только именно первые три и больше ничего. За подробными пояснениями по данным параметрам, вам нужно сходить на сайт MySQL и почитать документацию по развёртыванию кластера, но краткие пояснения я дам NoOfReplicas=2 говорит, что в нашем кластере два узла DataMemory=702M и IndexMemory=160M два самых гадских параметра. Гадских потому, что нехватка памяти там или там может привести к ошибкам в работе кластера и к появлению разных (порой совершенно непонятных) сообщений при импорте БД на кластер. Значения, которые я поставил в этих переменных чисто условные, но советую начинать не менее чем с 400M и 100M соответственно. Забегая вперёд, могу сказать, что для моей БД этого не хватило! В документации MySQL приводится даже какая-то методика расчёта этих параметров, только вот эта методика больно уж неточная и непонятная, хотя вы можете и попробовать. RedoBuffer=32M значение размера буфера наката данных. Вроде бы как написано, что по умолчанию оно как раз 32M составляет. Поясню, что это такое. При закачивании данных в БД, которая размещена на кластере, порции данных передаются по сети на другой узел кластера для синхронизации и передаются именно в этот буфер, который затем записывается на диск. Если скорость данных записи на диск будет медленее, чем скорость поступления данных в буфер, то буфер переполнится, о чём вы получите так называемую "Temporality error" (временную ошибку). То-то вас это утешит, что ошибка временная, ведь ваша операция-то тем не менее обломается! MaxNoOfOrderedIndexes=8196 это количество индексов, которые может обслуживать кластер. Сюда входят все индексы, в том числе и первичные ключи. Если индексов в вашей БД будет больше, чем значение этого паметра, вы получите ошибку и ваш кластер работать не будет!MaxNoOfUniqueHashIndexes=2048 это количество индексов, созданных с ключевым словом HASH. В остальном всё аналогично предыдущему параметру. MaxNoOfAttributes=9600 это общее количество атрибутов, которые может обслуживать кластер. Что рассматривать как атрибут, я несколько не понял до конца. Совершенно точно, что любое поле (столбец) таблицы является атрибутом, но вот является ли атрибутом любой именованый объект в БД (например функция, триггер, индекс) я затрудняюсь сказать. TimeBetweenLocalCheckpoints=10 это очень хитрый параметр, который управляет частотой сброса на диск буферов узлов кластера, т.е. по сути частотой синхронизации данных между узлами. Для более нагруженных кластеров (в плане новых данных) рекомендуется меньшие значения, для менее нагруженных большие. Итак, с настройкой арбитра мы закончили, переходим к настройками самих узлов кластера. Собственно вы просто дописываете тот конфиг /etc/my.cnf, который у вас уже есть с вашими излюбленными параметрами. Надо начать секцию [mysqld] вот так: [mysqld] ndbcluster ndb-connectstring=10.1.1.2:1186 ... далее ваши любимые параметры настройки MySQL сервера и дополнительная [mysql_cluster] ndb-connectstring=10.1.1.2:1186 Вот собственно и всё. Все необходимые параметры для функционирования кластера, узлы возьмут из конфига арбитра. Переходим к старту кластера... Старт кластера MySQLСперва запускаем арбитр, для чего на сервере с арбитром запускаем service ndb_mgmd start Затем на каждом из узлов кластера запускаем собственно сам MySQL-сервер и кластерную составляющую: service mysqld start service ndbd start Разумеется, в случае если всё настроено везде верно, вам должно выдать ОК на все эти операции. Теперь идёт в консоль управления кластером. Для этого на сервере с арбитром запускаем: ndb_mgmи видим -- NDB Cluster -- Management Client -- ndb_mgm> Значит подключение к арбитру прошло успешно, он функционирует нормально. Теперь смотрим состояние кластера: ndb_mgm> show Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=2 @10.1.1.3 (Version: 5.0.77, Nodegroup: 0, Master) id=3 @10.1.1.13 (Version: 5.0.77, starting, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @10.1.1.2 (Version: 5.0.77) [mysqld(API)] 2 node(s) id=4 @10.1.1.13 (Version: 5.0.77) id=5 @10.1.1.3 (Version: 5.0.77) Как видим, оба узла запущены, узел 10.1.1.3 считается мастером. Если же картина например такая: ndb_mgm> show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=2 @10.1.1.3 (Version: 5.0.77, Nodegroup: 0, Master) id=3 (not connected, accepting connect from 10.1.1.13) [ndb_mgmd(MGM)] 1 node(s) id=1 @10.1.1.2 (Version: 5.0.77) [mysqld(API)] 2 node(s) id=4 @10.1.1.13 (Version: 5.0.77) id=5 @10.1.1.3 (Version: 5.0.77) то понятное дело, что узел 10.1.1.13 не запущен и соответственно надо принимать меры (например повторно его запустить) Необходимо ещё написать как вы можете изменить конфигурационные параметры, которые мы указывали в конфиге арбитра. Для этого вы должны, исправить config.ini на сервере с арбитром, после чего зайти в консоль управления nbd_mgm, остановить кластер командой shutdown, а затем выполнить снова все операции по старту кластера. В отдельных случаях, мной замечено, что после запуска ndbd на узлах кластера, должно пройти довольно продолжительное время, прежде чем по команде show в консоли вы увидите, что всё поднялось как надо. По всей видимости это связано с синхронизацией недосинхронизированных данных с последнего запуска кластера. Это был собственно старт кластера, а теперь начинается самое весёлое! Нам нужно импортировать существующую БД в кластер... Импорт существующей БД в кластерИтак, вы думаете, что теперь вам достаточно создать БД на любом из узлов кластера и она тут же появится на другом? Нет! Вы очень глубоко заблуждаетесь! Суперкластер от MySQL работает не так! Вы должны создать БД с одним и тем же именем на обоих узлах кластера. Далее, вам следует уяснить, что кластера как такового у вас нет! Вы в шоке? В недоумении? Поясняю. Всё что даёт вам кластер - это новый так называемый Storage Engine или говоря по простому - способ хранения данных в БД MySQL. В первых версиях MySQL был только один Storage Engine - MyISAM. Он до сих пор широко используется потому что наиболее просто, содержит наименьшее количество ограничений и хранится на файловой системе в виде множества отдельных файлов (как правило по 3 файла на таблицу). Далее появился более прогрессивный, поддерживающий транзакции Storage Engine под название InnoDB. Правда вот незадача, прогрессивный InnoDB не позволял в отличие от MyISAM использовать полнотекстовые индексы. Со временем появились и другие Storage Engine, например Archive, который позволяет хранить данные в БД в сжатом виде. Так вот, единственное, что делает кластер MySQL - это предоставляет вам новый Storage Engine, который называет NDB или ndbcluster. Как вы понимаете, в Storage Engine хранятся только таблицы и связанные с ними данные. А вот все остальные объекты БД (например, хранимые процедуры) вам придётся создавать (и при необходимости менять) ручками на обоих узлах кластера самим - правда здорово? То же самое касается пользователей, групп, прав и прочего, всего что не относится к таблицам. Всё веселее не правда ли? Но леший с этим, давайте вернёмся к импорту. Допустим на 1-м узле кластера у нас есть БД с именем mydb. По идее можно воспользоваться специальной утилитой, входящей в состав MySQL, чтобы изменить в данной БД Storage Engine для всех таблиц: mysql_convert_table_format --type=NDB mydb По идее она должна отработать и будет вам счастье (ну за исключением вышеописанных хранимых процедур, пользователей, групп и прочего). Но это по идее. На самом деле, если у вас большая БД с большой структурой, вы будете получать самые разныее сообщения об ошибках и невозможности импорта. Например: ERROR 157 (HY000): Could not connect to storage engine.. нет подключения к арбитру, а возможно просто зависание последней сессии (или сессий). Зайдите в консоль управления кластером на сервере с арбитром (nbd_mgm), убедитесь что оба узла кластера запущены, а также нелишним будет выполнить команду: "purge stale sessions" для сброса зависших сессий. error 1296 HY000 at line 1392; got error 902, out of memory in NDB kernal, orderd index data ( increase dataMemory) from NDB cluster. что будет означать, что вы выделили недостаточно памяти в параметре DataMemory error чего-то там #sql-XXX опять может не хватать памяти как в DataMemory так и в IndexMemory. Если не помогает, попробуйте прогнать код ошибки через: perror КОДили perror --nbd КОД возможно и получите какое-то осмысленное сообщение, а может и нет! ERROR 1297 (HY000): Got temporary error 233 'Out of operation records in transaction coordinator (increase MaxNoOfConcurrentOperations)' from ndbcluster тут понятное дело, что надо в config.ini на сервере с арбитром завести параметр MaxNoOfConcurrentOperations и увеличить его от значения по умолчанию, которое смотрите в доках по кластеру на сайте MySQL ERROR 1297 (HY000): Got temporary error 410 'REDO log files overloaded, consult online manual (decrease TimeBetweenLocalCheckpoints, and|or incre' from ndbcluster что означает ошибку переполнения буфера наката, о которой я говорил в параграфе о настройках арбитра Ну что, вам хватит? Вы уже поняли, что такое кластер MySQL и всё ещё желаете с ним работать, несмотря на то, что тут подпорка на подпорке? Тогда вот вам ещё ошибка: ERROR 1005 (HY000): Can't create table './mydb/table.frm' (errno: 4318) прогнав через perror получаем "application error". Тут уж без google не разобраться! В итоге оказывается, что кластерный Storage Engine имеет ещё и
Вот тут собственно и сказки конец! Для моей БД эти ограничения оказались критичными. А вам решать самим - стоит ли пользоваться этим сплошным недоразумением или всё-таки жить спокойно. Мой вывод - такой кластер будет работать только на небольших таблицах при небольшом размере БД, но тогда зачем вообще нужен кластер? На нагруженных и тяжёлых БД всё это работать не будет! В продолжении выводов - оптимизируйте структуру БД и запросы, создавайте индексы. Если же несмотря на всё это мощность MySQL вам не хватает и вы думаете о кластере, то лучше посмотрите в сторону PostgreSQL или Oracle.
|
|||
Еще вопросик.
Может он не по теме, но всеже я расчитываю на Вашу снесходительность.
Если например место на машинке закончилось.
Тоесть все следующие записи нужно производить на другую машинку.
Как быть?
Если например мне нужно вытащить последнее сообщение для usera а я не знаю на каком сервере это сообщение.
Тут надо создавать кокую то дополнительную бд и вести логи или есть предусмотренные способы?
Спасибо!
Совершенно не понял ваш
Совершенно не понял ваш вопрос. Место в БД закончилось? Так как бы для этого нужно систему оповещения сделать, которая начнёт вам орать когда места скажем останется 10%, чтобы вы заблаговременно озаботились его расширением.
Все об архитектуре :)
Хотя можно попробывать чтото на подобии того как сделано сдесь!
http://nikita.rockby.net/2008/02/01/ustanovka-i-nastrojka-mysql-klastera...
2 сервака на которых хронятся данные (которые репликуются между сабой)
и два (или три) для кластера (которые принимают нагрузку а инфу берут из реплики) В них даже сама база распологаться не будет.
На кластерные пойдет оснавная нагрузка (SELECT)в выводом данных.
Если нет деньжат на съем 4-х серверов, то можно воспользоваться виртуальными. Для репликации.
Причем реплику можно замутить своими средствами. По скольку на эти сервера будет нужна нагрузка только при записи или изменеии данных. Причем врят ли хостер разрешит копаться в MYSQL настройках.
Гланое чтобы они распологались на разных серверах.
Неплохо былобы их снимать (распологать) на разных хостингах, которые и географически распологаются в дали друг от друга. Ну по крайней мере не в одном здании!!!
Как показывает практика с недавним пожаром в коком то из дата центров. Не помню где!
То все ресурсы, которые там распологались, даже те, которые снимали дополнительные сервера для копирования БД, остались с носом! По тому что сгорел весь дата центр.
Если так сделать, то получится полнофункциональный устойчивый к нагрузкам кластер, в котором в добавок будет надежно хранится информация.
Если Вам кажется, что я не прав, то отпишитесь пожалуйста. Мне будет интересно Ваше мнение по этому поводу.
Спасибо.
Архитектура
Очень интересный пост.
Я сейчас на стадии разработки своего сайта. Перед тем как создавать БД, решил углубится в вопрос ее архитектуры.
Размер одной записи (строки) в таблице не может превышать 8кбайт. При этом любое поле BLOB или TEXT занимает 264 байта
Тоесть с полем TEXT не прокатит?
И если в моей таблице строк больше чем 20320 то тоже работать не будет?
Нахрена тогда этот клестер сдался! :(
Вот и я в конечном итоге к
Вот и я в конечном итоге к такому же мнению пришёл - нахрена оно мне такое сдалось? :)
То что вы писали выше называется мультимастерная репликация работает, но это не кластер :)
А Вы практиковали
А Вы практиковали мультимастерную репликацию?
Если да, То я бы не отказался почитать Ваш постик про это! :)))
И еще вопросик. Я пока только разбираюсь!
Вы немогли бы почетче объяснить саму систему распределения нагрузки между серверами. Не то как она устанавливается, а как она работает.
На сколько я понял, то два кластеных сервера как бы объеденяются в один!?
Куда идут запросы на запись инфы а куда на вывод?
Мня интересует вопрос как сделать именно распределение нагрузки между серверами без дублирования бд. Просто, чтобы при большой нагрузке она распределялась на них обоих.
А записывать инфу они будут на другой сервак. Просто чтобы они руководили самим процесом вместе!
Спасибо.
С мультимастерной
С мультимастерной репликацией я работал, да, но всё-таки она годиться не для всяких задач. Поясню. Если у вас высокий процент запросов на обновление, вставку и удаление - мультимастер репликация будет не самым лучшим решением, ибо тогда велики расходы ресурсов по синхронизации между двумя серверами. В этом случае лучше использовать master-slave репликацию, заточив ваше ПО так, чтобы на мастер шли операции по модификации БД и SELECT'ы, а на slave только SELECT'ы. Балансировка нагрузки в этом случае осуществляется с помощью приложения, которое работает с БД - достаточно простого генератора случайных чисел, чтобы открывать коннект к одному или другому серверу. Разумеется при этом вы должны настроить также замену мастер-сервера на slave в случае если мастер-сервер перестал работать (так называемый standby).
Если же всё-таки вы используете мульти-мастер репликацию, то здесь распределять нагрузку можно как с помощью приложения, так и с помощью mysql-proxy, указав ему оба сервера. Таким образом приложение видит только proxy, а далее уже proxy сам раскидывает по серверам. Статейку если будет время накропаю :)
Если често, то master-slave
Если често, то master-slave репликация меня не очень возбуждает по тому, что очень уж часто встречаются отклики о долгих задержках репликации!
А, что Вы скажете на счет задержек при master-slave репликации?
Таблици у меня будут не большие.
Например:
ID (INT с авто инкрименотом) TEXT и еще пару полей INT и VARCHAR. Выборка будет производится по ID.
Вот такую таблицу master-slave осилит. В смысле какова верятность задержек?
Можно ли одновременно использовать master-slave и MySQL-proxy?
Если да. То:
На сколько я понимаю, если установит MySQL-proxy на WEB сервер то нельзя отправлять на slave только SELECT-ы а на мастер модификацию и запись?
Или если задать:
--proxy-read-only-backend-addresses=host:port
Адрес подчинённого MySQL сервера, работающего в режиме только для чтения. По умолчанию не задан.
Можно задать пару серверов как (slave)?
Если да, то:
Насколько я понял, при таком потходе нет ни какого смысла в (standby)
Исходя из того, что мастер работает только на запиись, То его временно пока он восстанавливается можно заменить SQLITE на WEB сервере.
Вот я почитал про mysql-proxy и у меня сложилось такое впечатление, что это очень хорошая вещь.
Может просто я туго вникаю. Просто уже пару недель занимаюсь онализом этого вопроса и в голове уже такая каша :)))
Спасибо!
Задержки при репликации
Задержки при репликации неизбежны, независимо от метода репликации, потому что данные должны быть переданы с сервера на сервер и записаны в базу. Время задержки будет зависеть от скорости соединения, нагруженности серверов и объёма данных.
Использовать master-slave репликацию и mysql-proxy разумеется можно, если использовать прокси как прослойку между клиентами и серверами. Дальнейшее зависит от требуемой вам логики работы.
Пару серверов как slave задать разумеется можно.
Смысл в standby всегда есть, там где важна непрерывность обслуживания. Про замену не понял - как вы собираетесь потом из SQLite перекачивать данные в MySQL?
как вы собираетесь потом из SQLite перекачивать данные в MySQL?
Через админку зделать к Sqlite запрос и сгенерить из него дамп для MYSQL.
Просто как-то не охото на WEB сервере держать MYSQL. А то вдруг и он упадет!
В общем будем искать оптимальный вариант!
Спасибо.
p/s Ждем постик про мультимастер рпликацию!