Страницы

Сохранить статью у себя в соцсети:

вторник, 18 марта 2014 г.

pg_rewind: a quickly recycle a Postgres master into stand-by.

pg_rewind: Превращаем мастера в stand-by без переинициализации.

Всем кому приходилось сталкиваться с процедурой failover при работе с потоковой репликацией в PostgreSQL, наверняка озадачивались вопросом: "А как бы мне ничего заново не копировать, а по-быстрому завести старый мастер в качестве stand-by". Так вот к сожалению, встроенной такой функциональности в PostgreSQL, увы нет. Да, нельзя так просто взять и подключить старый мастер к новому и чтобы все заработало. Для этого нужно повторить процесс настройки потоковой репликации заново, т.е. скопировать весь кластер и запустить postgres в режиме hot-standby.
К счастью работы в этом направлении ведутся, причем результаты довольно не плохие. Называется же проект pg_rewind.
Известные ограничения:
  • На данный момент pg_rewind поддерживает работу только с версиями 9.4 и частично 9.3. Почему частично, потому что кластер должен быть обязательно проинициализирован с поддержкой контрольных сумм (initdb -k). С версией 9.4 попроще, там нужна либо поддержка контрольных сумм, либо наличие параметра wal_log_hints выставленный в on.
  • Еще одно существенное ограничение, мастер должен быть выключен штатно. То есть, если мастер был выключен аварийно, то перемотка не выполнится. Но, разработчики ведут работы в этом направлении.
  • Пока не поддерживаются tablespace'ы и не реализована работа с WAL архивами (недостающие архивы следует скопировать вручную).
Еще немного теории и перейдем к практике... что из себя представляет процесс перемотки:
  • Сканирование каталога старого узла с момента ветвления WAL и запись блоков которые были изменены после ветвления.
  • Копирование изменившихся блоков с нового мастера на старый;
  • Копирование оставшихся файлов (clog, конфигурационные файлы и пр.);
  • Редактирование recovery.conf и запуск старого мастера с новыми настройками;
  • Воспроизведение WAL с момент контрольной точки после failover.
Итак теперь практика, ниже я опишу процесс как выполнить "перемотку" старого мастера и подключение к новому мастеру без полной переинициализации.
План простой:
  • собрать и установить PostgreSQL 9.4 (на данный момент только devel);
  • собрать pg_rewind;
  • настроить потоковую репликацию;
  • выполнить failover;
  • выполнить перемотку старого мастера и подключиться к новому мастеру.
Все операции выполняются в CentOS 6.5. Вообще процесс довольно простой, больше всего сложностей у меня возникло на этапе сборки pg_rewind, поэтому опишу процесс полностью.
Итак, поехали! Для начала нужно установить несколько пакетов которые потребуются в качестве зависимостей при сборке postgresql. После установки клонируем репозитории и выполняем установку PostgreSQL.
# yum install git gcc zlib-devel flex bison readline-devel pam-devel openssl-devel libxslt-devel
# git clone --branch master http://git.postgresql.org/git/postgresql.git
# git clone https://github.com/vmware/pg_rewind
# cd postgresql
# ./configure && make && make install

Тут стоит заметить что по-умолчанию PostgreSQL установился в /usr/local и все утилиты находятся в /usr/local/pgsql/bin, поэтому этот путь нужно добавить в переменную окружения PATH. Сделать это можно разными способами, я поступил следующим, более менее приличным (а может и не очень) для CentOS образом:
# vi /etc/profile.d/pgsql-9.4.sh 
PGSQL94_BINDIR=/usr/local/pgsql/bin
pathmunge $PGSQL94_BINDIR
export PGSQL94_BINDIR
# source /etc/profile

Теперь переходим в каталог с кодом pg_rewind и выполняем сборку утилиты. Полученную утилиту просто копируем к утилитам postgres'a.
# cd ../pg_rewind
# make USE_PGXS=1 top_srcdir=../postgresql/
# cp pg_rewind /usr/local/pgsql/bin/

