Страницы

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

четверг, 6 марта 2014 г.

§ PostgreSQL Streaming Replication Setup. Updated.

Настройка потоковой репликации в PostgreSQL.

Как-то я уже писал о настройке потоковой репликации. Пришло время слегка переписать статью, т.к. теперь процесс изменился в лучшую сторону. Настроить потоковую репликацию стало еще проще.
Пара слов, для тех кто сталкивается с этим впервые. Потоковая (Streaming) репликация в PostgreSQL это master-slave репликация при которой подчиненный slave-сервер работает в hot-standby режиме. Hot Standby это режим работы при котором существует возможность подключаться к серверу и выполнять запросы на чтение. Более того в случае аварии на master-сервере, запасной hot-standby сервер может быть оперативно переключен в режим мастера.
streaming replication
Для начала определимся с участниками мероприятия.
master = 172.16.90.51, он же мастер, главный сервер.
slave = 172.16.90.52, он же слэйв, stand-by, подчиненный и т.п.

Перед тем как начать, добавлю что все файлы конфигурации находятся в /var/lib/postgresql/db/. В зависимости от дистрибутива каталог может отличаться.
Итак, поехали. Первое что мы делаем это настраиваем доступы. Редактируем pg_hba.conf на мастере, разрешаем доверенные обращения со слэйва по протоколу репликации. 
master # vi /var/lib/postgresql/db/pg_hba.conf
host    replication     postgres        172.16.90.52/32         trust

Дальше, следует перезапустить мастер с поддержкой репликации. Суть настройки сводится к включению режима hot_standby для WAL (wal_level), определению максимального количества процессов участвующих в пересылке WAL-логов на standby-сервер (max_wal_senders) и количество сегментов WAL-журналов (wal_keep_segments). Настройка wal_keep_segments играет роль в случае когда слэйв потерял связь с мастером. В этом случае мастер начинает копить WAL сегменты, чтобы отдать их слэйву когда восстановится связь. Таким образом чем больше wal_keep_segments, тем больше вероятность того что слейв сможет восстановиться после возобновления связи. Архивирование WAL сегментов можно не настраивать. Опции архивирования, не играют первостепенной роли при потоковой репликации. 
master # vi /var/lib/postgresql/db/postgresql.conf
listen_addresses = '172.16.90.51'
wal_level = hot_standby
max_wal_senders = 3
wal_keep_segments = 64
# hot_standby = on
master # /etc/init.d/postgresql-9.3 restart

Переносим все файлы БД на слэйв. В прошлой статье это делалось с помощью rsync. Теперь будем делать это через pg_basebackup. Этот инструмент предназначен для создания т.н. base бэкапов. При использовании pg_basebackup не нужно запускать функции для перевода БД в режиме бэкапа (pg_start_backup()). Однако в pg_basebackup пока нет возможности ограничивать поток (такая возможность есть у rsync).
Итак переносить будем со слейва. Каталог /var/lib/postgresql/db должен быть пуст, иметь права 700 и принадлежать аккаунту от имени которого будет запущен сервис postrges (как правило это postgres или pgsql).
standby # su - postgres
standby $ mkdir /var/lib/postgresql/db/
standby $ chmod 700 /var/lib/postgresql/db/
standby $ pg_basebackup -P -R -X stream -c fast -h 172.16.90.51 -U postgres -D /var/lib/postgresql/db/

В результате pg_basebackup выполнит два подключения к мастеру по протоколу репликации, одно подключение для переноса данных, второе (-X stream) для переноса WAL журналов. Затем выполнит checkpoint (-c fast) - аналог pg_start_backup, после чего начнет переносить данные в каталог /var/lib/postrgesql/db. По завершению будет создан рабочий прототип recovery.conf (-R) который будет вполне пригоден для использования.
После завершения pg_basebackup редактируем postgresql.conf слэйва. Оставляем там все неизменным за исключением двух опций: включаем режим hot_standby, это позволит выполнять к нему запросы на чтение, и меняем listen_address.
standby # vi /var/lib/postgresql/db/postgresql.conf
listen_addresses = '172.16.90.52'
hot_standby = on

Проверяем конфигурацию репликации в созданном recovery.conf.
По большей части нас должно интересовать значение опции trigger_file (по умолчанию оно не добавляется в recovery.conf) - файл наличие которого будет означать что postgres должен переключиться на работу в режиме мастера.
standby # vi /var/lib/postgresql/db/recovery.conf 
standby_mode = 'on'
primary_conninfo = 'host=172.16.90.51 port=5432 user=postgres'
trigger_file = '/var/lib/postgresql/db/trigger'

Все готово для запуска. Запускаем слэйв и проверяем работоспособность.
standby # /etc/init.d/postgresql-9.3 start
standby # tail -f /var/lib/postgresql/db/postmaster.log 
LOG:  entering standby mode
LOG:  redo starts at 4/8D225FB0
LOG:  consistent recovery state reached at 4/8D2260C0
LOG:  record with zero length at 4/8D2260C0
LOG:  database system is ready to accept read only connections
LOG:  started streaming WAL from primary at 4/8D000000 on timeline 1
standby # ps aux |grep receiver
postgres 13211  0.0  0.1 349052  4088 ?        Ss   17:30   0:00 postgres: wal receiver process

На стороне мастера проверка выполняется с помощью pg_stat_replication:
postgres@master # SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 13212
usesysid         | 10
usename          | postgres
application_name | walreceiver
client_addr      | 172.16.90.52
client_hostname  | 
client_port      | 60897
backend_start    | 2014-03-04 17:30:23.901967+06
state            | streaming
sent_location    | 4/8D2260C0
write_location   | 4/8D2260C0
flush_location   | 4/8D2260C0
replay_location  | 4/8D2260C0
sync_priority    | 0
sync_state       | async

Еще вариант, создать что-либо на стороне мастера и проверить наличие на стороне слэйва. Например можно создать простенькую таблицу:
postgres@master # CREATE TABLE t1 AS SELECT generate_series(1,100);
SELECT 100
postgres@standby # SELECT count(*) from t1;
 count 
-------
   100
(1 row)

Как видим данные реплицируются успешно. 
И напоследок привожу команду которую можно использовать для мониторинга лага репликации. Команду следует выполнить на слэйве (через psql), результатом будет время отставания слэйва от мастера. 
postgres@standby # psql -U postgres -c "select now() - pg_last_xact_replay_timestamp();"
    ?column?    
----------------
 00:00:02.15845
(1 row)

В идеальном лаг должен стремится к нулю  и его увеличение говорит о наличии проблем (нагрузка на сеть или на сервера).

Upd. и небольшое видео как это делается.

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

29 комментариев:

  1. допиленный вариант:
    https://github.com/lesovsky/zabbix-extensions/blob/master/files/postgresql/scripts/pgsql.streaming.lag.sh
    Ошибка 404

    ОтветитьУдалить
  2. bingo)))
    psql -qAtX -h $2 $1 -c "select greatest(extract(epoch from now() - pg_last_xact_replay_timestamp()))"

    ОтветитьУдалить
    Ответы
    1. да, от скриптов то я избавился, а вот ссылки побились. удалил упоминание о скрипте из статьи.

      Удалить
  3. Добрый день, с вами уже много где списывались в различное время. И где то вы мне очень сильно помогли. Подскажите пожалуйста что в этот раз не так. Уже 3 сервера так пробовал сделать. Везде одно и тоже, делал и через старт-стоп бэкап, и то как у вас показано в статье.

    http://joxi.ru/l2ZVMwNhwdzP2J

    вот такие ошибки. В логе все тоже самое.

    2014-11-15 15:44:07 UTC ОТМЕТКА: работа системы БД была прервана; последний момент работы: 2014-11-15 13:22:44 UTC
    2014-11-15 15:44:07 UTC ОТМЕТКА: создаётся отсутствующий каталог WAL "pg_xlog/archive_status"
    2014-11-15 15:44:07 UTC ОТМЕТКА: переход в режим резервного сервера
    2014-11-15 15:44:07 UTC ОТМЕТКА: запись REDO начинается со смещения 137/6B000028
    2014-11-15 15:44:07 UTC ОТМЕТКА: согласованное состояние восстановления достигнуто по смещению 137/6B000EB0
    2014-11-15 15:44:07 UTC ОТМЕТКА: начало передачи журнала с главного сервера, с позиции 137/6C000000 на линии времени 1
    2014-11-15 15:44:07 UTC ОТМЕТКА: неполный стартовый пакет
    2014-11-15 15:44:08 UTC ВАЖНО: система баз данных запускается
    2014-11-15 15:44:08 UTC ВАЖНО: система баз данных запускается
    2014-11-15 15:44:09 UTC ВАЖНО: система баз данных запускается
    2014-11-15 15:44:10 UTC ВАЖНО: система баз данных запускается

    ОтветитьУдалить
    Ответы
    1. Отвечаю на вопрос.
      hot_standby = on - очень плохой параметр, я не хотел что бы с реплики что то читалось и не вставил этот параметр в конфиг слейва. Сервер естественно не запускался. После его добавление все прошло как и должно было

      Удалить
    2. Добрый день. Ну вообще все верно, вас недолжна были пугать такая ситуация. Если вы не хотите чтобы с реплики читали, нужно сделать "hot_standby = off", в этом случае при попытке подключения вы будете всегда получать сообщение "ВАЖНО: система баз данных запускается". Но в тоже время реплика считается вполне работоспособной. Если что-то вдруг случается с мастером, вы останавливаете постгрес на реплике, удаляете recovery.conf, запускаете постгрес - и он стартует в режиме мастера.

      Удалить
  4. а как быть если перед репликацией на базе было расширение PostGIS ?

    ОтветитьУдалить
    Ответы
    1. проверить что на будущей реплике установлена та же версия постгиса

      Удалить
  5. Добрый день,
    а возможно как-нибудь настроить slave таким образом, чтобы он начал принимать запросы чтения, только после того, как он подключится к master в режиме streaming replication?

    ОтветитьУдалить
    Ответы
    1. Насколько я знаю оно так и работает. Пока реплика не подключится к мастеру, все попытки клиентских подключений будут завершаться сообщением "recovery in progress" (как-то так).

      Удалить
  6. Добрый день.
    Подскажите - не могу войти в psql со slave. В терминале:
    psql: ВАЖНО: система баз данных запускается
    В лог периодически валится:
    ВАЖНО: не удалось подключиться к главному серверу: fe_sendauth: no password supplied

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      По первому пункту убедитесь что у вас в recovery.conf прописано "standby_mode = on".
      По второму пункту у вас стендбай не может авторизоваться на мастере, смотрите реквизиты подключения в recovery.conf и правила авторизации pg_hba.conf на мастере.
      p.s. есть видео по настройке репликации http://www.youtube.com/watch?v=z0bhyqyBSUI

      Удалить
  7. Этот комментарий был удален автором.

    ОтветитьУдалить
  8. Алексей, правильно ли я понимаю, что если прописан параметр на slave сервере "trigger_file = '/var/lib/postgresql/db/trigger'" то при наличии данного файла, slave сервер становится master сервером и кнему можно осущетсвлять CRUD функции?!

    ОтветитьУдалить
    Ответы
    1. Да, вы все верно понимаете. Постгрес мониторит наличие этого файла, как только обнаруживает его, то переходит из стендбай режима в нормальный режим, в котором уже доступны CRUD.

      Удалить
  9. Hi Alex,
    First of all thank you for this knowledge sharing. I have couple of questions. It would great if you consider to answer.

    I am novice in PGDB but got a task to create PGDB in streaming replication setup.
    I am now following your repo: https://github.com/lesovsky/ansible-postgresql-sr-on-el6. I am creating this on AWS/RHEL7.2

    1. I am currently trying to create PGDB with 1 master and 2 slaves. Does this mean, if the master is failed, out of two slaves, one of the slaves will become master on it's own? or the application that was connected to master or connected to master via cluster, need to take care?

    2. In this git repo, the versions are not getting validated. It means, - postgresql{{ postgresql_version |replace('.', '') }}-server in install_rhel.yml is not able to install from the repo (/defaults/repo.yml) that I updated with latest value: postgresql_repo_RedHat:
    - { version: "9.5", repo: "https://yum.postgresql.org/9.5/redhat/rhel-{{ ansible_lsb.major_release }}-x86_64/pgdg-redhat95-9.5-3.noarch.rpm" } that actually exists.

    3. Indeed this version is an issue wherever, it appears. For example: /group_vars/os_RedHat.yml, the statement: postgresql_exec_dir: /usr/pgsql-{{ postgresql_version }}/bin is not getting validated.

    If you can throw some light on to these issues, I should be able to proceed and come back to you again, for further issues, if any.

    Thanks for your help in advance.

    PS: I can't write/read anything other than English. That's my limitation. Please oblige.

    Regards,
    Kiran

    ОтветитьУдалить
    Ответы
    1. Hi, Kiran.

      At first setup, I recommend you configure replication manually without any automation tools. It helps you to clearly understand how replication works in details.

      Next, I try to answer on your questions:
      1. When master goes down, DBA must promote available slave to the new master (and reconfigure other slaves). It can be done manually via pg_ctl or creating a trigger file. Also failover can be automated via shell/ansible/etc... Anyway, postgres has no built-in auto-failover features.

      2 (and possibly 3). That role written 2 years ago, and many things may change (because ansible team doesn't care about backward compatibility), so feel free to clone this repo, go through the errors and optimize for you needs.

      Also, I accept pull-requests for this repo, so you can send me your patches.

      Regards, Alexey

      Удалить
  10. Алексей, дайте совет, если я хочу делать запланированные бэкапы со слейва. То мне же нужно каким то образом проверить кто именно слейв (так как мог сработать файловер и тот кто я думала что слейв будет вовсе не слейв). Как рекомендуете поступать?

    ОтветитьУдалить
    Ответы
    1. В постгресе есть функция pg_is_in_recovery(), которая возвращает true если постгрес является репликой и false если мастер. Перед бэкапом дергайте эту функцию, анализируйте ответ, принимайте решение запускать бэкап или нет.

      А вообще мне любопытно, то есть ваш уровень инфраструктуры на такком уровне что знание о том кто мастер не имеет важности?

      Удалить
    2. не совсем. Я только изучаю всю эту кухню, Пробую в тестовом режиме связку: репликацию средствами postgres + pgpool2 (в нем балансировка нагрузки + файловер). Вроде все настроила, возник только вопрос с автоматическим бэкапом. Очень много вопросов было, когда только начала изучать, сейчас уже чуть меньше)). Спасибо что ответили. Просто нигде не нашла информации как делают бэкапы со слейва. Пока есть только мысль оформить это в отдельный скрипт. больше ж никак?

      Удалить
    3. Бэкапы с реплики можно деласть с помощью pg_basebackup. Вобще обратите внимание на pgbarman - это на мой взгляд лучшее решение для бэкапов на данный момент.
      И пара слов про pgpool - вобще не самое лучшее решение для балансировки, на мучаетесь с ним. Опыт показывает что балансировку следует програмировать либо на уровне приложения (приложению лучше знать когда читать с мастера, а когда с реплики), либо на уровне драйвера к бд.

      Удалить
    4. Спасибо за советы)) буду пробывать. Мне сейчас просто интересно на себе испытать эту схему. Про балансировку pgpool не знаете, как pgpool разруливает ситуации когда например пользователь записал данные в таблицу, и потом из нее их читает, может запрос на чтение быть послан на слейв (при том что то что он записал еще не успело залиться на реплику)? или это отслеживается? или как раз с этим и могут быть проблемы?

      Удалить
    5. никак не разруливает, и именно на этом и следует сделать акцент, если между мастером и слейвом есть лаг и данные с мастера еще не приехали на реплику то пгпул просто не увидит свежие данные. Именно поэтому например, баланс денег в личном кабинете всегда читается с мастера (или синхронной реплики). Балансировка в пгпуле неинтелектуальная, видит селект и отправляет его на реплику.

      Удалить
    6. ОГО, я надеялась что это не правда, и он умеет думать хоть чуть-чуть, т.к по личным наблюдениям он по какому то алгоритму select распределяет, не всегда на реплику. В официальной документации не нашла ни опровержения ни доказательств, к сожалению. Доверюсь вашему опыту.

      Удалить
    7. вобще ответ кроется в исходниках)) но так или иначе мы в лице компании где я работаю, никому не рекомендуем его использовать и основные аргументы: 1) тупая балансировка в лоб; 2) просад производительности при выполнении запросов от 10 до 30%; 3) по какому-то своему хотению выкидывает ноды из пула и в итоге все запросы отправляет просто на мастер.

      Удалить
    8. Алексей, продолжаю интересоваться и изучать pgpool. Может подскажите один момент. Использование pgpool предполагает обслуживание только одного кластера? Как поступать если будет нужно что бы он управлял несколькими кластерами? (не встречала что бы так делали, но все таки интересен такой момент). И к слову о кластерах, обращаюсь к вам как к специалисту postgres, скажите если я создаю несколько кластеров: например стандартный main и свой mycluster. Как можно делать start/restart/stop.. служб postgresql? если писать service postgresql start [версия] то действие происходит на оба кластера (даже если имя так же указать рядом с версией) Буду благодарна, если разъясните)

      Удалить
    9. Добрый день,
      1. да, pgpool может быть настроен только на работу с одним кластером.
      2. если вы работаете с ubuntu/debian то там есть утилита pg_ctlcluster, всё можно сделать через нее. В случае с centos/rhel можно через встроенный pg_ctl это делать.

      Удалить
    10. т.е один сервер - один pgpool? или в таком случае как то можно поставить второй? Работаю с debian

      Удалить
  11. За 2 наводку большое спасибо. Все получилось!)

    ОтветитьУдалить

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

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