Пользователь
0,0
рейтинг
18 октября 2012 в 15:34

Разработка → Percona XtraDB Cluster. Установка и тестирование tutorial recovery mode

Некоторое время назад я задумался о повышении доступности серверов своего проекта. Всё решалось относительно легко за исключением MySQL базы данных. Репликация типа мастер-мастер создаёт проблемы с синхронизацией индексов, а кластерное решение NDBcluster хоть и стремительно развивается, но до сих под не годится для миграции на него готового проекта ввиду большого списка различий и ограничений.

Но есть альтернативное решение под названием Galera Cluster, на котором основан Percona XtraDB Cluster, об установке, настройке и тестировании которого применительно к Ubuntu я и расскажу.


Чем это лучше NDBcluster?


Во-первых: меньшим количеством ограничений (список ограничений NDBcluster: dev.mysql.com/doc/refman/5.5/en/mysql-cluster-limitations.html, список ограничений XtraDB Cluster: www.percona.com/doc/percona-xtradb-cluster/limitation.html).
Мне пришлось только переделать немногочисленные MyISAM таблицы в InnoDB.
Во-вторых: множественными патчами MySQL движка кода от Перконы.
В-третьих: возможностью работы в двухнодовой конфигурации (сразу оговорюсь, что это годно разве что для тестирования).
Ну и наконец, форки MySQL сейчас в тренде :)

Чем это лучше Galera Cluster прикрученного к форку MySQL?


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

Установка


Установка под Ubuntu, как водится, элементарна:
gpg --keyserver  hkp://keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
gpg -a --export CD2EFD2A | sudo apt-key add -
sudo apt-get update
sudo apt-get install percona-xtradb-cluster-server-5.5

Иногда ругается на нерешаемые зависимости. Тогда достаточно сначала установить зависимости, а потом сам сервер.

Сначала ничего не меняя в настройках надо зайти в mysql консоль (достаточно на узле, который будут запущен первым) и добавить юзера для бэкапа:
grant RELOAD, LOCK TABLES, REPLICATION CLIENT, FILE on *.* to backup@localhost identified by 'password';


Потом потребуется одна небольшая переделочка. Дело в том что в Убунте симлинк с sh ведёт на dash, а стартовый скрипт кластера заточен под bash. Если нет никаких противопоказаний, можно уладить это общесистемно:
dpkg-reconfigure dash

Ответить «нет».

Так как базы после запуска кластера станут полностью идентичными, то и пароль системного юзера на всех нодах станет как на первой. Поэтому надо скопировать файл /etc/mysql/debian.cnf с сервера, который будет запущен первым на остальные.

Мои конфиги выглядят так:
[mysqld_safe]
wsrep_urls=gcomm://192.168.1.1:3400,gcomm://192.168.1.2:3400,gcomm://

[mysqld]
port=3306
socket=/var/run/mysqld/mysqld.sock
datadir=/var/lib/mysql
basedir=/usr
user=mysql
log_error=error.log
binlog_format=ROW
wsrep_provider=/usr/lib/libgalera_smm.so
wsrep_sst_receive_address=192.168.1.1:3500
wsrep_node_incoming_address=192.168.1.1
wsrep_slave_threads=2
wsrep_cluster_name=cluster0
wsrep_provider_options="gmcast.listen_addr=tcp://192.168.1.1:3400;"
wsrep_sst_method=xtrabackup
wsrep_sst_auth=backup:password
wsrep_node_name=node0
innodb_locks_unsafe_for_binlog=1
innodb_autoinc_lock_mode=2
innodb_buffer_pool_size=5000M
innodb_log_file_size=256M
innodb_log_buffer_size=4M

[client]
port=3306
socket=/var/run/mysqld/mysqld.sock

Проверьте расположение libgalera_smm.so.
Значение параметра wsrep_slave_threads рекомендуется ставить как количество ядер*4.
В wsrep_sst_auth указывается логин и пароль пользователя для бэкапов.
innodb_buffer_pool_size, innodb_log_file_size, innodb_log_buffer_size — влияют на производительность, и подбираются экспериментальным путём. В моём случае на каждом узле стоит 8 гигов ОЗУ.

Для добавления нод надо добавлять их в строку wsrep_urls (в конце строки должна быть пустая запись).
Все ip адреса, встречающиеся в файле (кроме строки wsrep_urls) указывают на адрес текущей ноды. Их и надо менять при распространении этого файла на остальные узлы. Также надо менять имя ноды в wsrep_node_name.

В моей настройке порт 3400 используется для синхронизации, порт 3500 — для заливки дампа, порт 3306 (стандартный) — для подключения клиента.

Можно запустить несколько нод на одной машине, выдав им разные порты. Если решите так сделать, то надо насоздавать несколько конфигурационных файлов в /etc/mysql и запускать сервер например такой командой:
/usr/bin/mysqld_safe --defaults-file=/etc/mysql/my0.cnf

Учтите, что xtrabackup умеет подключаться только по стандартному сокету /var/run/mysqld/mysqld.sock (параметры из конфига игнорирует). Так что в этом случае придётся его не использовать: wsrep_sst_method=rsync


Ну и в завершение, перезапускаем демона:
sudo service mysql restart

Если что-то пошло не так, смотрим в /var/lib/mysql/error.log.
Обычно надо стереть /var/lib/mysql/ib_logfile* из-за изменения размеров лога в конфиге.

Иногда проще стереть вообще весь /var/lib/mysql/ (если в базах нет ничего ценного) и пересоздать дефолтные базы:
mysql_install_db


Ещё некоторые возможные ошибки я привёл в конце статьи.

Количество узлов


Производитель рекомендует не менее трёх, но есть отличия от NDB: изначально все ноды одного ранга и имеют одинаковый функционал. Ничто не мешает сделать и 2 ноды.

С двухнодовой конфигурацией всё просто и грустно: работает пока не пропадёт связь между узлами. В этом случае кластер в целях защиты от split-brain вообще не даёт ничего делать. Есть пара опций для конфига, при которых он будет работать даже при обрыве связи, но, понятно дело, вреда от них больше чем пользы — при появлении связи то мы получим 2 разных копии базы, которые непонятно как объединять.

Вариант с тремя нодами в моём случае не подходил, так как у меня только 2 сервера на колокейшене, и добавленный к ним третий где-нибудь на офисном канале сильно бы подпортил производительность, ведь скорость работы кластера определяется скоростью работы самого медленного его узла.

Но есть решение: Galera Arbitator. Это неполноценный узел, который не хранит баз, и которому не нужен быстрый канал, но пока нода держит с ним связь она будет продолжать работать. Этот узел настолько неполноценный, что он даже конфиг не использует, все параметры передаются ему через командную строку.
Из параметров нужен только адрес одной из нормальных нод и название кластера:
garbd -a gcomm://192.168.1.1:3400 -g cluster0


Тесты


Тестировал стандартной утилитой sql-bench из пакета test сначала узлы по отдельности, а потом кластер. Софт при этом не менялся — percona-xtradb-cluster.

Установка и запуск тестового пакета:
apt-get install percona-server-test-5.5 libdbd-mysql-perl
cd /usr/share/sql-bench/sql-bench/
perl run-all-tests --server=mysql --user=root --password=<password>


Сначала тестировал на двух идентичных быстрых машинах с SSD.
Результаты первого прогона выкинул, так как они были в насколько раз лучше последующих (спишем на чистые SSD).

Это 1 нода:
alter-table: Total time: 17 wallclock secs ( 0.04 usr  0.00 sys +  0.00 cusr  0.00 csys =  0.04 CPU)
ATIS: Total time:  7 wallclock secs ( 2.48 usr  0.16 sys +  0.00 cusr  0.00 csys =  2.64 CPU)
big-tables: Total time: 10 wallclock secs ( 1.87 usr  0.34 sys +  0.00 cusr  0.00 csys =  2.21 CPU)
connect: Total time: 64 wallclock secs (19.80 usr  5.68 sys +  0.00 cusr  0.00 csys = 25.48 CPU)
create: Total time: 548 wallclock secs ( 3.35 usr  1.66 sys +  0.00 cusr  0.00 csys =  5.01 CPU)
insert: Total time: 531 wallclock secs (155.04 usr 19.15 sys +  0.00 cusr  0.00 csys = 174.19 CPU)
select: Total time: 168 wallclock secs (17.93 usr  1.90 sys +  0.00 cusr  0.00 csys = 19.83 CPU)
transactions: Test skipped because the database doesn't support transactions
wisconsin: Total time:  5 wallclock secs ( 1.31 usr  0.18 sys +  0.00 cusr  0.00 csys =  1.49 CPU)


Это кластер:
alter-table: Total time: 21 wallclock secs ( 0.04 usr  0.05 sys +  0.00 cusr  0.00 csys =  0.09 CPU)
ATIS: Total time: 21 wallclock secs ( 2.76 usr  0.30 sys +  0.00 cusr  0.00 csys =  3.06 CPU)
big-tables: Total time: 17 wallclock secs ( 1.98 usr  0.40 sys +  0.00 cusr  0.00 csys =  2.38 CPU)
connect: Total time: 67 wallclock secs (21.13 usr  5.59 sys +  0.00 cusr  0.00 csys = 26.72 CPU)
create: Total time: 597 wallclock secs ( 3.55 usr  1.55 sys +  0.00 cusr  0.00 csys =  5.10 CPU)
insert: Total time: 1710 wallclock secs (164.66 usr 35.25 sys +  0.00 cusr  0.00 csys = 199.91 CPU)
select: Total time: 187 wallclock secs (19.49 usr  2.44 sys +  0.00 cusr  0.00 csys = 21.93 CPU)
transactions: Test skipped because the database doesn't support transactions
wisconsin: Total time: 47 wallclock secs ( 1.62 usr  0.88 sys +  0.00 cusr  0.00 csys =  2.50 CPU)

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

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

Первая нода отдельно:
alter-table: Total time: 55 wallclock secs ( 0.04 usr  0.02 sys +  0.00 cusr  0.00 csys =  0.06 CPU)
ATIS: Total time: 10 wallclock secs ( 2.40 usr  0.14 sys +  0.00 cusr  0.00 csys =  2.54 CPU)
big-tables: Total time:  7 wallclock secs ( 1.23 usr  0.15 sys +  0.00 cusr  0.00 csys =  1.38 CPU)
connect: Total time: 53 wallclock secs (16.31 usr  7.65 sys +  0.00 cusr  0.00 csys = 23.96 CPU)
create: Total time: 3215 wallclock secs ( 2.58 usr  0.83 sys +  0.00 cusr  0.00 csys =  3.41 CPU)
insert: Total time: 541 wallclock secs (142.41 usr 22.53 sys +  0.00 cusr  0.00 csys = 164.94 CPU)
select: Total time: 154 wallclock secs (12.66 usr  1.34 sys +  0.00 cusr  0.00 csys = 14.00 CPU)
transactions: Test skipped because the database doesn't support transactions
wisconsin: Total time:  4 wallclock secs ( 1.15 usr  0.29 sys +  0.00 cusr  0.00 csys =  1.44 CPU)