Теперь настраиваем потоковую репликацию. Как я уже писал вначале, для успешной работы pg_rewind нужно соблюсти одно из двух условий:
1) кластера должны быть проинициализированы с поддержкой контрольных сумм (initdb -k).
или
2) postgres сервисы должны быть запущены с опцией wal_log_hints = on в postgresql.conf
Я выбрал второй вариант.

Процесс настройки уже описан много раз, поэтому останавливаться здесь на этом не буду.
Итак когда репликация настроена и работает, выполняем failover. Эта операция выполняется с помощью создания файла-триггера указанного в recovery.conf в опции trigger_file. После создания файла-триггера, stand-by переключится в режим мастера и начнет жить своей жизнью. Поэтому старый мастер теперь нужно выключить.

И теперь в дело вступает pg_rewind. В качестве параметров выступает каталог где размещен кластер старого мастера (-D) и опции подключения к новому мастер серверу (--source-server). Внимание, операцию нужны выполнять под пользователем которому принадлежит кластер БД (по-умолчанию postgres).
$ pg_rewind -D /var/lib/pgsql/9.4/data/ --source-server="host=192.168.122.12 port=5432 user=postgres"
The servers diverged at WAL position 0/48D9580 on timeline 1.
Rewinding from Last common checkpoint at 0/3000860 on timeline 1
error reading xlog record: record with zero length at 0/48D9620
Done!

Итак перемотка выполнена (не пугайтесь слова error, это штатная проверка). Теперь нужно уделить внимание файлам postrgesql.conf и recovery.done, помните что они скопированы с нового мастера и могут содержать специфичные для сервера настройки (например ip-адреса или номера портов в listen_addresses, port и т.п.) Второй файл, recovery. done следует переименовать в recovery.conf и настроить на подключение к новому мастеру. 
$ mv /var/lib/pgsql/9.4/data/recovery.done /var/lib/pgsql/9.4/data/recovery.conf
$ vi /var/lib/pgsql/9.4/data/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=postgres host=192.168.122.12 port=5432'
trigger_file = '/var/lib/pgsql/9.4/data/failover'

После того как конфигурация исправлена запускаем postgres и смотрим журнал сервера
$ cat /var/lib/pgsql/9.4/data/pg_log/postgresql-Mon.log
LOG:  entering standby mode
LOG:  redo starts at 0/48D95B0
LOG:  record with zero length at 0/61D9EE8
LOG:  consistent recovery state reached at 0/61D9EE8
LOG:  database system is ready to accept read only connections
LOG:  started streaming WAL from primary at 0/6000000 on timeline 2

Красным отмечены важные строки свидетельствующие о том что все прошло гладко и postgres запустился как и положено и готов принимать подключения. Можно проверить потоковую репликацию штатными средствами через pg_stat_replication или создать тестовые таблицы на мастере и проверить их наличие на stand-by.

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

Тем кто не готов проделать это все, есть небольшое видео на 8 минут (экшен по переключению начинается с 4:20).

На главную "Virtualizing Linux".

4 комментария:

  1. А разве timeline switching в 9.3 не решает проблему переключения master в hot standby?

    ОтветитьУдалить
    Ответы
    1. Увы, не всегда и только при соблюдении некоторых условий, например сначала корректно выключаем мастер, потом делаем switch-over... Фактически тепличные условия, в случае же факапа последующая попытка завести старый мастер с latest timeline завершится с "new timeline Y forked off current database system timeline X before current recovery point".

      Хотя я не отрицаю что возможно что-то не так делаю. Если есть идеи поделитесь.

      Удалить
    2. К сожалению, я не достаточно осведомлен в этой теме, поэтому и спросил.

      Удалить
    3. Рад подсказать помочь, но и я тоже уверен многого могу не знать.

      Удалить

Популярные сообщения

Профиль в Google+ Яндекс цитирования Яндекс.Метрика