Pull to refresh

Comments 42

>Теперь немного о грустном — в отличие от слонов, нативная репликация не умеет показывать лаг в человеко-читаемом формате.

И вся грусть? Или есть еще что-нибудь?
Пока никаких катаклизмов не обнаружил. Переносил несколько серверов с базами разного размера(от 3 до 250 Гб) — все переехали без проблем, путём простого импорта дампа. Работает ровно.
а двустороннюю репликацию кто-то поднимал?
Т.е. Вы реально считаете, что мастер-мастер не нужен?
'эт Вы просто привыкли без него обходиться. хороший мастер-мастер это огогого как хорошо.
Да, догадываюсь, но где бы его взять в случае с постгресом)
Ни одного из этих не использовал. Как они в работе?
Беглый обзор дал понять что оба они основаны на триггерах, а этого бы не хотелось т.к. по опыту со slony, вызывает дополнительный overhead.
Это 2 отдельных случая:
— мастер-слейв используется для создания бакапа, разгрузки мастера от операций чтения и тем самым повышения скорости работы. И то и другое полезно в веб-проектах. На мастере и слейве данные немного расходятся по времени на так называемый лаг репликации.
— мастер-мастер — «горячий» failover для минимизации простоя и не потери данных при строгой синхронности данных. Такая система работает медленее чем один мастер-сервер, потому что он при каждой транзакции он должен дождаться подтверждения коммита от слейва. Нужна только для работы с критически важными данными — например, в банке, для веб-проекта она скорее вредна.
Тоже присматриваюсь к новой репликации, но хочется обратить внимание на три момента, которые сразу же бросаются в глаза:

1. Можно ли исключить из репликации часть таблиц (или хотя бы ту или иную схему) в той или иной БД? Т.е. — часть таблиц реплицируется, часть — нет.

2. Когда мастер «дохнет», а слейвов — много, очень часто бывает, что одни слейвы успели накатить какие-то изменения, а другие — еще не успели. Соответственно, нельзя просто так назначить произвольный слейв мастером — это все поломает. Слони в этом случае (он называется failover) делает хитро: назначает слейв мастером, затем идет на все остальные слейвы и «добирает» с них то, чего не хватает, потом — рассылает всем изменения, так что в итоге весь кластер оказывается синхронизированным.

3. Похоже, нет инструментария, который позволил бы сделать failover (посмертное переключение) / switchover (прижизненное переключение) мастера одной командой?

Пункт (1) очень нужен для смешанной схемы «репликация+шардинг», когда в БД есть общая часть данных (всякие справочники и т.д. — то, чего мало и что редко меняется) и шарденная (то, чего много и часто меняется), причем из шарденной части есть ссылки по внешним ключам в общую, общая — реплицируется, а шарденная — нет (содержит разные данные на разных машинах). В Слони с этим проблем нет.

Пункт (2) делает крайне опасным использование встроенной репликации для кластеров из 5-6 машин — на моей памяти было 6 или 7 случаев, когда в Slony он очень спасал (не считая учений).
1. Нет. Создается точная копия инстанса PostgreSQL.
2. Слейвы накатывают с WAL логов данные, так что то что успел сбросить мастер перед падением будет на все слейвах (рано или поздно). Так что они всегда при падении мастера синхронны в данных (Не сразу, может зависить от настроек кластера).
3. Одной команды нет, но возможность есть.

репликация+шардинг = кластеризация :)
2. Не соглашусь. Представьте, что мастер умер на долгое время (дни), и за секунду перед его смертью один из слейвов не успел-таки забрать WAL-логи с него (например, сеть лагнула или просто была очень большая нагрузка на слейв в этот момент — не важно).
Что мешает слейву забрать логи после того как сеть не перестала «лагать»?
P.S. WAL логи — это файлы с изменениями в бд сброшеные в отдельную папку (а то вдруг вы про другое думаете)
Мешает то, что машина, с которой он должен забирать логи (т.е. мастер), умерла. Ощущение, что мы о каких-то разных вещах говорим; уточните, пожалуйста, что Вы имеете в виду?

Лаги сети — это только самый очевидный пример, не более того. В нагруженных системах слейвы могут на секунду-две отстать в заборе логов по самым разным причинам.
Если уж мастер умер с концами(сгорел хостинг или посыпался винт), тогда достаточно проверить через на слейвах
select pg_last_xlog_replay_location()
Где наибольшее число — тот ставим мастером. Переносим данные через онлайн бекап на те слейвы, что отличаются (на те, которые успели — не надо) и работаем дальше. При этом мастер во время переноса разницы через онлайн бекап может работать без перегрузок.
mixermsk — поставьте, пожалуйста, в статье комментарии ПЕРЕД директивами, а директивы — разделите пустой строкой, как было в исходной вики-странице.
Используем для масштабирования pl proxy.
данные распределяются по нескольким серверам баз данных равномерно по id пользователя
Но уж больно много телодвижений требует такая схема и с трудом себе представляю момент когда нам потребуется увеличить число баз в 2-3 раза.

Кто какие решения использует для масштабирования postgres?
Londiste + PgPool-II = replication (Londiste) + load balancing (pgpool) + failover (pgpool) + connection pool (pgpool)
В будущем заменим Londiste на стриминг репликацию.
Могли бы и статейку на эту тему написать, а то ищешь ищешь, что нибудь по репликации posgtreSQL, а ничего толкового не написано.
PgPool2 отличная вещь, использую только ее. Единственное что могу сказать про него — нельзя использовать конструкции NOW() и вызывать UPDATE, DELETE, INSERT внутри функций который будут дергаться SELECT, это надо учитывать при разработке, а так вполне отличная штука.

PgPool2 позволяет реализовывать репликации любых видов, как MASTERMASTER, так и MASTERSLAVE и еще несколько модификаций.

Слышал что Postresql пул хотела брать под свое крыло, очень надеюсь что они это сделают.
Вещь то хорошая, но как утилита для репликации её стоить брать в последнюю очередь (при INSERT нужно лочить таблицы, синхронная, при нагрузке упадут все, а не только мастер). Вообще лучше делать так, что бы приложение и не знало есть там кластер или нет, и работало с минимальным изменением кода.
При нагрузках которые связанные с INSERT может и не стоит, однако если соотношение запросов больше в пользу SELECT запросов то очень даже хорошо использовать.

Вообще всегда надо смотреть в первую очередь на задачу и уже потом выбирать подход. Вот pgpool2 я предпочитаю использовать именно на когда есть большое количество INSERT и огромное количество SELECT тогда проблем нет.

Так что все методы хороши, но в первую очередь надо смотреть на задачу которую необходимо реализовать. Любой очень большой проект не может быть нормализированным, он всегда будет использовать не стандартные подходы реализации и поэтому говорить о том что приложение не должно волновать что там стоит кластер или нет, так говорить нельзя. Большая система она должна собираться с учетом всего и каждый элемент должен взаимодействовать с другим и знать о нем все.
Согласен. Многое из сказаного верно, но насчет
>>Большая система она должна собираться с учетом всего и каждый элемент должен взаимодействовать с другим и знать о нем все.
взаимодействовать — да, знать о нем все — нет.
Многие используют репликацию для распределения нагрузки как я вижу.

Но мы уперлись в размер таблицы — при достижении определенного размера (более 20 мл записей)
запросы проходят плохо, даже по основному ключу.
Потому было решено кластеризовать базу в целях уменьшения именно размера таблиц.
И как я понимаю репликация тут не поможет?
Для начала — можно глянуть партрицирование больших таблиц(например, коментарии, логи пользователей). Если же данные все актуально выбираются (например, таблица юзеров) — шардинг.
партиционирование — так правильно. Ошибся при написании.
я правильно понял, что вы предлагаете вместо одной таблицы 'users' сделать 'users_1', 'users_2', ..., 'users_n'?
Вы про партиционирование?

Партиционирование (partitioning) — это разбиение больших таблиц на логические части по выбранным критериям. Звучит сложно, но на практике все просто.

Скорее всего у Вас есть несколько огромных таблиц (обычно всю нагрузку обеспечивают всего несколько таблиц СУБД из всех имеющихся). Причем чтение в большинстве случаев приходится только на самую последнюю их часть (т.е. активно читаются те данные, которые недавно появились). Примером тому может служить блог — на первую страницу (это последние 5…10 постов) приходится 40…50% всей нагрузки, или новостной портал (суть одна и та же), или системы личных сообщений… впрочем понятно. Партиционирование таблицы позволяет базе данных делать интеллектуальную выборку — сначала СУБД уточнит, какой партиции соответствует Ваш запрос (если это реально) и только потом сделает этот запрос, применительно к нужной партиции (или нескольким партициям). Таким образом, в рассмотренном случае, Вы распределите нагрузку на таблицу по ее партициям. Следовательно выборка типа “SELECT * FROM articles ORDER BY id DESC LIMIT 10” будет выполняться только над последней партицией, которая значительно меньше всей таблицы.

Многие СУБД поддерживают партиционирование на том или ином уровне, например:
dev.mysql.com/doc/refman/5.1/en/partitioning.html — Партиционирование в Mysql, отлично реализовано на уровне СУБД (убедитесь, что Ваша версия >= 5.1).
www.postgresql.org/docs/8.1/interactive/ddl-partitioning.html — Партиционирование в Postgres, не так хорошо, но все же возможность есть.
И первый же select count(*) from articles для построения постранички приведет к тому, что БД полезет шуршать по всем партициям, что в случае с постгресом, будет означать N запросов.

Запросы select * from article where id = X будут выполняться так же быстро, как без партиционирования. А в умную БД которая поймет, что при ORDER BY id DESC LIMIT 10 надо смотреть только в последнюю партицию мне не верится.

Я затрудняюсь привести пример, когда партишнинг таблицы в рамках одного сервера приведет к заметному выигрышу в производительности. Обратных примеров видел достаточно.
>>И первый же select count(*) from articles для построения постранички приведет к тому, что БД полезет шуршать по всем партициям, что в случае с постгресом, будет означать N запросов.

Что вам мешает хранить количество в отдельном поле другой таблици и обновлять через тригеры? Тем более партиции могут делится по разным атрибутам.

>>Запросы select * from article where id = X будут выполняться так же быстро, как без партиционирования. А в умную БД которая поймет, что при ORDER BY id DESC LIMIT 10 надо смотреть только в последнюю партицию мне не верится.

Проблемы СУБД в том, что сначала будет делаться выборка по запросу, а потом лимитируется выборка. Если таблица большая — СУБД будет не сладко сделать LIMIT 10.

>>Я затрудняюсь привести пример, когда партишнинг таблицы в рамках одного сервера приведет к заметному выигрышу в производительности. Обратных примеров видел достаточно.

Обратный пример пожалуйста :)
А вы пробовали перестроить индексы? www.postgresql.org/docs/8.3/static/sql-reindex.html

Просто 20млн Primary Key должны влезать в память, и если у вас постгре хоть немного настроен, то проблем с выборкой по индексу быть не должно.

p.s.
У нас 40+ млн записей и индекс по PK занимает 900мег (опять отожрался), и выборка по индексу отрабатывает за 0.060 ms. Правда памяти 16гиг и база должна целиком влезать…
Да, иногда админ это делал насколько помню, но памяти на тот момент было вроде меньше 10г.
возможно сейчас (когда машины посильнее) мы и не заметили бы проблему.
Важное дополнение: репликация возможна только на одинаковых архитектурах — 64bit-64bit или 32bit-32bit.
Спасибо, было интересно почитать.
После почти года использования ничего нового не появилось рассказать?
Странно, что по PostgreSQL так мало статей на хабре. Используется вроде бы широко.
Рад, что оказалось полезно. В принципе — кроме пары костылей — наверно ничего. :)
Есть ли какие-нибудь более вменяемые способы синхронизировать master-slave?
Что-то встроенное, которое будет работать предсказуемо без лишних утилит синхронизация FS? Т.е указал адрес сервера, указал базу и тип (merge, transaction) и нажал кнопку Ok, затем у тебя в интерфейсе появилась строчка с красным/зеленым значком и статусом?
Утрирую конечно, но слышал много хвалебных отзывов, что Postgres имеет репликацию из коробки, в отличие от MSSQL. А на деле вижу какую-то непонятную субстанцию половина которой к Postgres никак не относится.
rsync работает более, чем предсказуемо — проверено годами :)

В 9.1 появилась утилита pg_basebackup, которая делает наливку реплики из мастера одной командой.

В 9.3 или 9.4 (лень смотреть changelog`и) появилась поддержка replication-slot`ов. В частности, мастер не будет удалять бинлог пока все его не скачают. Но у этого есть и очевидные обратные стороны.

Узнать о подключенных репликах можно начиная с 9.0 из таблицы pg_stat_replication

Only those users with full accounts are able to leave comments. Log in, please.