Предыдущие статьи серии разбирали, что Picodata умеет. Эта — про две стороны эксплуатации, которые удалось проверить на стенде: что кластер сам рассказывает о себе и что происходит, когда его расширяют.
Сразу о границах, чтобы заголовок не обещал лишнего. Полного руководства по эксплуатации здесь нет: резервное копирование и восстановление, обновление кластера между версиями, TLS и готовые правила алертинга стендом не проверялись. О том, что из этого существует и где об этом читать, — в разделе о развёртывании.
Пятая, заключительная статья серии. Всё ниже снято на стенде databases/picodata — кластер из четырёх инстансов, который по ходу дела вырастает до шести.
В статье
- Наблюдаемость из коробки
- Кластерная только часть метрик
- Что мониторить обязательно
- Расширение кластера
- Развёртывание
- Чем платим
- Что дальше
Наблюдаемость из коробки
Один флаг --http-listen поднимает сразу две вещи, и ни для одной не нужны плагины или отдельный экспортёр — проверено на кластере, где установленных плагинов ровно ноль.
Веб-интерфейс отдаётся на корне указанного порта: собственная страница со своими ассетами и конфигурацией. Полезен как быстрый взгляд на кластер, но полноценный мониторинг не заменяет.
Экспорт метрик в формате Prometheus — на /metrics. Сколько там семейств, зависит от того, что уже происходило в кластере: часть появляется только после первого события своего типа. На только что поднятом голом кластере — 140 на узле (на одном из четырёх — 139), после первых SQL-запросов добавляются pico_sql_query_total и pico_sql_query_duration, и выходит 142. Делятся они на три части (снимок одного узла свежего кластера):
pico_*(28 семейств, после первых запросов — 30) — то, что добавила сама Picodata: состояние Raft и инстансов, счётчики PostgreSQL-протокола, длительность и число распределённых запросов, кэш планов на роутере и на хранилищах, RPC-вызовы плагинов;tnt_*(93) — ядро: памятьmemtx, дисковый движок, сеть, процессор;lj_*(19) — сборщик мусора LuaJIT.
Отдельного внимания заслуживают pico_pgproto_* — счётчики соединений, подготовленных выражений и порталов. Раз PostgreSQL-протокол здесь основной канал, наблюдать за ним стоит так же, как за пулом соединений в обычной СУБД.
Кластерная только часть метрик
Здесь легко ошибиться, и я ошибся сам, прежде чем перепроверил.
Часть метрик описывает кластер целиком. pico_instance_state перечисляет все инстансы с их состоянием и тиром, и картина одинакова, с какого узла её ни снимай. Соблазн сделать из этого вывод «достаточно опрашивать любой живой узел» велик — и он неверен.
Раскладка по памяти и движкам, сборщик мусора, роль в Raft и счётчики запросов относятся к тому инстансу, у которого вы забрали метрики. Проверяется это мгновенно — достаточно снять /metrics с разных узлов одного кластера:
:8081 — семейств 154, tnt_* 97, raft: default_1_1 Leader
:8082 — семейств 148, tnt_* 97, raft: default_2_1 Follower
:8083 — семейств 146, tnt_* 97, raft: default_2_2 Follower
:8084 — семейств 145, tnt_* 97, raft: default_1_2 FollowerНаборы различаются и по составу, и по значениям. Это разные измерения, а не разные представления одного. Документация Picodata требует того же — отдельный адрес сбора метрик под каждый инстанс, и пример конфигурации перечисляет все узлы как отдельные цели.
Заодно из этого снимка видно то, чего нет в SQL: роль узла в Raft. pico_raft_state, pico_raft_leader_id и pico_raft_term отдаются штатно, тогда как через SQL состояние лидера не получить. Практический вывод: административная консоль — инструмент разбора инцидента, а не мониторинга.
Что мониторить обязательно
Обычный набор — задержки, ошибки, насыщение — здесь тоже нужен, но есть вещь, специфичная для Picodata, и она важнее остальных.
Доступность репликасетов нужно отслеживать отдельно, и вот почему. Кластер переживает потерю одного узла в репликасете штатно: реплика подхватывает, запросы возвращают полный набор. А при потере обоих узлов репликасета запрос не падает — он возвращает неполный результат, без ошибки и без предупреждения:
count(*) = 133249 ← в кластере 200000Ни исключения, ни признака, что часть данных недоступна. Приложение не включит запасной путь, отчёт построится, решение примется — на неполных данных. Механику подробно разбирает первая статья серии; здесь важно операционное следствие: нельзя выводить здоровье кластера из того, что запросы проходят. Смотреть надо на pico_instance_state — сколько инстансов в состоянии Online и все ли репликасеты имеют живых членов.
Ещё две вещи, которые стоит держать на виду:
- Смена Raft-лидера.
pico_raft_leader_idиpico_raft_term: рост терма без видимой причины — сигнал о нестабильности связности. - Кэш планов.
pico_router_cache_*иpico_storage_cache_*: доля промахов показывает, насколько приложение параметризует запросы. Много промахов — значит планы строятся заново на каждый вызов.
Расширение кластера
Добавление узлов устроено приятно: новые инстансы подключаются к существующему кластеру, сами собираются в репликасет и получают вес — вручную ничего регистрировать не нужно.
default_1_1 | default_1 | ["Online",2]
default_1_2 | default_1 | ["Online",2]
default_2_1 | default_2 | ["Online",1]
default_2_2 | default_2 | ["Online",1]
default_3_1 | default_3 | ["Online",1] ← новые
default_3_2 | default_3 | ["Online",1]
веса репликасетов: default_1 = 1 ready, default_2 = 1 ready, default_3 = 1 readyДобавлять нужно парой — при факторе репликации 2 одиночный инстанс образует неполный репликасет и не получит бакетов вообще, ровно как три инстанса на старте.
Дальше бакеты переезжают на новый репликасет. На корректно инициализированном кластере это происходило сразу: при первой же проверке на новых узлах было по 1000 бакетов, и все три репликасета выровнялись — 3000 бакетов, по 1000 на каждый, данные целы.
Здесь стоит рассказать, чего эта проверка мне стоила, потому что вывод чуть не оказался противоположным. В части прогонов бакеты не двигались минутами, а в журнале стояло The cluster is balanced ok. Schedule next rebalancing after 3600.000000 seconds — и напрашивалось заключение, что расширение кластера операция отложенная. Заключение было бы неверным: те прогоны снимались либо с кластера, не закончившего инициализацию, либо — что обиднее — с прогонов, где новые узлы вообще не поднялись из-за ошибки в самом стенде, а пустой ответ узла я принимал за «ноль бакетов». После того как стенд научился ждать готовности кластера и отличать «узел молчит» от «бакетов ноль», перераспределение начиналось незамедлительно в каждом прогоне.
Практический вывод от этого не меняется, и он важнее конкретного тайминга: готовность нового узла к нагрузке определяется по фактическому числу бакетов на нём, а не по статусу Online и не по выставленному весу. Планируя окно работ, дождитесь, пока бакеты действительно переедут.
Формулировка «cluster is balanced ok» при пустом третьем репликасете здесь второй раз за серию оказывается ненадёжным индикатором: она означает «размещение соответствует текущему плану», а не «мощность используется равномерно».
Развёртывание
Штатных путей два, и оба задокументированы вендором: роли Ansible для установки на машины и оператор Kubernetes для кластерного окружения. На стенде проверялся вариант с контейнерами напрямую, поэтому про Ansible и оператор здесь — со ссылкой на документацию, а не по результатам измерения.
Что точно стоит знать про эксплуатацию до первого развёртывания:
- Резервное копирование средствами PostgreSQL не работает.
pg_dumpпадает на первом же запросе к системным каталогам — подробности в статье про границы совместимости. Механизмы у Picodata свои: SQL-командаBACKUPи отдельная командаpicodata restore --path. Обе присутствуют в 26.1.3, и обе стендом не проверялись — попытка вызватьBACKUPна кластере, поднятом флагами командной строки, отвергается сообщениемNo config found for local backup (it was not found on instance start). Одного флага--backup-dirдля этого недостаточно: резервное копирование настраивается через конфигурационный файл инстанса, а стенд запускает узлы флагами. Планировать восстановление нужно на этих механизмах, но проверять их придётся отдельно — здесь они не измерены. - Плагины версионированы вместе с кластером. Версия библиотеки плагина привязана к версии Picodata, значит обновление кластера означает пересборку плагинов — см. статью про плагины.
- Кластерные лимиты придётся настраивать под нагрузку. Дефолты не рассчитаны на агрегацию по сотням тысяч строк; какие именно параметры и почему — в статье про распределённый SQL.
Чем платим
- Мониторинг обходит все узлы. Один эндпоинт даёт срез кластера, но не заменяет опрос каждого инстанса.
- Здоровье не выводится из успешности запросов. Потеря репликасета не проявляется как ошибка — только как неполный ответ.
- Расширение требует дождаться переезда бакетов. Узлы принимаются в кластер сразу и сразу переходят в Online, но рабочими становятся, когда получат бакеты; проверять нужно именно это, а не статус инстанса.
- Резервное копирование — не через привычный инструментарий PostgreSQL.
- Взамен наблюдаемость действительно встроенная: ни экспортёра, ни агента, ни плагина — один флаг и обычный Prometheus.
Что дальше
На этом серия закончена: 1 — что такое Picodata, 2 — границы совместимости с PostgreSQL, 3 — распределённый SQL, 4 — плагины на Rust, 5 — эта статья.
Рядом стоит держать статью про Tarantool и Picodata — там та же идея вычислений рядом с данными показана в сравнении двух систем, и карту хранилищ, где Picodata стоит среди остальных подходов.
Комментарии