Вторая нода отдельно:
alter-table: Total time: 59 wallclock secs ( 0.03 usr  0.03 sys +  0.00 cusr  0.00 csys =  0.06 CPU)
ATIS: Total time: 11 wallclock secs ( 2.35 usr  0.23 sys +  0.00 cusr  0.00 csys =  2.58 CPU)
big-tables: Total time: 11 wallclock secs ( 1.92 usr  0.30 sys +  0.00 cusr  0.00 csys =  2.22 CPU)
connect: Total time: 64 wallclock secs (19.67 usr  5.84 sys +  0.00 cusr  0.00 csys = 25.51 CPU)
create: Total time: 4592 wallclock secs ( 3.90 usr  1.39 sys +  0.00 cusr  0.00 csys =  5.29 CPU)
insert: Total time: 581 wallclock secs (148.16 usr 19.80 sys +  0.00 cusr  0.00 csys = 167.96 CPU)
select: Total time: 168 wallclock secs (18.45 usr  2.07 sys +  0.00 cusr  0.00 csys = 20.52 CPU)
transactions: Test skipped because the database doesn't support transactions
wisconsin: Total time:  5 wallclock secs ( 1.18 usr  0.25 sys +  0.00 cusr  0.00 csys =  1.43 CPU)


Кластер:
alter-table: Total time: 110 wallclock secs ( 0.04 usr  0.02 sys +  0.00 cusr  0.00 csys =  0.06 CPU)
ATIS: Total time: 496 wallclock secs ( 1.61 usr  0.17 sys +  0.00 cusr  0.00 csys =  1.78 CPU)
big-tables: Total time: 116 wallclock secs ( 1.02 usr  0.16 sys +  0.00 cusr  0.00 csys =  1.18 CPU)
connect: Total time: 34 wallclock secs (10.98 usr  2.49 sys +  0.00 cusr  0.00 csys = 13.47 CPU)
create: Total time: 4638 wallclock secs ( 2.42 usr  0.91 sys +  0.00 cusr  0.00 csys =  3.33 CPU)
insert: Estimated total time: 43470.8 wallclock secs (106.50 usr 15.34 sys +  0.00 cusr  0.00 csys = 121.84 CPU)
select: Total time: 631 wallclock secs (11.02 usr  1.02 sys +  0.00 cusr  0.00 csys = 12.04 CPU)
transactions: Test skipped because the database doesn't support transactions
wisconsin: Total time: 1576 wallclock secs ( 1.37 usr  0.44 sys +  0.00 cusr  0.00 csys =  1.81 CPU)


Однако предположение не подтвердилось: операция записи на винчестерных компьютерах в кластере замедлилась аж в 10 раз. Чем это объяснить — я не знаю.

Что касается использования это в реальном продакшене — каждый выбирает для себя. Мне такое относительное снижение производительности некритично ввиду малых абсолютных цифр.

Возможные проблемы и методы их решения


1.
WSREP: Process completed with error: wsrep_sst_xtrabackup 'donor' '192.168.1.1:6000/xtrabackup_sst' 'backup:password' '/var/lib/mysql2/' '/etc/mysql/my2.cnf' '9bdd7773-0cb4-11e2-0800-8e876ebc6b70' '0' '0': 22 (Invalid argument)

xtrabackup не смог подключиться к базе. Вы точно не пытаетесь сделать несколько нод на одной машине? Смотрите подробности в innobackup.backup.log.

2.
121002 15:19:54 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql0
/usr/bin/mysqld_safe: 172: [: gcomm://: unexpected operator

Вместо bash используется другой интерпретатор. Либо в mysqld_safe измените первую строку, либо правьте симлинки.

3. Если MyISAM таблицы создаются, но не наполняются из дампа, то так и должно быть: поддерживается только InnoDB.

4. Если на все команды пишущие или читающие данные, MySQL клиент выдаёт «Unknown command»: это защита от split-brain при обрыве связи между узлами.
unwrecker @unwrecker
карма
0,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (33)

  • +1
    Одно плохо, что при «split-brain», оно выдает «Invalid command», а не свою, «родную» ошибку.
    • 0
      Кстати, не invalid, a unknown. Сейчас исправлю.

      Полностью ошибка выглядит так:
      ERROR 1047 (08S01): Unknown command

      Состояние кластера ещё можно узнать командой clustercheck
  • 0
    Какое то невнятное падение производительности.
    Пробовали развернуть на centos?
    • 0
      Нет. Но беглый осмотр аналогичных логов с NDBcluster говорит от том, что падение вполне себе обычное.
  • +1
    Пару замечаний.
    1) В конфигурации с двумя нодами, при подключении новой (второй) ноды, или при восстановлении ее после сбоя, первая нода отключится на время выполнения дампа, который потом сливается на вторую ноду.
    На время дампа первя нода недоступна, как и весь кластер.
    В случае с тремя нодами, при подключении новой ноды, останавливается последняя (вторая), а первая продолжает обсдуживать запросы.
    Рекомендация делать три ноды не с потолка взята.

    2) Строка gcomm:// в конфиге предполагает поиск мастера через широковещательные запросы,
    в случае, если сервера в разных сетях (разные VDS, у разных хостеров), это не сработает.
    В локальной сети — да.
    Достаточно указать адрес первой ноды. Она уже отдаст адрес последней ноды в кластере (второй, например), с которой будет выполняться первоначальная синхронизация новой ноды.

    3) По производительности, смотрите IOPS дисков. Обычно это следствие слишком активной записи в журнал.
    Ведь происходит запись в саму БД (файл на диске) и в журнал репликации. Кроме того, еще и в логи какие-нибудь.

    4) Хорошим решением будет haproxy с двумя адресами. Пусть 3306 на чтение (с равномерной балансировкой), а 3307 на запись, без балансировки, на один из доступных серверов. С него и пойдет репликация на остальные. В случае выхода из строя первого сервера, его функции перейдут на второй автоматически. В этом случае минимальна вероятность split-brain.

    • 0
      За замечания спасибо. Особенно полезным мне будет второе. А насчёт первого я писал, что при использовании xtrabackup ноды останавливаться не будут на время дампа.
      • 0
        Не уверен за xtrabackup… Перепроверю.
        У меня останаливалось обслуживание на время подключения второй ноды.
        Третья поднималась со второй, а первая обслуживала запросы.
        • 0
          Скажите, вы не проверели случайно?
          • 0
            Пока нет. Другие задачи…
            Попробуйте самостоятельно.
            Контейнер OpenVZ осилите или поделиться?
            • 0
              Осилю конечно. Просто меня интересует кластерное решение mysql. Пока не могу определится на чем остановится или galera или percona. Вроде бы mariadb использует percona.

              Может быть порекомендуете, что почитать? Я хотел бы понять, что мне подайдет для моих задач.
              Планирую для начала 3 Master-Master сервера.
              • 0
                Не «или galera или percona», а «и galera и percona»…

                www.percona.com/doc/percona-server/5.5

                • 0
                  Так ясно. Какие тогда плюсы перед mariadb-galera?

                  Понятно, что mariadb-galera в стадии альфа. Я так понимаю патчи от percona так же включены в mariadb, или я не прав?
                  • 0
                    Не знаю. Может и прав…
                    Попробуйте, погоняйте под нагрузкой…
                    Убейте одну из баз…
                    Там видно будет.
              • 0
                Если не секрет, на чем остановились?
                Ищу товарищей по несчастью, мучаю третью неделю Percona XtraDB Cluster, хочется мнений / отзывов
                • 0
                  Думаю все же percona.

                  Выбор прост. Много кто использует в серьзных вещах, есть платная поддержка.
                  mariadb-galera находится в альфа версии, выход из этой стадии непонятен, поддержки платной нет :)
                  Хотя сама mariadb у нас на текущий момент рабоает без нареканий.
    • 0
      по п.4. вопрос — при выходе из строя той ноды, на которую идет запись, haproxy сам переключит запись на другие? как это возможно, если мы к примеру жестко вписали ip ноды?
      • 0
        В конфигурации haproxy менее двух адресов писать не имеет смысла…
        А если более одного, то переключит…
        При этом есть несколько режимов распределения нагрузки, один из которых «кто первый попал под раздачу, тот и будет крайним, пока не сдохнет». Он нам и нужен для записи.
        Для чтения более другой вариант.
        • 0
          ясно, меня собственно что и удивило — если тупо писать на один жестко заданный узел, то зачем прокси? спасибо за объяснение
          • 0
            Я ж не сказал, что писать «тупо»…
            Без балансировки и на один из доступных…
            Сеанет он недоступным, будем писать на другой, пока будет доступным…

            • 0
              > Сеанет он недоступным, будем писать на другой, пока будет доступным…
              если я правильно понял, не «мы», а haproxy =)
              • 0
                Если хочешь найти баг, стань багом…
                Думай как баг, поступай как баг и ты поймаешь баг…

                Сисадмин обязан отождествлять себя с сервером и прокручивать в голове все связи и взаимодействия… Иначе не получится.

                «Мы», в данном случае, haproxy и я…
                Я придумал, как писать, а он выполняет диррективы настроек, заданные мной в конфигурационном файле…

                Где-то в таком ракурсе…
                ;)
                • 0
                  все правильно :)
    • 0
      А чем обусловлена большая вероятность split-brain, если писать сразу на 3 сервера? Это же мультимастер, и это требование выглядит немного странно
    • 0
      Наткнулся на глюк, которого по идее в кластере возникать не должно.

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

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

      Что бы это могло быть?
      • 0
        А можно детали проги приподраскрыть, чтобы можно было воспроизвести у себя?
        • 0
          Я просто повесил прогу, которая в бесконечном цикле проходится по серверам и сравнивает последнюю строку в каждой таблице. Если что-то не совпадает — выдаёт сообщение. И такие сообщения при нормальной работе сайта периодически выдаются. При нагрузочном же тестировании выдаются постоянно.

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

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

          Сама программа (PHP)
          <?php
          require dirname(__FILE__).'/config.php';

          while(true)
          {
          $ts=date('r');
          // echo «старт\n»;
          foreach ($config['db'] as $key=>$val)
          {
          if(!$db[$key]=mysql_connect($val['host'], $val['user'], $val['password']))
          die(«Ошибка подключения к БД: ». var_dump($val)."\n");
          }
          // echo «подключено\n»;

          $tables=array();
          $tables_summary=array();

          // считываем названия всех таблиц во всех базах
          foreach($config['db'] as $key=>$val)
          {
          $db_=$db[$key];
          if(!mysql_query(«USE {$config['scheme']}», $db_))
          echo $ts.' Ошибка выбора таблицы: '.mysql_error($db_)."\n";
          mysql_query(«SET names 'utf8'», $db_);
          if($res=mysql_query(«SHOW TABLES», $db_))
          {
          while($row=mysql_fetch_row($res))
          {
          $tables[$key][$row[0]]=true;
          $tables_summary[$row[0]]=true;
          }
          }
          else
          echo $ts.' '.mysql_error($db_);
          }

          // echo «проверка таблиц\n»;
          // проверяем наличие таблиц во всех базах
          foreach($tables_summary as $key=>$val)
          {
          foreach($config['db'] as $key0=>$val0)
          {
          if(!@$tables[$key0][$key])
          {
          echo "$ts В базе $key0 нет таблицы $key. Таблица исключена из проверки.\n";
          $tables_summary[$key]=false;
          }
          }
          }

          //system(«clear»);

          // echo «проверка данных\n»;
          foreach($tables_summary as $key=>$val)
          {
          if($val)
          {
          // лочим таблицы
          foreach($config['db'] as $key0=>$val0)
          {
          $db_=$db[$key0];
          if(mysql_query(«START TRANSACTION», $db_))
          mysql_query(«SELECT 1 FROM $key LIMIT 1», $db_); // чтоб запустилась блокировка внутри транзакции надо что-нибудь прочитать из таблицы
          if(mysql_error($db_))
          echo $ts.' Ошибка блокировки: '.mysql_error($db_)."\n";
          }
          //echo "$key\t";
          unset($id_summary);
          unset($id_name);
          foreach($config['db'] as $key0=>$val0)
          {
          if(!isset($id_name))
          {
          $db_=$db[$key0];
          // получаем имя первой колонки
          $res=mysql_query(«DESCRIBE $key», $db_);
          $row=mysql_fetch_row($res);
          $id_name=$row[0];
          //echo "$id_name\t";
          }

          // получаем максимальный id
          $res=mysql_query(«SELECT MAX($id_name) FROM $key», $db_);
          $row=mysql_fetch_row($res);
          if(is_numeric($row[0]))
          {
          //echo " $row[0] ";
          if(!isset($id_summary))
          {
          $id_summary=$row[0];
          }
          else
          {
          if($id_summary<$row[0])
          {
          echo "$ts В базе $key0 в таблице $key ключ $id_name опережает другие на ".$row[0]-$id_summary."\n";
          }
          if($id_summary>$row[0])
          {
          echo "$ts В базе $key0 в таблице $key ключ $id_name отстаёт от других на ".$row[0]-$id_summary."\n";
          $id_summary=$row[0]; // В $id_summary попадает значение id, которое есть во всех базах
          }
          }
          }
          else
          unset($id_summary);
          }
          if(@$id_summary)
          {
          // echo «сравнение данных\n»;
          $data=array();
          foreach($config['db'] as $key0=>$val0)
          {
          $db_=$db[$key0];
          // считываем по одной строке из каждой базы
          $res=mysql_query(«SELECT * FROM $key WHERE $id_name='$id_summary' LIMIT 1», $db_);
          $row=mysql_fetch_row($res);
          if($data)
          {
          if(is_array($data) && is_array($row))
          $result = array_diff($data, $row);
          elseif($data!=$row)
          $result=true;
          if($result || !$row)
          {
          echo "$ts Есть расхождения в таблице $key, $id_name='$id_summary':\n";
          print_r($data);
          print_r($row);
          }
          }
          else
          {
          if($row)
          $data=$row;
          }
          }
          }
          // разлочиваем таблицы
          foreach($config['db'] as $key0=>$val0)
          {
          $db_=$db[$key0];
          mysql_query(«COMMIT», $db_);
          if(mysql_error($db_))
          echo $ts.' Ошибка разблокировки: '.mysql_error($db_)."\n";
          }
          }
          }
          //echo «закрытие соединений\n»;
          foreach($config['db'] as $key0=>$val0)
          {
          mysql_close($db[$key0]);
          }
          usleep(10);
          }

  • 0
    А как распараллеливать запросы на ноды в таком кластере?
    Понятно что в приложении можно, но интересует вариант с прозрачным коннектом и балансировкой. Какие есть варианты?
    • 0
      mysql proxy
      • 0
        Некоторые рекомендуют haproxy.
        Я присоединяюсь к рекомендациям.
        haproxy умеет не только mysql, можно делать более управляемые сервисы.

        Но, на вкус и цвет…
  • 0
    спасибо

    еще вопрос — вот вы пишите о том что тестировали и кластер, и ноды отдельно — имеется в виду, что ноды выкидывались на время из кластера и на стандартном mysql сервере проводился тест?
    • 0
      Просто убирал из конфига всё относящееся к кластеру, и он работал как самостоятельный сервер.
      • 0
        спс, ясно
        да, система выглядит привлекательно, но без ложки дегтя не бывает — такое проседание по записи удручает.
        • 0
          Я думаю, надо копать в сторону более быстрых SSD. У меня были вполне рядовые OCZ Vertex 3

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.