Хабрахабр

Топ ошибок со стороны разработки при работе с PostgreSQL

HighLoad++ существует давно, и про работу с PostgreSQL мы говорим регулярно. Но у разработчиков все равно из месяца в месяц, из года в год возникают одни и те же проблемы. Когда в маленьких компаниях без DBA в штате случаются ошибки в работе с базами данных, в этом нет ничего удивительного. В крупных компаниях тоже нужны БД, и даже при отлаженных процессах все равно случаются ошибки, и базы падают. Неважно, какого размера компания — ошибки все равно бывают, БД периодически обваливаются, рушатся.

Под катом перечислим топ типичных ошибок, которые совершают разработчики при работе с PostgreSQL, разберемся, почему так делать не надо, и выясним, как надо. С вами такого, конечно, никогда не случится, но проверить чек-лист не трудно, а сэкономить будущих нервов он может очень прилично.

О спикере: Алексей Лесовский (lesovsky) начинал системным администратором Linux. От задач виртуализации и систем мониторинга постепенно пришел к PostgreSQL. Сейчас PostgreSQL DBA в Data Egret — консалтинговой компании, которая работает с большим количеством разных проектов и видит много примеров повторяющихся проблем. Это ссылка на презентацию доклада на HighLoad++ 2018.

Откуда берутся проблемы

Для разминки, несколько историй о том, как возникают ошибки.

История 1. Фичи

Одна из проблем — это то, какими фичами пользуется компания при работе с PostgreSQL. Начинается все просто: PostgreSQL, наборы данных, простые запросы с JOIN. Берем данные, делаем SELECT — все просто.

Фич становится больше. Потом начинаем использовать дополнительную функциональность PostgreSQL, добавляем новые функции, расширения. Вокруг появляются разные утилиты и обвесы — pgbouncer, pgpool, patroni. Подключаем потоковую репликацию, шардирование. Примерно так.

Каждое ключевое слово — повод появиться ошибке.

История 2. Хранение данных

То, как мы храним данные, тоже источник ошибок.

Достаточно простых запросов, чтобы получать и записывать данные. Когда проект только появился, в нем довольно мало данных и таблиц. Данные выбираются из разных мест, появляются JOIN. Но потом таблиц становится все больше. Допустить ошибку и написать кривой запрос становится гораздо легче. Запросы усложняются и включают в себя CTE-конструкции, SUBQUERY, IN-списки, LATERAL.

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

История 3. Жизненный цикл

История о том, как продукт сопровождается. Данные всегда нужно где-то хранить, поэтому всегда есть базы данных. Как развивается БД, когда развивается продукт?

Они пишут свои приложения и развивают навыки в области разработки ПО, не обращая внимания на сервисы. С одной стороны, есть разработчики, которые заняты языками программирования. Часто им неинтересно, как работает Kafka или PostgreSQL — они разрабатывают новые фичи в своем приложении, и до остального им дела нет.

Они поднимают новые инстансы в Amazon на Bare-metal и заняты автоматизацией: настраивают деплой, чтобы хорошо работала выкладка, и конфиги, чтобы сервисы хорошо взаимодействовали между собой. С другой стороны — админы.

Базы работают с дефолтными конфигами, а потом про них и вовсе забывают — «работает, не трогай». Складывается ситуация, когда на тонкий тюнинг компонентов, и БД в том числе, не остается времени или желания.

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

Планирование и мониторинг

Сначала представим, что у нас есть новый проект — это всегда активная разработка, проверка гипотез и реализация новых фич. В момент, когда приложение только-только появилось и развивается, у него мало трафика, пользователей и клиентов, и все они генерируют небольшие объемы данных. В БД работают простые запросы, которые быстро отрабатываются. Не нужно тягать большие объемы данных, нет никаких проблем.

Нужно достраивать индексы, переписывать и оптимизировать запросы. Но вот пользователей больше, приходит трафик: появляются новые данные, базы растут и старые запросы перестают работать. Все это приводит к алертам в 4 утра, стрессу для админов и недовольству руководства. Появляются проблемы производительности.

Что не так?

По моему опыту, чаще всего не хватает дисков.

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

Смотрим сколько места и чем съедено — оказывается, есть каталог pg_xlog:

$ du -csh -t 100M /pgdb/9.6/main/*
15G /pgdb/9.6/main/base
58G /pgdb/9.6/main/pg_xlog
72G итого

Админы баз данных обычно знают, что это за каталог, и его не трогают — существует и существует. Но разработчик, особенно если он смотрит на staging, чешет голову и думает:

— Какие-то логи… Давайте удалим pg_xlog!

Тут же приходится гуглить, как поднять базу после того, как удалил журналы транзакций. Удаляет каталог, база перестает работать.

Опять открываем мониторинг и видим, что места не хватает. Второй пример. На сей раз место занято какой-то базой.

$ du -csh -t 100M /pgdb/9.6/main/*
70G /pgdb/9.6/main/base
2G /pgdb/9.6/main/pg_xlog
72G итого

Ищем, какая база занимает больше всего места, какие таблицы и индексы.

Исторические логи нам никогда были не нужны. Выясняется, что это таблица с историческими логами. Они пишутся на всякий случай, и, если бы не проблема с местом, в них бы никто не смотрел до второго пришествия:

— Давайте, зачистим всё, что мм… старше октября!

Составим update-запрос, запустим его, он отработает и удалит часть строк.

=# DELETE FROM history_log
-# WHERE created_at < «2018-10-01»;
DELETE 165517399
Time: 585478.451 ms

Запрос работает 10 минут, но таблица по-прежнему занимает столько же места.

Такое поведение PostgreSQL неизвестно большинству разработчиков и может сильно удивить. PostgreSQL удаляет строки из таблицы — все верно, но он не возвращает место операционной системе.

Например, ОРМ составил интересный запрос. Третий пример. Обычно все винят ОРМ в том, что они составляют «плохие» запросы, которые вычитывают несколько таблиц.

PostgreSQL умеет параллелить операции работы с данными и может читать таблицы в несколько потоков. Допустим, там несколько операций JOIN, которые читают таблицы параллельно в несколько потоков. Получается, что сервер баз данных перегружается, диски не справляются, и все это приводит к ошибке 502 Bad Gateway c бэкенда — база недоступна. Но, учитывая, что у нас несколько серверов приложений, этот запрос вычитывает все таблицы несколько тысяч раз в секунду.

Можно вспомнить про другие особенности PostgerSQL. Но это еще не все.

  • Тормоза фоновых процессов СУБД — в PostgreSQL есть всякие checkpoint’ы, vacuum’ы, репликация.
  • Накладные расходы от виртуализации. Когда база запущена на виртуальной машине, на этой же железке сбоку есть еще виртуальные машины, и они могут конфликтовать за ресурсы.
  • Хранилище от китайского производителя NoName, производительность которого зависит от Луны в Козероге или положения Сатурна, и разобраться, почему оно работает именно так, нет возможности. База страдает.
  • Дефолтные конфигурации. Это моя любимая тема: заказчик говорит, что у него тормозит база — смотришь, а у него дефолтный конфиг. Дело в том, что дефолтный конфиг PostgreSQL предназначен для того, чтобы запускаться на самом слабом чайнике. База запускается, работает, но когда она работает уже на железе среднего уровня, то этого конфига недостаточно, его нужно тюнить.

К счастью, с процессорами, памятью, сетью, как правило, все более-менее в порядке. Чаще всего PostgreSQL не хватает либо дискового пространства, либо дисковой производительности.

Как быть? Нужен мониторинг и планирование! Казалось бы — очевидно, но почему-то в большинстве случаев никто не планирует базу, а мониторинг не покрывает всего того, что нужно отслеживать при эксплуатации PostgreSQL. Есть набор четких правил, при соблюдении которых все будет работать хорошо, а не «на авось».

Планирование

Размещайте базу данных на SSD не раздумывая. SSD давно стали надежными, стабильными и производительными. Энтерпрайзные модели SSD работают годами.

Не пишите в БД то, что вы сомневаетесь, что понадобится — гарантированно не понадобится. Всегда планируйте схему данных. Простой пример — немного измененная таблица одного из наших клиентов.

Условно говоря, в эту колонку можно записать что угодно. Это таблица логов, в которой есть колонка data с типом json. В PostgreSQL нет проблем с хранением записей такой длины. Из последней записи этой таблицы видно, что логи занимают 8 Мб. У PostgreSQL очень хороший storage, который прожёвывает такие записи.

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

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

В рассмотренном пример удаления данных за 10 минут, DELETE можно заменить на DROP TABLE — такая операция в аналогичных обстоятельствах займет всего несколько миллисекунд.

Управлять историческими данными так легче, проще и безопаснее. Когда данные рассортированы по партициям, партиция удаляется буквально за несколько миллисекунд, и место ОС отдается сразу.

Мониторинг

Мониторинг — отдельная большая тема, но с точки зрения БД есть рекомендации, которые можно уместить в один раздел статьи.

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

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

  • Подключенные клиенты. Нужно отслеживать, с какими статусами они работают, быстро находить «вредных» клиентов, которые вредят базе, и отключать их.
  • Ошибки. Нужно мониторить ошибки, чтобы отслеживать, насколько хорошо работает база: нет ошибок — замечательно, появились ошибки — повод заглянуть в логи и начать разбираться, что идет не так.
  • Запросы (statements). Мониторим количественные и качественные характеристики запросов, чтобы примерно оценивать, нет ли у нас медленных, долгих или ресурсоемких запросов.

За более детальной информацией обратитесь к докладу «Основы мониторинга PostgreSQL» с HighLoad++ Siberia и страницу Monitoring в PostgreSQL Wiki.

Когда мы все спланировали и «обмазались» мониторингом, мы все равно можем столкнуться с некоторыми проблемами.

Масштабирование

Обычно разработчик видит БД строчкой в конфиге. Ему не особо интересно, как она устроена внутри — как работает checkpoint, репликация, планировщик. Разработчику и так есть, чем заняться — в todo стоит много интересных вещей, которые ему хочется попробовать.

© Anonymous developer. «Дайте мне адрес базы, дальше я сам».

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

OLTP транзакции — быстрые, короткие, легкие, которые выполняются доли миллисекунд. Есть два типа транзакций. OLAP — аналитические запросы — медленные, долгие, тяжелые, читают большие массивы таблиц и считают статистику. Они отрабатывают очень быстро, и их очень много.

Если вам некогда думать над масштабированием и разнесением OLAP и OLTP запросов, можно говорить: «У нас HTAP!» Но опыт и боль ошибок показывают, что все-таки разные типы запросов должны жить отдельно друг от друга, потому что долгие запросы OLAP блокируют легкие OLTP-запросы. Последние 2-3 года часто звучит аббревиатура HTAP — Hybrid Transaction / Analytical Processing или гибридный транзакционно-аналитический процессинг.

Так мы подходим к вопросу, как масштабировать PostgreSQL так, чтобы разнести нагрузку, и все остались довольны.

Самый простой вариант — потоковая репликация. Streaming replication. Запись по-прежнему идет в мастер-базу, а чтение на реплики. Когда приложение работает с базой, подключаем к этой базе несколько реплик и распределяем нагрузку. Такой способ позволяет масштабироваться очень широко.

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

Эти наборы таблиц можно подключать в соседние базы, они будут видны приложениям, которые смогут ими нормально пользоваться. Logical publications, subscriptions — механизм логических публикаций и подписок предполагает наличие нескольких независимых PostgreSQL-серверов с отдельными базами и наборами таблиц. Прекрасно работает с PostgreSQL 10. То есть все изменения, которые происходят в источнике, реплицируются на базу назначения и там видны.

Можно взять несколько PostgreSQL и создать там несколько наборов таблиц, которые будут хранить нужные диапазоны данных. Foreign tables, Declarative Partitioning — декларативное партиционирование и внешние таблицы. Это могут быть данные за конкретный год или данные, собранные по любому range.

Приложение может работать уже с этой партиционированной таблицей, но на самом деле оно будет читать данные с удаленных партиций. С помощью механизма внешних таблиц можно объединить все эти базы в виде партиционированной таблицы в отдельной PostgreSQL. Когда объемы данных больше возможностей одного сервера, то это шардинг.

Это все можно объединять в развесистые конфигурации, придумывать разные топологии репликации PostgreSQL, но как все это будет работать и как этим управлять — тема отдельного доклада.

С чего начать?

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

У нас по-прежнему остается та самая строчка в конфиге, которой оперирует разработчик. Следующий шаг — балансировка. Здесь есть несколько вариантов. Ему нужно место, куда он будет писать и читать.

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

  • DNS Round Robin, на мой взгляд, не очень удобная реализация, поскольку иногда работает долго и не дает необходимого времени при переключении ролей мастера между серверами в случаях failover.
  • Более интересный вариант — использование Keepalived и HAProxy. Виртуальные адреса для мастера и набора реплик перекидываются между серверами HAProxy, а HAProxy уже осуществляет балансировку трафика.
  • Patroni, DCS в связке с чем-то типа ZooKeeper, etcd, Consul — самый интересный вариант, на мой взгляд. То есть service discovery отвечает за информацию, кто сейчас мастер, а кто реплики. Patroni управляет кластером PostgreSQL’ов, осуществляет переключение — если топология изменилась, эта информация появится в service discovery, и приложения смогут оперативно узнать текущую топологию.

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

Приложения и СУБД-транзакции

В общем случае медленные и ничего не делающие транзакции приводят к:

  • снижению производительности — не к резкому скачкообразному, а плавному;
  • блокировкам и дедлокам, потому что долгие транзакции удерживают блокировки на строки и мешают другим транзакциям работать;
  • ошибкам HTTP 50* на бэкенде, к ошибкам в интерфейсе или где-то еще.

Рассмотрим немного теории о том, как же возникают эти проблемы, и почему механизм долгих и ничего не делающих транзакций (idle transactions) вреден.

Он позволяет клиентам конкурентно работать с данными, не мешая при этом друг другу: читатели не мешают читателям, а писатели не мешают писателям. В PostgreSQL есть MVCC — условно говоря, движок БД. Конечно, есть некоторые исключения, но в данном случае они не важны.

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

Долгие транзакции существуют и мешают auto vacuum вычистить ненужные версии строк. Так возникает необходимость в сборщике мусора — auto vacuum. На то, чтобы хранить этот мусор, тратятся ресурсы CPU и памяти. Эти мусорные данные начинают кочевать из памяти на диск, из диска в память.

Чем дольше транзакции — тем больше мусора и ниже производительность.

С точки зрения «Кто виноват?», в появлении долгих транзакций виновато именно приложение. Если база будет существовать сама по себе, долгие, ничего не делающие транзакции ниоткуда не возьмутся. На практике же есть следующие варианты появления idle транзакций.

Приложение открывает транзакцию, что-то делает в базе, потом решает обратиться к внешнему источнику, например, Memcached или Redis, в надежде, что потом вернется в базу, продолжит работу и закроет транзакцию. «Давайте сходим во внешний источник». Но если во внешнем источнике происходит ошибка, приложение падает, и транзакция остается незакрытой, пока ее кто-нибудь не заметит и не убьет.

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

Например, админ, разработчик, аналитик, работает в каком-нибудь pgAdmin или в DBeaver — открыл транзакцию, что-то в ней делает. Человеческий фактор. Производительность базы страдает. Потом человека отвлекли, он переключился на другую задачу, потом на третью, забыл про транзакцию, ушел на выходные, а транзакция продолжает висеть.

Давайте разберем, что делать в этих случаях.

  • У нас есть мониторинг, соответственно, нужны алерты в мониторинге. Любая транзакция, которая висит больше часа и ничего не делает — повод посмотреть, откуда она взялась, и разбираться, что не так.
  • Следующий шаг — отстрел таких транзакций через задачу в кроне (pg_terminate_backend(pid)) или настройку в конфиге PostgreSQL. Нужны пороговые значения в 10-30 минут, после которых транзакции автоматически завершаются.
  • Рефакторинг приложения. Конечно же, нужно выяснить, откуда берутся idle транзакции, почему они происходят и устранять такие места.

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

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

Велосипедостроение

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

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

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

После этого таблицы, которые работают с очередями, распухают в размерах. Все это работает прекрасно, пока не появляются долгие транзакции. Её нужно регулярно чистить от устаревших версий строк, чтобы не страдала производительность. Новые jobs все время добавляются, старые удаляются, происходят апдейты — получается таблица с интенсивной записью.

Когда таблица увеличивается в размерах, время обработки тоже увеличивается, так как нужно прочитать много страниц с мусором. Растет время обработки — долгая транзакция удерживает блокировку на устаревшие версии строк или мешает vacuum ее почистить. Время увеличивается, и очередь в какой-то момент перестает работать вообще.

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

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

Не изобретайте свой велосипед — возьмите PgQ, один раз настройте и забудьте про очереди. Чтобы решить эти проблемы давно изобретен Skytools PgQ — менеджер очередей для PostgreSQL.

У Skytools PgQ мало документации. Правда, и у него есть особенности. Ощущение растет, когда что-то пробуешь сделать. После чтения официальной страницы, складывается ощущение, что ничего не понял. Какая-то джедайская магия. Все работает, но как работает — не понятно. Это не очень удобный формат, но много интересного находится именно там, и эти листы придется читать. Но многую информацию можно получить в Mailing-lists.

Создается триггерная функция, которая вешается на таблицу, с которой хотим получать изменения, и все работает надежно. Несмотря на минусы, Skytools PgQ работает по принципу «настроил и забыл». Использовать PgQ дешевле, чем поддержка и настройка отдельных брокеров. Практически про PgQ вспоминают, когда нужно добавить еще одну таблицу в очередь.

Это особенно относится к очередям. Если столкнулись с задачей, с которой кто-то уже скорее всего сталкивался — поищите инструменты, которые уже изобретены.

В своей практике мы выпилили очень много самописных очередей и заменили их на PgQ. Конечно, бывают большие инсталляции PostgreSQL, например, в Авито, где возможностей PgQ не хватает. Но это единичные кейсы, которые решаются отдельно.

Автоматизация

Админы хотят от автоматизации получить возможность раскатывать инстансы, чтобы деплой работал без их вмешательства и конфиги раскатывались мгновенно. А разработчики хотят, чтобы деплой работал так, чтобы, как только они закомитили какие-то изменения, они дальше подтянулись, оттестировались, разлились и все бы было хорошо. Конечно, они хотят катить миграции без ручного вмешательства, чтобы не надо было логиниться на сервер, руками выполнять alter.

Но есть несколько очень серьёзных проблем, которые мешают использованию auto-failover. Все вместе они хотят auto-failover — если вдруг во время работы кластера PostgreSQL произойдет какой-нибудь сбой, роль мастера автоматически перекинется на другой сервер, а мы об этом даже ничего не знали.

В нормальном кластере PostgreSQL с мастером и несколькими репликами, запись идет в один сервер, чтение — с реплик. Split-brain. Но в PostgreSQL из коробки нет механизма fencing, и часто даже в Kubernets его приходится настраивать отдельно. Если происходит сбой, то сервер выключается. Возникает ситуация Split-brain. При сбое приложение может по-прежнему писать в старый мастер, а новое переключившееся приложение начинает писать в новый мастер.

Когда GitHub столкнулся со Split-brain, им пришлось восстанавливать свою базу из бэкапа. Попытка восстановить консистентность может быть очень тяжелой и потребует много нервов.

Допустим, есть мастер и несколько реплик. Cascade failover. Мастер падает, и нагрузка переключается на новый мастер и оставшиеся реплики.

На это уходят секунды, и вся нагрузка приходится на единственный сервер. Старый мастер не успел переинициализироваться и стать репликой, а в этот момент падает другой мастер.

Он не справляется с нагрузкой и тоже отказывает — получается каскадный failover.

Если все же браться за auto-failover, то есть следующие пути.

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

Тоже нужно постоянно проверять, что все работает, прогонять на тестовых кластерах. Ansible playbooks — bash-скрипты на стероидах.

Patroni — на мой взгляд, один из лучших продуктов, потому что у него есть auto-failover, мониторинг состояния кластера, плюс функция отдачи топологии кластера в service discovery.

Тоже интересный инструмент для auto-failover в PostgreSQL, но он уже сложнее и требует знания Pacemaker. PAF — основан на Pacemaker.

Для Kubernetes, например. Stolon больше предназначен для облачных задач. Stolon сложнее Patroni, но они взаимозаменяемы и можно выбирать между ними.

Контейнеры и оркестрация

В последние годы Docker и Kubernetes растут. Это динамично развивающиеся технологии, в которых появляется много нового.

С «А что если развернуть базу в Kubernetes...» начинаются разные удивительные истории. В каждой новой версии добавляется много интересной функциональности, правда при этом старая может перестать работать.

Где? База — это всегда stateful, ее нужно где-то хранить. Решения из Open Source: CEPH, GlusterFS, LinStor DRBD. На ум приходит отказоустойчивое сетевое хранилище. Фундаментальная проблема в том, что все это работает очень медленно и, наверное, никогда не станет работать быстро.

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

  • Размер базы небольшой, и не нужно передавать Гб и десятки Гб данных между узлами.
  • Нет требований к производительности и latency. Если latency увеличивается до десятков или даже сотен миллисекунд — это совершенно нерабочее решение.
  • Не страшно потерять данные. Kubernetes развивается, в нем находят какие-то баги. Движки, которые позволяют делать shared storage для Kubernetes, тоже развиваются и там тоже находят баги. В какой-то момент можно просто напороться на баг и все потерять.

Этот подводит нас к тому, что хорошо использовать Kubernetes и Docker для БД на staging или dev-серверах либо на этапе проверки гипотез. Но для высоких нагрузок, на мой взгляд, Kubernetes и шаредные хранилища не очень хороши.

На данный момент есть два таких оператора: Zalando и Crunchy. Но если сильно хочется, то оптимальным вариантом будут local volumes — локальные хранилища без использования шаредных файловых систем, streaming replication — нативная потоковая репликация, через которую идет синхронизация данных и PostgreSQL-операторы, которые предоставляют нам нечто вроде кнопки — нажал, и все заработало.

Посмотрите на количество issues и pull requests. Конечно же стоит помнить, что это все динамично развивается. Появляются новые фичи, в них могут скрываться ошибки, поэтому внедряйте контейнеризацию без фанатизма.

Итоги

Когда вы занимаетесь планированием и мониторингом не экономьте на SSD — они относительно дешевы и оттянут проблемы с производительностью на год, а то и больше.

Практика писать JSON на 8 Мб — это плохо, так делать нельзя. Не пишите в базу все подряд.

Мониторьте PostgreSQL, расширяйте ваш мониторинг. Мониторинг нужен, причем не оставляйте его в дефолтно настроенном состоянии.

Старайтесь не читать и не писать данные из одного места. Разносите нагрузку — Postgres is ready. Для масштабирования нагрузки используйте: streaming replication; publications, subscriptions; foreign Tables; declarative partitioning. PostgreSQL очень хорошо масштабируется, и есть варианты его масштабирования на любой вкус.

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

Это напрямую касается очередей. Если вы делаете что-то, что уже могло понадобиться другим людям, посмотрите вокруг — возможно все уже есть. Не изобретайте самописные очереди, используйте Skytools PgQ!

С этим можно хоть как-то работать, но без фанатизма, потому что все очень быстро меняется. Если очень хочется базу в Kubernetes, используйте local volumes, streaming replication и PostgreSQL операторы.

На этот раз в Новосибирске, где уже 24 и 25 июня на HighLoad++ Siberia коллега Алексея Андрей Сальников расскажет о том, как построить рабочий процесс, когда у тебя несколько сотен баз данных с абсолютно разной нагрузкой. Не пропустите новую возможность обсудить высокие нагрузки и услышать среди прочего об администрировании баз данных. И еще 38 классных докладов в расписании — отличный повод приехать на конференцию!

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть