В процессе мучений перелопатил тонну статей и решил написать подробнокомментируемый мануал. Тем более, что информации по конфигурированию multimaster и на русском языке очень мало и она какая-то кусочная.
Немного вводной. Чтобы Bucardo заработал, мы должы:
1) Сказать ему какие базы-участники на каких серверах вообще существуют.
2) Сказать ему какие таблицы участвуют в репликации.
Внимание: если разработчики добавят в приложение новую таблицу, мы должны об этом сообщить bucardo.
Тоже самое касается изменения схемы существующих таблиц.
3) Сказать ему какие группы таблиц существуют и какие таблицы попадают в какие группы. Группы нужны на тот случай, если между разными серверами надо реплицировать разные таблицы. Удобнее работать с группой, чем каждую отдельно указывать (очень похоже на группы в Nagios).
4) Сказать ему какие группы баз данных существуют. Цель — та же, что и для таблиц.
Перейдем к установке. Вариант для Debian 7.
Подразумевается, что пакеты postgresql-9.1 и postgresql-client-9.1 уже установлены.
Предварительная подготовка.
Серверы будут называться node1 и node2.
Обязательно также проверить, чтобы все участвующие PostreSQL-серверы слушали внешние интерфейсы:
# netstat -plnt4 | grep 5432
tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN 12345/postgres
Устанавливаем пакет Bucardo и поддержку PL/Perl для PostgreSQL на каждом из серверов:
# apt-get install bucardo postgresql-plperl-9.1
Активируем на каждом из серверов:
# sed -i 's/ENABLED=0/ENABLED=1/' /etc/default/bucardo
Мейнтенеры пакета почему-то не догадались создать директорию под PID, поэтому создадим ее сами на каждом из серверов:
# mkdir /var/run/bucardo
Удостоверяемся, что мы можем подключиться через TCP-сокет к СУБД на каждом из серверов:
# psql -U postgres -h 127.0.0.1
Если не помните пароль, то простейшая инструкция здесь.
Если PG не хочет принимать запросы с конкретного адреса конкретного пользователя, то настройте /etc/postgresql/9.1/main/pg_hba.conf
Далее будет происходить инициализация базы. Она будет создана пользователем postgres, но наполнена пользователем bucardo, поэтому можно упереться в проблему подключения.
Дабы ее избежать, заранее внесем строку для него в /etc/postgresql/9.1/main/pg_hba.conf. Кроме того, уже в процессе работы Bucardo будет обращаться не только к своей ноде кластера, но и к парной. Поэтому ее тоже не забываем. Если у Вас в кластере серверов больше, то не забудьте о них. На каждом из серверов:
host all bucardo 127.0.0.1/32 trust
host all bucardo SECOND.NODE.IP.ADDRESS/32 password
После этого рестартанем СУБД:
# pg_ctlcluster 9.1 main restart
Установка Bucardo.
Утилита bucardo_ctl в последних версиях Debian была заменена на bucardo, поэтому мы будем использовать ее.
Инициализируем базу данных:
# bucardo install
Диалог выглядит примерно так:
# bucardo install
This will install the bucardo database into an existing Postgres cluster.
Postgres must have been compiled with Perl support,
and you must connect as a superuser
Current connection settings:
1. Host: localhost
2. Port: 5432
3. User: postgres
4. Database: postgres
5. PID directory: /var/run/bucardo
Enter a number to change it, P to proceed, or Q to quit: P
Password for user postgres:
Postgres version is: 9.1
Password for user postgres:
Creating superuser 'bucardo'
Password for user postgres:
Attempting to create and populate the bucardo database and schema
Password for user postgres:
Database creation is complete
Updated configuration setting "piddir"
Installation is now complete.
If you see errors or need help, please email bucardo-general@bucardo.org
You may want to check over the configuration variables next, by running:
bucardo show all
Change any setting by using: bucardo set foo=bar
В процесс инициализации база была создана из файла /usr/share/bucardo/bucardo.schema, поэтому нет необходимости ее заполнять руками, как это описано в мануалах прошлых версий.
Bucardo установлен, можно его запустить:
# bucardo start
Настройка репликации.
Прежде, чем настроить репликацию, создадим тестовые базы, которые будем реплицировать.
На каждом из серверов:
# psql -U postgres -c "CREATE DATABASE mydb;"
# psql -U postgres mydb -c "CREATE TABLE mytable ( num123 integer PRIMARY KEY, abc varchar(10) );"
Еще один важный момент касательно безопасности. После добавления реплицируемой базы в настройку, Bucardo впишет пароль пользователя в базу. А так как при установке он его не запросил, то сделал его точно таким же, как у пользователя postgres. Другими словами у нас в базе bucardo будет храниться в открытом виде пароль от суперпользователя, что несколько опасно.
Поэтому сделаем ему другой пароль. На каждом из серверов:
# psql -U postgres -c "ALTER USER bucardo WITH PASSWORD 'eiP4uSash5';"
Далее даем информацию Bucardo, как подключиться к базе данных, которую будем реплицировать. Я не поклонник Unix-сокетов в условиях высокой нагрузки (отдельная тема для разговора), поэтому даже там, где локально, укажем TCP-сокет.
ВНИМАНИЕ: Это мы делаем на сервере node1. И вообще далее работаем только с node1 пока не уточнено, что надо делать на обоих.
Добавим локальную (mydb_node1) и ее удаленную копию (mydb_node2) с сервера node2:
# bucardo add database mydb_node1 dbname=mydb dbhost=127.0.0.1 dbuser=bucardo dbpass=eiP4uSash5
Added database "mydb_node1"
# bucardo add database mydb_node2 dbname=mydb dbhost=node2.example.com dbuser=bucardo dbpass=eiP4uSash5
Added database "mydb_node2"
Здесь:
mydb_nodeX — внутренее обозначение базы. Это имя Bucardo использует во внутренних работах с базой.
dbname=mydb — реальное имя базы в PostgreSQL, на которое ссылается mydb_nodeX.
dbuser=bucardo — под кем Bucardo будет подключаться к СУБД, чтобы работать с этой базой.
Результат мы можем видеть так:
# bucardo list database
Database: mydb_node1 Status: active Conn: psql -p -U bucardo -d mydb -h 127.0.0.1
Database: mydb_node2 Status: active Conn: psql -p -U bucardo -d mydb -h node2.example.com
Эти настройки берутся из таблицы db базы bucardo, где и сидит упомянутый выше пароль:
# psql -U postgres bucardo -c "SELECT name,dbname,dbhost,dbuser,dbpass,status FROM db;"
name | dbname | dbhost | dbuser | dbpass | status
------------+--------+-------------------+---------+------------+--------
mydb_node1 | mydb | 127.0.0.1 | bucardo | eiP4uSash5 | active
mydb_node2 | mydb | node2b.forbet.net | bucardo | eiP4uSash5 | active
(2 rows)
Теперь нам надо добавить таблицу, которую мы будем между ними реплицировать. В большинстве случаев люди реплицируют целиком базу, поэтому уж сразу все добавим (группа таблиц(herd) создастся автоматически). Если разработчики придумают новую таблицу, мы просто добавим ее потом в группу и все само заработает — так как дальнейшие настройки будут касаться группы целиком.
# bucardo add table all --db=mydb_node1 --herd=mydb_herd
Creating herd: mydb_herd
Added table public.mytable to herd mydb_herd
New tables added: 1
Здесь:
--herd=mydb_herd — имя группы таблиц, чтобы потом настраивать синхронизацию не к каждой отдельно, а всем скопом.
И сразу можем ее посмотреть:
# bucardo list tables
1. Table: public.mytable DB: mydb_node1 PK: num123 (int4)
Здесь нужно заострить внимание на PK. Bucardo, похоже, не работает с таблицами без первичных ключей. Вы потом не сможете синк сделать.
И группу тоже видно:
# bucardo list herd
Herd: mydb_herd DB: mydb_node1 Members: public.mytable
Тоже самое касается последовательностей. В нашем примере их нет, но вдруг кто использует. Группу под них свою создавать не будем, чтобы не усложнять. Вероятность того, что таблицы реплицируются в одном направлении, а последовательности в другом — чрезвычайно мала. Поэтому пусть будет одна группа для таблиц и последовательностей:
# bucardo add sequence all --db=mydb_node1 --herd=mydb_herd
Sorry, no sequences were found
New sequences added: 0
Следующая наша задача создать репликационную группу. В этой группе мы скажем какая база будет источником, а какая реципиентом данных. Создадим сначала саму группу, пока пустую:
# bucardo add dbgoup other_mydb_servers
Created database group "mydb_servers_group"
Добавляем оба наших сервера в группу, указывая кто какую роль будет исполнять. Это единственная точка, где отличаеся настройка master-slave от master-master.
Изначально можно подумать, что source — это источник, а target — это реципиент. На самом деле это не совсем так. source — это тот, кто работает и как источник и как реципиент, а target — только реципиент.
То есть если у нас master-slave, то указываем одного source, а второго target. А если у нас master-master, то оба будут source, а target'ов не будет вообще.
Вариант для MASTER-->SLAVE:
# bucardo add dbgroup mydb_servers_group mydb_node1:source
Added database "mydb_node1" to group "mydb_servers_group" as source
# bucardo add dbgroup mydb_servers_group mydb_node2:target
Added database "mydb_node2" to group "mydb_servers_group" as target
Вариант для MASTER<-->MASTER:
# bucardo add dbgroup mydb_servers_group mydb_node1:source
Added database "mydb_node1" to group "mydb_servers_group" as source
# bucardo add dbgroup mydb_servers_group mydb_node2:source
Added database "mydb_node2" to group "mydb_servers_group" as source
Все! У нас написано какие есть базы. Написано какие есть в них таблицы. Написано кто в какой группе. Осталось сказать заключительный штрих — сказать какая группа таблиц будет «курсировть» между базами какой группы. Другими словами — создать «синк»:
# bucardo add sync mydb_sync herd=mydb_herd dbs=mydb_servers_group
Added sync "mydb_sync"
Можем посмотреть, что у нас получилось:
# bucardo list sync
Sync: mydb_sync Herd: mydb_herd [Active]
DB group mydb_servers_group: mydb_node1 (source) mydb_node2 (source или target - как настроили)
После изменения настроек обязательно рестартовать Bucardo:
# bucardo restart
========
Проверка:
на первой ноде node1 запускаем:
# psql -U postgres mydb -c "INSERT INTO mytable VALUES (1, 'a');"
а на второй node2 проверяем:
# psql -U postgres mydb -c "SELECT * FROM mytable;"
кто сделал multimaster, тому надо и в обратном направлении проверять. Создаете на node2, а проверяете на node1.
========
Вопросы, которые возникнут у большинства людей:
1) Что будет с таблицей на target-базе, если таблица на source-базе была изменена пока Bucardo был выключен или сеть была недоступна?
Ответ: все Ok. При старте или при появлении сети Bucardo передаст данные на target-сервер. Так что target-сервер может ломаться как угодно. Единственное требование — на нем должна быть та же схема данных (структура таблиц), что и на первом.
__
2) Если база большая (десятки-сотни гигабайт), Bucardo «отламывается» и не синхронизирует до конца. Как быть?
Ответ: переведите sync в состояние неактивного. Но Bucardo должен быть включен для source-базы для логивания запросов.
bucardo update sync mydb_sync status=inactive (для multimaster на всех нодах)
Далее делаете pg_dump/pg_restore руками и возвращаете синк в активный режим (для multimaster сначала на той, куда шли новые запросы после запуска дампа).
Автор: Singaporian