Комментарии 28
RPO в худшем случае: 160 Мб.
Можно подробнее, в каких ситуациях могут быть потеряны данные в такой архитектуре?
В статье это опущено, но есть параметр synchronous_commit
. У нас он выставлен в off
. Плюс используется асинхронная потоковая репликация, поэтому некоторые данные до реплик могут не доехать, особенно если лидер будет перегружен.
Поясните, пожалуйста, каким образом настройка maximum_lag_on_failover оный RPO гарантирует? Я даже не о плюс-минуc loop_wait/2 seconds из документации, а как вообще оно механически работает?
Когда лидер стал недоступен, у нас есть LSN-ы реплик, есть последний зафиксированный LSN лидера в DCS (в Consul, например). Под капотом в PostgreSQL LSN - смещение в журнале транзакций в байтах.
Получается, разница LSN мастера и LSN реплики покажет отставание в байтах. Если реплика отстала на 160 мегабайт, то она просто не участвует в выборах нового лидера.
А вот если у нас все реплики отстанут более чем на 160 мегабайт, то это уже совсем другая история :)
Понятно, спасибо. Если можно, приведите примеры, для каких операций в avito используется описанный "асинхронный подход", а для каких этого недостаточно и приходится "синхронизировать".
RTO и RPO обычно определяются как золотая середина между стоимостью потери данных или простоя и доступности сервиса. Чем меньшее время простоя сервиса обеспечивает защита, тем дороже она стоит.
В local-first архитектурах потери данных в принципе не происходит и это ничего не стоит. На вашей картинке это будет в центре координат:
![](https://habrastorage.org/getpro/habr/upload_files/94f/19c/c74/94f19cc748a05a6f72762fe7424f14f4.png)
:
А где предполагается хранить local-first базы для случая avito?
Там же, где и remote-first.
В облаке, что ли? Можете схемку набросать, допустим, тут https://mermaid.live?
Тут есть куча схемок например: https://page.hyoo.ru/#!=aqsy4f_sh755c
Интересно, я один не понимаю смысла писать 100500ю статью на тему "Мы используем Patroni, он классный"?
А как вы решаете проблему, когда нужно записать в базу и сразу сделать чтение данных с учетом записанных? Если писать только в мастер, а читать из слейвов, то есть риск не получить данные. Если и писать и читать из мастера - то не получится подразмазать нагрузку. Как вы решаете такие проблемы, особенно с учетом синхрониус коммит офф? Буду благодарен за инфу :)
Никак не решают, читания-писания уровнем выше скорее всего реализованы.
Все верно, при таком подходе на репликах не всегда возможны актуальные данные.
В команде мы придерживаемся того, что реплики используются только для обеспечения отказоустойчивости. Проблемы масштабирования чтения решаются иначе, не за счет реплики: кэширование (Redis, программный кэш на стороне сервиса), шардирование PostgreSQL, шина данных.
С другой стороны, нам рано или поздно предстоит позаботиться о проблеме "локальности чтения" (чтобы сервис читал данные с БД на том же ДЦ), поэтому не исключено, что будут пересмотрены гарантии и механизмы предоставления гарантий.
Это active - active cluster?
Да. В статье это опущено, но у нас есть самописный механизм для балансировки - db_discovery. Этот механизм, в рамках PostgreSQL, предоставляет DSN до текущего лидера. Когда лидер сменяется, DSN меняется до нового лидера с минимальной задержкой.
а CockroachDB или yougadb не рассматривали? тот же PostgreSQL только нормально масштабируется
Сейчас мы занимаемся активным внедрением CRDB на платформу Avito, плюс есть положительный опыт у сервиса, который сам поддерживает и администрирует CRDB.
Изучали YDB (Open-Source который) в прошлом году, но он не смог прижиться у нас.
Понятно. А можете сказать почему YDB не прижился?
В 2022, когда исследовали, столкнулись со следующим:
Не прижился к текущей топологии K8s (невозможно работать вне k8s, например пользователям подключаться);
Проблемы документации: либо что-то не соответствовало действительности, не описаны некоторые подводные камни (например, перед созданием БД требовалось инициализировать хранилище (storage));
Невозможно создавать и администрировать ролевую модель в YDB.
Возможно, это уже давно все поправили, но мы сейчас все силы бросили на внедрение CRDB.
используете ли pg_rewind и если происходит переключение, то занимаетесь ли восстановлением данных, если на момент переключения был replication lag?
Да, пока у нас используется pg_rewind
, но подумываем от него отказаться.
В общем случае, если был replication lag более 160 Мб и у нас имеются бэкапы WAL-ов (лидер успел передать WAL-ы перед своим отказом), то реплики будут восстанавливаться (используя restore_command
) до тех пор, пока replication lag станет менее 160 Мб.
Если бэкапов WAL-ов нет и реплики не могут догнать экс-лидера, то предстоит действовать по ситуации.
спасибо за ответ, я немного про другое имел ввиду) pg_rewind
затирает данные и были ли ситуации когда такое происходило, насколько я понимаю, там восстановление только руками можно выполнить. То есть произошел failover и произошло переключение, отработал pg_rewind
и затёр разницу в wal
чтобы работала синхронизация с новым мастером
а ещё мы используем RAID
Интересно было бы узнать поподробнее, какая реализация используется? Программный/аппаратный, какая конфигурация себя зарекомендовала?
Организуем High Availability PostgreSQL