H.2. pg_failover_slots

pg_failover_slots — это расширение Postgres Pro Enterprise, предназначенное для автоматического создания и синхронизации слотов логической репликации на физических репликах.

Поскольку слоты логической репликации доступны только на ведущем узле, до момента создания слота нижестоящие подписчики не получают никаких изменений от узла, недавно ставшего ведущим. Это небезопасно, так как будет утеряна информация о том, получение каких данных подписчик уже подтвердил, а какие данные журнала ещё необходимо сохранить, что приведёт к пробелу в истории изменения данных. Расширение pg_failover_slots позволяет использовать слоты логической репликации при физическом переключении узлов с помощью следующих возможностей:

  • Копирование всех недостающих слотов репликации с ведущего узла на резервный.

  • Удаление с резервного узла всех слотов, которые отсутствуют на ведущем.

  • Периодическая синхронизация позиции слотов на резервном узле с позициями слотов на ведущем узле.

  • Обеспечение получения данных выбранными резервными узлами до того, как процессы-передатчики WAL логических слотов отправят данные потребителям.

H.2.1. Установка и настройка

Расширение pg_failover_slots поставляется вместе с Postgres Pro Enterprise в виде отдельного пакета pg-failover-slots-ent-14 (подробные инструкции по установке приведены в Главе 17).

После установки Postgres Pro Enterprise выполните следующие действия:

  1. Добавьте расширение pg_failover_slots в shared_preload_libraries на ведущем узле и всех резервных узлах, которые используются для обеспечения высокой доступности (ручного или аварийного переключения узлов):

    shared_preload_libraries = 'pg_failover_slots'
  2. Выполните предварительную настройку, как описано в Подразделе H.2.3.

H.2.2. Проверка готовности резервного узла

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

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

Убедиться, что слоты полностью синхронизировались с ведущим узлом, достаточно просто. Слоты должны присутствовать в представлении pg_replication_slots на резервном узле и иметь состояние active со значением false. Если у состояния active установлено значение true, это значит, что слот находится в процессе инициализации.

Для примера рассмотрим следующий сеанс psql:

# SELECT slot_name, active FROM pg_replication_slots WHERE slot_type = 'logical';
slot_name    | active
-----------------+--------
regression_slot1 | f
regression_slot2 | f
regression_slot3 | t

Это означает, что синхронизация слотов regression_slot1 и regression_slot2 между ведущим и резервным узлами завершена, а слот regression_slot3 всё ещё синхронизируется. Если в этот момент произойдёт переключение, слот regression_slot3 будет утерян.

Повторим запрос после небольшого ожидания:

# SELECT slot_name, active FROM pg_replication_slots WHERE slot_type = 'logical';
slot_name    | active
-----------------+--------
regression_slot1 | f
regression_slot2 | f
regression_slot3 | f

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

H.2.3. Предварительная настройка

Необходимо выполнить следующую настройку, чтобы избежать получения серьёзных ошибок от расширения:

Это необходимо для подключения к ведущему узлу, чтобы обеспечить раздельную отправку xmin и catalog_xmin по hot_standby_feedback.

H.2.4. Параметры конфигурации

Необходимо добавить расширение в shared_preload_libraries как на ведущем узле, так и на всех резервных узлах, которые используются для обеспечения высокой доступности (ручного или аварийного переключения).

Настройку pg_failover_slots можно выполнить с помощью следующих параметров конфигурации (устанавливаемых в postgresql.conf).

pg_failover_slots.synchronize_slot_names (text)

Этот параметр резервного узла устанавливает, какой логический слот должен быть синхронизирован на этом физическом резервном узле. Значение передаётся в виде списка фильтров слотов, разделённого запятыми.

Фильтр слотов определяется парой key:value (ключ и значение, разделённые двоеточием), где key может быть представлен одной из нижеприведённых сущностей:

  • name проверяет точное соответствие имени слота

  • name_like проверяет соответствие имени слота SQL-выражению LIKE

  • plugin проверяет соответствие имени плагина слота указанному значению

