26 October 2010

Репликация в Postgresql 9.0

PostgreSQLDistributed systems
Доброго времени суток. Учитывая, что с момента релиза PostgreSQL 9 прошло уже некоторое количество времени — я решил пощупать одну из его новых функций — нативную репликацию. Как известно, новый механизм основан на пересылке XLOG`a от мастера к слейву. Одним из жирных плюсов можно назвать нормальную обработку ALTER`ов. Иными словами — администратор 9й версии может обойтись без Slony.

Будем считать, что пакеты у вас уже установлены(а если нет — для Debian/Ubuntu их можно взять здесь), создана база testdb. Я описываю процесс считая, что базы postgres`a у вас лежат в /var/lib/postgresql/9.0/, если это не так — используйте корректный для вас путь.

Итак, поехали:
1. Настраиваем listen && pg_hba.conf
Предположим, что у ip мастера у нас 192.168.0.1, а слейва — 192.168.0.2. Тогда строка listen в postgresql.conf у нас будет выглядеть так:
listen_addresses = '192.168.0.1'

А, в pg_hba.conf на мастере будет такая запись:
host replication postgres 192.168.0.2/32 trust

2. Включаем на мастере всё, что нужно для репликации
#Выставляем ведение журнала таким образом, чтобы слейв мог использоваться для чтения. Можно вместо hot_standby поставить archive и тогда он будет просто хранилищем журанала(нечитаемым).
wal_level = hot_standby

#Максимальное количество слейвов
max_wal_senders = 2

#Сколько кусков лога будем хранить?Если вдруг у вас большая нагрузка на запись в базу - возможно это значение нужно будет увеличить, чтобы всё успевало доезжать до реплики.
wal_keep_segments = 32

#На случай ядерной войны дублируем журнал в отдельное место(лучше чистить по крону эту локацию, удаляя всё, чему больше суток). Хотя, офф. ман говорит, что оно вообще не обязательно.
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/9.0/main/archive/%f'

Теперь мастер нужно перезапустить.

3. Отправляем базу с мастера на слейв.
Нам потребуется что-нибудь, что умеет пересылать данные по сети. Я использовал rsync, хотя, разумеется, можно применять любое другое средство. Тушим на слейве postgresql, после чего на мастере выполняем следующее:
$ psql -c "SELECT pg_start_backup('label', true)"
$ rsync -a /var/lib/postgresql/9.0/main/ slave:/var/lib/postgresql/9.0/main/ --exclude postmaster.pid
$ psql -c "SELECT pg_stop_backup()"


4. Включаем hot_standby на слейве
Добавляем в postgresql.conf:
hot_standby = on

5. Создаем конфиг репликации на слейве.
Для этого в файлике recovery.conf(его нужно создать), лежащем в /var/lib/postgresql/9.0/main пишем следующее:
standby_mode = 'on'
primary_conninfo = 'host=192.168.0.1 port=5432 user=postgres'
trigger_file = '/var/lib/postgresql/9.0/main/trigger'
restore_command = 'cp /var/lib/postgresql/9.0/main/archive/%f "%p"'

Отдельно расскажу про trigger_file. По дефолту его быть не должно. Он нужен для того, чтобы в случае факапа вы могли(создав этот файл) остановить процесс репликации и сделать слейв доступным на запись.

6. Готово!
Запускаем слейв. Если на слейве команда
ps aux | grep receiver
Показывает что-то вида
postgres 1953 0.0 0.0 101980 4156 ? Ss 19:19 0:00 postgres: wal receiver process streaming 2/B40001D0
(читай — есть процесс postgres с описанием wal receiver) — можно считать, что всё работает.

7. Мониторинг
Теперь немного о грустном — в отличие от слонов, нативная репликация не умеет показывать лаг в человеко-читаемом формате.
Один из возможных способов мониторинга репликации — считать разницу в позициях журнала на мастере/слейве:
psql -c "SELECT pg_current_xlog_location()" -h192.168.0.1
--------------------------
0/2000000
(1 row)

psql -c "select pg_last_xlog_replay_location()" -h192.168.0.2
pg_last_xlog_replay_location
------------------------------
0/2000000
(1 row)

От полученных результатов нужно отрезать слэш и то, что до него, далее конвертировать из HEX в нормальное число — результатом будет некое абстрактное значение, критический порог которого будет индивидуален для каждого случая.
Более правильным способом мне видится создание таблички с одним полем типа timestamp, держать там одну единственную запись и раз в n-секунд(например 30) обновлять её значение на текущее время. Тогда, вычитая из записи в мастере, содержимое этой же таблички на слейве, мы получим время отставания.

8. Если случилось ужасное
Как правило, репликация нужна для двух случаев: распределение нагрузки и на случай, если с мастером что-то случится. Так вот, если у вас отказал мастер, то ваши действия будут примерно такими:
а) Создаём на слейве триггер-файл(описано в 5м пункте). Слейв откроется на запись, прекратив репликацию — можно переводить на него клиентов.
б) Далее, когда машина, обслуживающая мастер, вернётся в строй — мы оборачиваем процесс вспять — делаем из изначального мастера реплику — выполняем на мастере 5й пункт. Когда оно восстановится — удаляем на слейве триггер-файл — всё должно вернуться в норму.

P.S. Данный текст является вольным переводом этой вики-страницы.
Tags:postgresql 9.0postgresqlрепликация
Hubs: PostgreSQL Distributed systems
+44
81.2k 181
Comments 42
Popular right now