Pull to refresh
1

Разработчик информационных систем.

3
Subscribers
Send message

Во первых читал, а чтиво там не на пять минут. Во вторых я не спорю и более того соглашусь, что REPLICATION SLOT более производительное решение. Но и более сложное в реализации: помимо отдельной нити нужно ещё решить вопрос с разбором данных. Текущая реализация уже на NOTIFY и она проще в применении.

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

Вопросы по реализации и использованию:

Реализация на примере.

Один из текущий проектов предполагает активное взаимодействие с ИИ. Это не только ChatGPT, много сервисов для работы с изображениями.

Midjourney один из них. Но так как было четкое понимание, что из-за проблем с коммерческой эксплуатацией этот сервис нам не подходит, создали временное решение на node.js, не входящее в основную сборку. На выходе получится микросервис со своим не большим API. Взаимодействие с ним происходило так же как описано в этой статье. Обратная связь через webhook.

Hidden text

Со временем перешли на RunPod, а с него на Replicate.

Я к тому, что ни кто не отменяет микросервисную архитектуру, а наоборот. При этом СУБД как источник данных превращается в центр управления, дережируюя микросервисами.

Благодарю! Не сталкивался, почитаю.

Вызов:

SELECT * FROM pg_logical_slot_get_changes('test_slot_1', NULL, NULL, 'include-xids', '0');

Заблокирует намертво одно из соединений, что уже неприемлемо при асинхронной обработке данных.

Тот механизм который предоставляет библиотека libpq в среде C/C++ выглядит белее привлекательно. Так как работает на уровне кода, а не SQL запросов.

Если Вы хотите продолжить обсуждение то найдите меня в телеграм по тому же нику. Готов показать как это работает в отладчике C++.

после чего

После того так внешний процесс получит извещение :) которое будет обработано на уровне libpq.

Хорошо, как приложение подключенное к СУБД через libpq "просто получит данные из WAL"?

Судя по статье, задача передать асинхронно данные внешнему сервису, а не только управление. 

Задача выполнить HTTP-запрос по данным из http.request. Вместе с NOTIFY передается идентификатор записи в таблице http.request, далее происходит запрос данных по этому идентификатору и выполнение HTTP-запроса с сохранением результата в http.request. Всё.

И как раз благодаря NOTIFY я не атакую запросами БД в ожидании новой записи в http.request. Я просто жду уведомление и по факту его получения выполняю описанное выше.

Достаточно их просто оттуда считать через REPLICATION SLOT.

Зачем таки сложности? Всё, что нужно для выполнения задачи уже в http.request.

- отладка проблемных запросов - как траблушить проблемы?

Через журналы событий. Через внутренние и внешние инструменты анализа производительности PostgeSQL.

- тяжелые запросы, потребляющие проц и память - как будет работать обработчик, когда на сервере тяжелая нагрузка?

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

- балансировка нагрузки - в случае роста нагрузки, как масштабироваться горизонтально, если данные и обработка в одной точке и неделима?

Так у вас же не один процесс запущен и не только он занимается обработкой входящих данных: https://habr.com/ru/articles/767442/#comment_26058162

В настройках Апостол можно указать как количество рабочих процессов (аналогично nginx), так и пул подключений к СУБД. Если железо позволяет можно одновременно держать сотни готовых подключений. Обработка запросов асинхронная через epoll поэтому запас прочности большой, но да, всему есть предел. На самом деле вопрос отрытый :)

Например ETL с подгрузкой и обработкой больших объемов данных.

Если объем данных большой и есть четкое понимание, что пихать это всё в одну ячейку таблицы, с последующей обработкой на PL/pgSQL не самая удачная затея. То на помощь приходит C++. Апостол это не только про PostgreSQL- это фреймворк для разработки серверного программного обеспечения. Можно создать отдельный модуль или процесс который будет заниматься разбором данных.

- командная разработка - как реализовать стандартный для команд SDLC?

Да всё как и у всех. Упоминал об этом тут: https://habr.com/ru/articles/767442/#comment_26059064

- SLA - как гарантировать время ответа, если бешенный запрос может нагрузить сервер по самые тапочки?

Бывает, может "призадуматься" один из процессов, но как я уже упомянул их не мало, да и это уже повод задуматься, что не так.

На синтетических тестах грузили так, что количество запросов превышало в разы количество клиентов (которые вряд ли ринутся все разом в одну секунду) и результат заказчика устроил.

Всё происходит так как описано.

то сам факт записи в таблицу уже является сигналом от одного процесса другому.

Это как? Каким образом внешний процесс будет извещён о том, что в таблицу добавлена запись? Непрерывно сканируя её, закидывая БД ненужными запросами? Кажется мы уже это обсуждали.

Задача передать управление внешнему процессу, для этих целей NOTIFY и создан.

Может так будет понятнее.

В любом случае за комментарий спасибо, почитать про REPLICATION SLOT было полезно :)

Мне не нужно передавать данные, мне нужно передать сигнал от одного процесса другому. Известить Апостол о том, что нужно отправить HTTP-запрос. Сам Апостол подключен к PostgeSQL через libpq.

Приложения, использующие libpq, отправляют серверу команды LISTENUNLISTEN и NOTIFY как обычные SQL-команды. Поступление сообщений от команды NOTIFY можно впоследствии отследить с помощью функции PQnotifies.

Я использую то, что есть в этой библиотеке: https://postgrespro.ru/docs/postgresql/16/libpq-async

// Так, мне неудобно и не нужно...
select * from pg_replication_slots;

И мне не нужна гарантированная доставка, если сигнал не будет доставлен то ни чего страшного не произойдет.

NOTIFY - тоже штатный механизм включенный в библиотеку libpq.

Ещё раз. Асинхронное уведомление, это не про репликацию. Это разные вещи.

https://postgrespro.ru/docs/postgresql/16/sql-notify

Асинхронное уведомление, это не про репликацию. Это разные вещи.

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

Асинхронное уведомление позволяет от этого избавится. Сама СУБД известит ваше приложение о том, что произошли требуемые изменения.

До тех пор, пока мастер справляется. И это очень серьезное ограничение.

:) так в том-то и дело, что можно каждый узел сделать мастером.

Это всё верно, если мы исходим из ситуации когда кэширование становится необходимым. А если в этом нет необходимости, если запросы и так отрабатываются достаточно быстро:

API Log
API Log

В любом случае одно другому не мешает. Можно кэшировать запросы на уровне HTTP-сервера, на этом же уровне можно задействовать и Redis. Правда это уже будет код на C++ :).

Вы по любому нагружаете PostgreSQL запросами из вне, а если бизнес логика тесно связана с этими данными, то отработка кода бизнес логики внутри СУБД будет эффективнее, чем таскать данные по сети между разными процессами и отрабатывать логику за пределами СУБД.

Сделать контейнер на подобии того, что в этой статье задача не сложная. Развернуть несколько таких контейнеров (с одинаковым кодом) тоже не проблема. Проблема обеспечить идентичность данных в разных базах данных. Но в моём случае она решаема.

Хранить код только в БД и вести там разработку - да так делать нельзя! Но мы так и не делаем. Об этом я уже написал тут: https://habr.com/ru/articles/767442/#comment_26058754.

При правильной организации процесса разработки хранимая в БД процедура не является головной болью как и реализуемая ею бизнес логика.

Ответить на Ваши вопросы коротко не получится. Придётся обсудить очень много базовых вещей, объяснить, как это работает на низком уровне.

Я лишь хочу сказать, что если, при разработке информационной системы, использование PostgeSQL неизбежно, то куда эффективнее будет задействовать встроенный в саму СУБД инструмент разработки. Правда придется решить ряд технических вопросов. Обычно эти вопросы закрываются с помощью скриптовых языков программирования. Но меня такое решение не устроило.

Каким бы сложным не было Ваше приложение в его основе лежат базовые вещи - протоколы, технологии, стандарты и чем ближе вы к базовым вещам тем меньше задаетесь вопросом: "Какого черта оно не работает".

Спасибо! Интересное решение, изучу повнимательнее. Я то по привычке изобретаю свои велосипеды.

Не стоит хранить код в БД как единственную копию и вести разработку непосредственно в БД. Тут, да и я скажу, что так делать нельзя.

Сейчас, у нас по крайней мере, процесс разработки на PL/pgSQL особо ни чем не отличается от JavaScript.

Весь код хранится в репозиторий, при фиксации изменений отрабатывают механизмы CI/CD. Отрабатывают скрипты и код обновляется в БД (во всех копиях) с полной заменой всех функций. Да есть особенности в виде написания патчей для удаления старых функций или изменений структур таблиц, но это SQL что поделаешь.

Сам код находится в отдельной от таблиц (данных) схеме и если уж так получилось, что кто-то полез туда руками и код в БД стал не соответствовать тому, что в исходных файлах, то смело можно удалить всю схему в которой хранится только код и перезалить скриптами по новой.

Вопрос же не в можно или нельзя, а в том кому как удобно и кто как знает, умеет, может :)

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

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

По поводу неудобно.

Вы пишите код на Python, код храниться в файле. Далее помещаете файл в контейнер в котором запускается бинарный файл python и выполняет код из файла. При выполнении кода с операционной системой взаимодействует процесс python.

Я пишу код на PL/pgSQL, он храниться в файле, далее скриптами «проливаю» (помещаю) этот код в PostgreSQL т. е. в БД (своего рода контейнер), а БД это что — правильно файл, т. е. код храниться тоже в файле, который выполняется бинарным файлом postgres. При выполнении кода с операционной системой взаимодействует процесс postgres.

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

1

Information

Rating
Does not participate
Location
Москва и Московская обл., Россия
Registered
Activity

Specialization

Бэкенд разработчик, Разработчик баз данных
PostgreSQL
Nginx
Docker
Linux
Git
C++
Разработка программного обеспечения
C
Системное программирование
Проектирование баз данных