Согласованность синхронной репликации PostgreSQL

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

PostgreSQL в своей потоковой репликации имеет возможность сделать все свои реплики синхронными с помощью synchronous_standby_names, а также имеет возможность точной настройки с помощью параметра synchronous_commit, где для него можно установить значение remote_apply, поэтому лидер ждет, пока транзакция не будет воспроизведена на резервный (что делает его видимым для запросов). В документации, в абзаце, где говорится что касается параметра remote_apply, в нем говорится, что он позволяет балансировать нагрузку в простых случаях с причинно-следственной согласованностью.

Несколько страниц назад там написано это:

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

Поэтому я изо всех сил пытаюсь понять, что можно гарантировать и какие аномалии могут произойти, если мы балансируем запросы на чтение к репликам чтения. Могут ли еще быть устаревшие чтения? Может ли это произойти, когда я запрашиваю разные реплики, чтобы получить разные результаты, даже если запись не происходит после того, как на лидере? Мое впечатление - да, но я не совсем уверен. Если нет, то как PostgreSQL предотвращает устаревшие чтения? Я не нашел ничего с более подробной информацией о том, как это работает в полной мере под капотом. Использует ли он двухфазную фиксацию или какую-то его модификацию, или использует какой-то другой алгоритм для предотвращения устаревших операций чтения?

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

Меня действительно сбивает с толку, чтобы действительно понять, могут ли быть аномалии в полностью синхронной репликации в PostgreSQL.

Я понимаю, что у такой установки есть проблемы с доступностью, но сейчас это не проблема.


person Стефан Цолић    schedule 02.09.2020    source источник


Ответы (1)


Если вы используете синхронную репликацию с synchronous_commit = remote_apply, вы можете быть уверены, что увидите измененные данные в резервной копии, как только модифицирующая транзакция будет зафиксирована.

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

  • Наблюдатель увидит измененные данные на первичном сервере до того, как COMMIT вернется, и до того, как данные будут переданы на резервный сервер.

  • Наблюдатель увидит измененные данные на резервном сервере до того, как COMMIT вернется на основной.

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

    В конце концов, однако, модификация данных всегда попадет в резерв.

person Laurenz Albe    schedule 02.09.2020
comment
Нетрудно рассуждать об этом, когда вы получаете ответ, каждый последующий запрос должен видеть данные. Я попытался смоделировать некоторую задержку в сети, используя инструмент tc в кластере, который использует pg_pool впереди, и я заметил, что данные могут быть запрошены на реплике, даже если мастер не вернулся. Насколько я понимаю, если репликация использует 2pc, фиксации на репликах выполняются в разное время, поэтому за небольшой интервал балансировка нагрузки может привести к обновленному чтению, а затем к устаревшему чтению. Я прав? - person Стефан Цолић; 03.09.2020
comment
Я добавил некоторые детали к своему слишком короткому ответу. - person Laurenz Albe; 03.09.2020