Ключ key можно не указывать, тогда по умолчанию он будет совпадать с именем name.

Например, 'my_slot_name,plugin:test_decoding' будет синхронизировать слот с именем my_slot_name и любые слоты, которые используют плагин test_decoding.

Если указать пустую строку, никакие слоты на этом физическом резервном узле не будут синхронизированы.

Значение по умолчанию — 'name_like:%', при котором все слоты логической репликации будут синхронизированы.

pg_failover_slots.drop_extra_slots (boolean)

Этот параметр резервного узла определяет, как поступить со слотами резервного узла, которые не были обнаружены на ведущем с помощью фильтра pg_failover_slots.synchronize_slot_names. Если задать значение true (по умолчанию), слоты будут удалены. При значении false слоты будут сохранены.

pg_failover_slots.primary_dsn (string)

Параметр резервного узла, который указывает строку подключения к ведущему узлу для получения информации о слотах.

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

Примечание

Параметр primary_conninfo нельзя использовать, если в строке подключения задано поле passwordPostgres Pro скрывает пароль, делая его невидимым для pg_failover_slots. В этом случае необходимо задать значение параметра pg_failover_slots.primary_dsn.

pg_failover_slots.standby_slot_names (text)

Этот параметр обычно используется в отказоустойчивых конфигурациях для гарантии, что кандидаты на переключение (физические реплики потоковой репликации) получили и записали все изменения до того, как они станут доступны подписчикам. Это гарантирует, что фиксация не исчезнет для потребителя логического слота при переключении на резервный узел.

Слоты репликации, чьи имена перечислены в разделённом запятыми списке pg_failover_slots.standby_slot_names, особым образом обрабатываются процессами-передатчиками WAL на ведущем узле.

Процессы-передатчики WAL, участвующие в логической репликации, обеспечивают отправку и запись всех локальных изменений в слоты репликации, указанные в параметре pg_failover_slots.standby_slot_names, до того, как процессы-передатчики WAL отправят эти изменения в слоты логической репликации. Фактически это создаёт барьер синхронной репликации между упомянутым списком слотов и всеми потребителями логически декодированных потоков от процессов-передатчиков WAL.

Любой слот репликации может быть добавлен в список pg_failover_slots.standby_slot_names; поддерживаются как логические, так и физические слоты, но в основном используются физические.

Без таких мер предосторожности возможна ситуация, при которой подписчик получил фиксацию, но она исчезла на провайдере из-за того, что во время переключения кандидат не получил эту фиксацию. В этом случае могут возникнуть следующие аномалии:

  • При наличии одного и более подписчиков, подписчик может применить изменение, но дальнейшие транзакции, выполненные на новом провайдере, могут конфликтовать с этим изменением, так как с точки зрения провайдера оно никогда не происходило;

и/или

  • При наличии двух и более подписчиков, во время переключения возможна ситуация, когда не все подписчики применили изменение. Подписчики в этом случае находятся в несогласованных и противоречащих друг другу состояниях, потому что у тех подписчиков, которые не получили фиксацию, теперь нет возможности её получить.

Настройка параметра pg_failover_slots.standby_slot_names (как и задумано) приведёт к отставанию подписчиков от провайдера, если реплики-кандидаты на переключение не успевают за ним. Поэтому мониторинг этого процесса крайне важен.

pg_failover_slots.standby_slots_min_confirmed (integer)

Контролирует, как много слотов репликации из списка pg_failover_slots.standby_slot_names должны прислать подтверждение перед отправкой данных по слотам логической репликации. Значение -1 (по умолчанию) означает, что будет ожидаться подтверждение от всех указанных в pg_failover_slots.standby_slot_names слотов.

pg_failover_slots.worker_nap_time (integer)

Время ожидания (в миллисекундах) между двумя попытками синхронизации. Значение по умолчанию — 60s.

pg_failover_slots.maintenance_db (text)

Имя базы данных, которая будет использоваться в primary_conninfo для подключения к ведущему серверу и получения списка слотов репликации. Значение по умолчанию — postgres.