Ads 468x60px

пятница, 10 августа 2012 г.

Debian squeeze - репликация postgresql 8.4.

Задача: настроить master/slave репликацию базы postgresql, с которой работает dovecot, настроенный по заметке Dovecot 2 (imaps) + postgresql.
Параметры:
Операционная система на обоих серверах Debian squeeze
Master: 192.168.30.9, имя сервера cl09
Slave: 192.168.30.10, имя сервера cl10
Субд postgresql 8.4; система репликаций slony; Имя базы: vmail
Приводимые примеры команд даются с учетом наличия настройки ssh,на master сервере, где в качестве псевдонима для slave использовано его имя(cl10).
Подготовка систем.
Postgresql.
На обоих серверах в файле /etc/postgresql/8.4/main/pg_hba.conf редактируем раздел описывающий подключение по IPv4, добавляя правила подключения для пользователей с IP адресов наших серверов. Для редактирования файла на slave сервере, достаточно запустить команду:
cl09:~$ ssh cl10 -t "sudo vim /etc/postgresql/8.4/main/pg_hba.conf"
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
host    all         all         192.168.30.9/32          md5
host    all         all         192.168.30.10/32          md5
А так же не забываем про файл /etc/postgresql/8.4/main/postgresql.conf, где необходим указать IP адреса с которых принимать подключения, если данная директива раннее не изменялась, то правку можно внести следующими командами:
cl09:~$ sudo sed -i "s|^#\(listen_addresses =\).*\(#\)|\1 \'localhost, 192.168.30.9\' \2|" /etc/postgresql/8.4/main/postgresql.conf
И на slave сервере
cl09:~$ ssh cl10 -t "sudo sed -i \"s|^#\(listen_addresses =\).*\(#\)|\1 \'localhost, 192.168.30.10\' \2|\" /etc/postgresql/8.4/main/postgresql.conf"
Перезапускаем postgres на обоих серверах
cl09:~$ sudo service postgresql restart
cl09:~$ ssh cl10 -t sudo service postgresql restart
Проверяем, что все работает верно:
cl09:~$ psql vmail -U vmail -h 192.168.30.10 -c "\copyright"
и
cl09:~$ ssh cl10 -t 'psql vmail -U vmail -h 192.168.30.9 -c "\copyright"'
Установка slony.
На master сервере:
cl09:~$ sudo aptitude install slony1-2-bin
На slave сервере:
cl09:~$ ssh cl10 -t sudo aptitude install postgresql-8.4-slony1-2
Подготовка баз.
Создание первичных ключей.
Одним из требований системы репликаций slony, является наличие первичных ключей в таблицах. Создадим недостающие ключи для наших таблиц. Алгоритм действий следующий: пройтись по списку интересующихся таблиц, проверяя есть ли у текущей первичный ключ, при его отсутствии добавить колонку pkid с типом serial и назначить на нее первичный ключ. Реализация через perl скрипт, текст которого приведен ниже:
#!/usr/bin/perl
# pk.pl
use warnings;
use strict;
use DBI; # подключаем класс работы с базами

# имя базы, имя пользователя базы, пароль 
my ($dbname,$dbuser,$dbpass,$schema) = ('vmail','vmail','secret','public');
# подключение к локальнoй базе
 my $dbh = DBI->connect("dbi:Pg:dbname=$dbname", $dbuser, $dbpass,
                         { RaiseError => 1,  # в случае ошибки на строне базы данных прерывать работу perl
                          AutoCommit => 0 }) # отключение автоматической фиксации изменнений
             or die $DBI::errstr;
# список таблиц для проверки наличия Primary Key
# Получаем список таблиц в выбранной нами схеме
my @tables2rep = $dbh->tables($dbname,$schema);
foreach my $table (@tables2rep){
# выбока проверяющая наличие у таблицы первичного ключа
# поиск идет по таблице индексов
# условия выборки:
#        i.indisprimary -- индекс является первичным ключем
#        u.usename -- принадлежит указаному пользователю
#        n.nspname -- находиться в заданной схеме
#        c2.relname -- относится к проверяемой таблице
    my $sth=$dbh->prepare(" select c2.relname
                            FROM pg_catalog.pg_class c
                                JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
                                JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid
                                LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner
                                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
                            WHERE   i.indisprimary
                                and u.usename = ?  and n.nspname||'.'||c2.relname = ?");
    $sth->execute($dbuser,$table);
# при отсутсвии первичного ключа добавляем колнку и назначаем на нее ключ
    if ($sth->rows < 1){
        my $ddl = "Alter Table $table add pkid serial";
        $dbh->do($ddl) or die $DBI::errstr;
        $ddl = "Alter Table $table ADD Primary Key (pkid)";
        $dbh->do($ddl) or die $DBI::errstr;
        print $ddl ."\n";
    }
    $sth->finish();
}
 $dbh->commit();
 $dbh->disconnect();
Создание пользователя.
Для применения изменений необходим пользователь субд postgres, с под которым будут выполняться операции с данными. Так же выдаем ему права суперпользователя (требования системы slony). На master:
cl09:~$ sudo su - postgres -c "psql <<EOF
Create User slony with password 'slony_pass';
Alter user slony createuser;
EOF
"
На slave
cl09:~$ ssh cl10 -t sudo su - postgres -c "psql <<EOF
Create User slony with password 'slony_pass';
Alter user slony createuser;
EOF
"
Копирование базы.
Перед запуском репликаций необходимо привести базы в идентичное состояние.
Экспорт базы на master сервере:
cl09:~$ pg_dump -c -U vmail vmail > vmail.sql
Перенос на slave:
cl09:~$ psql -U vmail vmail -h 192.168.30.10 < vmail.sql
Включение поддержки pl/pgsql.
На master сервере:
cl09:~$ sudo su - postgres -c 'createlang -d vmail plpgsql'
На slave сервере:
cl09:~$ ssh cl10 -t "sudo su - postgres -c 'createlang -d vmail plpgsql'"
Настройка репликации.
Управление репликациями осуществляеться с помошью консольной утилиты slonik, которая принимает на свой вход команды из stdin или файла. Создадим с помощью perl-скрипта файлы команд и оправим их как параметр для slonik. Также для формирования файла конфигурации демона slony параметры сохраняються в файл 4slon_tools.conf. В данном скрипте создаются правила для репликации всей схемы, если нужен ограниченный список, можно его задать в массиве @tables2rep:
#!/usr/bin/perl
# slonik.pl
use warnings;
use strict;
use DBI; # подключаем класс работы с базами
#######################
# параметры репликации#
#######################
# имя базы, имя пользователя базы, пароль 
my ($dbname,$dbuser,$dbpass,$schema) = ('vmail','vmail','secret','public');
my $clustername = 'cl_dovecot';
my ($masterhost,$slavehost)= ('192.168.30.9','192.168.30.10');
my ($repuser,$reppass) = ('slony','slony_pass');
# файлы параметров для slonik и конфигурационный для демона slon
my ($initfile,$subfile,$slonconf) = ('init.slk','sub.slk','4slon_tools.conf');
# формирование файла конфигурации
open INITFILE,"> $initfile";
print INITFILE "cluster name = $clustername;\n";
# описание подключений к базам
print INITFILE "node 1 admin conninfo = 'dbname=$dbname  host=$masterhost user=$repuser password=$reppass';\n";
print INITFILE "node 2 admin conninfo = 'dbname=$dbname  host=$slavehost user=$repuser password=$reppass';\n\n";
print INITFILE "init cluster ( id=1, comment = 'Master Node');\n\n";
# создание набора в который будут включены табблицы для репликаций
print INITFILE "create set (id=1, origin=1, comment='$dbname replication set');\n";
# подключение к локальнoй базе
 my $dbh = DBI->connect("dbi:Pg:dbname=$dbname", $dbuser, $dbpass,
                         { RaiseError => 1,  # в случае ошибки на строне базы данных прерывать работу perl
                          AutoCommit => 0 }) # отключение автоматической фиксации изменнений
             or die $DBI::errstr;
# Получаем список таблиц в выбранной нами схеме
my @tables2rep = $dbh->tables($dbname,$schema);
# Сохраняем параметры для файла slon_tools.conf
open SLONCONF,"> $slonconf";
print SLONCONF "clustername=$clustername\n";
print SLONCONF "slavehost=$slavehost\n";
print SLONCONF "masterhost=$masterhost\n";
print SLONCONF "dbname=$dbname\n";
print SLONCONF "repuser=$repuser\n";
print SLONCONF "reppass=$reppass\n";
print SLONCONF 'TABLES=\'"',join('","',@tables2rep),"\"\'\n";
close SLONCONF;
$dbh->disconnect();
# добавление таблиц для репликации
my $i = 1;
foreach my $table (@tables2rep){
    print INITFILE "set add table (set id=1, origin=1, id=$i, fully qualified name = '$table');\n";
    $i++;
}
# добавление slave к репликации с уведомлением (event) master`а о новом узле
print INITFILE "\n";
print INITFILE "store node (id=2, comment = 'Slave node', event node=1);\n";
# описание правил подключений узлов между собой
print INITFILE "store path (server=1, client=2, conninfo='dbname=$dbname host=$masterhost user=$repuser password=$reppass');\n";
print INITFILE "store path (server=2, client=1, conninfo='dbname=$dbname host=$slavehost user=$repuser password=$reppass');\n";
print INITFILE "\n";
close INITFILE;
# передаем свойства репликации в систему slony
system('slonik',$initfile);

###############################################
# подписываем slave на прием данных от master #
###############################################
open SUBFILE,"> $subfile";
print SUBFILE "cluster name = $clustername;\n";
# описание подключений к базам
print SUBFILE "node 1 admin conninfo = 'dbname=$dbname  host=$masterhost user=$repuser password=$reppass';\n";
print SUBFILE "node 2 admin conninfo = 'dbname=$dbname  host=$slavehost user=$repuser password=$reppass';\n\n";
print SUBFILE "subscribe set ( id = 1, provider = 1, receiver = 2, forward = no);";
close SUBFILE;

# передаем slonik'y информацию о подписке
system('slonik',$subfile);

# удаляем файлы команд для slonik
system ("rm *.slk");
В директории /usr/share/doc/slony1-2-bin/examples/ расположены примеры скриптов и файлов для работы slony. Подредактируем с помощью bash-скрипта имеющийся там файл slon_tools.conf-sample:
#!/bin/bash
# makeconf.sh
# загружаем значения сформированные perl сриптом
. ./4slon_tools.conf
# распаковываем файл из примеров
gunzip -c /usr/share/doc/slony1-2-bin/examples/slon_tools.conf-sample.gz > slon_tools.conf
# чистим избыточную информацию
 sed -i "/add_node(node     => 3/,/^$/ d" slon_tools.conf
 sed -i "/add_node(node     => 4/,/^$/ d" slon_tools.conf
 sed -i "/set2/,/^$/ d" slon_tools.conf
 sed -i '/keyedtables" => {/,/^$/ d' slon_tools.conf
 sed -i "/sequence_id/,/^$/ d" slon_tools.conf
 sed -i "/serialtables/ d" slon_tools.conf
 sed -i '/sequences" => /,/],/ d' slon_tools.conf
 sed -i '/TABLE1/,/table2/ d' slon_tools.conf

# добавляем свои параметры
 sed -i "s/replication/$clustername/" slon_tools.conf
 sed -i "s/server1/$masterhost/" slon_tools.conf
 sed -i "s/server2/$slavehost/" slon_tools.conf
 sed -i "s/postgres/$repuser/" slon_tools.conf
 sed -i "s/password => ''/password => '$reppass'/" slon_tools.conf
 sed -i "s/database/$dbname/" slon_tools.conf
 sed -i "/pkeyedtables\" =>/ a\ $TABLES" slon_tools.conf

# немного красоты
sed -i '/^$/d' slon_tools.conf
sed -i '/[;|}|{$]/G' slon_tools.conf

# удаляем файл параметров
rm ./4slon_tools.conf

# переносим файл в /etc
sudo mv slon_tools.conf /etc/slony1/
Указываем в файле /etc/default/slony1 узлы, которые должны запускаться:
cl09:~$ sudo sed -i 's/SLON.*/SLON_TOOLS_START_NODES="1 2"/' /etc/default/slony1
Настройка закончена перезапускаем slony1:
cl09:~$ sudo service slony1 restart
Проверка.
Делаем вставку на master сервере:
cl09:~$psql -U vmail vmail -c "insert into hostreject(domain,coment) Values('55.25.30.819','4test')"
Смотрим наличие новой строчки на slave:
cl09:~$ psql -U vmail vmail -h 192.168.30.10 -c "Select * from hostreject"
Что почитать.
PostgreSQL Slony - настройка асинхронной master/slave репликации
Configuration and Action commmands

Комментариев нет: