Обновить

Комментарии 14

Могу ошибаться, но по-моему есть в Postgresql расширения для работы с очередями. Почему не используете?

Как быть, если компания не OpenAI и бурно растет и нарезать производительные нод проще, чем купить выделенный мощный сервер? И в случае необходимости добавить к ним еще одну или две ноды? А как обеспечить отказоустойчивость с околонулевыми RPO\RTO с одним писателем? А как быть если все-таки уперлись на доступной физике в потолок производительности? Всё по-быстрому переписать с нуля, главное чтобы бизнес не заметил? Парадигма взаимодействия с бд и с p2p или pub\sub системами различна. Возомжно, универсальные комбайны хороши. Вот только бы кто-то обозначил границы их применимости в зависимости от нагрузки и требований по надежности.

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

Вопрос новичка - а какие проблемы его ждут?

С вакуумом как минимум

Я не пробовал делать очереди на базе постгреса, но я с ним немало поработал и заметил следующие недостатки:

  1. Постгрес очень не любит апдейты и удаления. Если ты апдейтишь строку - создается новая строка. Если ты удаляешь строку - она только помечается удаленной. И даже после вакуума (я тут имею в виду не full, потому что в проде его никто не делает из-за блокировок) у тебя объём занимаемого места не сильно уменьшается, потому что если после удаления всех dead tuple в странице осталась хоть одна живая запись - страница продолжает жить и занимать место. Да, есть репак, но это трудоемко

  2. Из первого пункта растет много других проблем, например: если надо хранить короткоживущие данные и потом массово их удалять (например ты сохраняешь айди обработанных сообщений для дедупликации), то тебе надо уметь эти данные эффективно чистить. Автоудаления по таймеру в постгресе нет. Обычно тут применяют партиционирование и дропают данные целыми партициями, но тут возникает куча приколов, например нельзя сделать сквозной синтетический айдишник, ключ партиционирования должен быть частью первичного ключа, индексы, не включающие ключ партиционирования, не работают. А это значит, возвращаясь к примеру с дедупликацией сообщений, ты не можешь сделать индекс по айди сообщения, потому что таблица у тебя, скорее всего, партиционирована по дате сообщения чтобы обеспечить гарантии на временное окно работы дедупликации. Это я еще молчу о том, что партиционирование приходится делать либо как-то вручную, либо кастомными плагинами типа партмана. И не дай бог у тебя что-то пошло не так и ты это не заметил. Если у тебя кончились партиции и данные налились в дефолтную - чинить это будет очень больно, без даунтайма получается далеко не всегда

  3. У постгреса довольно низкий лимит на количество соединений. Если приложению надо тысячи (а это не так много, если у тебя 30 апи хостов, у каждого по 100 потоков для клиентских соединений - то тебе надо 3к соединений с базой), то можно использовать какой-нибудь pg boucer, который будет много клиентских соединений обрабатывать через небольшое количество соединений с базой. Несмотря на то, что этот механизм на удивление хорошо работает, он лишает тебя некоторых возможностей (например сессионные advisory локи). И если ты не внимательно читал документацию, ты узнаешь об этой проблеме максимально жестоким образом

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

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

вот тут есть обсуждение: https://www.morling.dev/blog/you-dont-need-kafka-just-use-postgres-considered-harmful/

ну и вцелом: а зачем? есть готовые решения которые точно будут лучше, есть готовые библиотеки и фреймворки для интеграции с кафкой, чтобы все в клиентском коде сделать красиво, но нет, автор решил воспроизвести руками потому что just use postgresql и ладно бы он получил скорость в 2 раза больше чтобы это было как-то оправданно, но ведь нет. что в сухом остатке остается? ну да, может на 1 сервис меньше поднимать придется, ценой того что он загрузит базу лишней работой за которую все равно заплатит из кармана. есть же еще момент насчет того что "вам не нужна кафка потому что она для highload" - если что-то хорошо справляется с высокими нагрузками, то значит оно будет супер хорошо справляться с низкими потребляя меньше ресурсов чем конкурирующие решения. ну ок, возьмем в расчет что это java и нужно заложить больше памяти, но он все равно оперирует суммой в 1000 уе в месяц а не 5. (хотя вот гуглится native image кафки для тех кто очень хочет сэкономить по памяти и уложиться в “бомж” тариф). + если вы оперируете суммами в районе 5 баксов в месяц и 3мя сообщениями в день то тогда можно рассмотреть sqs и его аналоги.

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

Нормальную очередь делать может и не стоит, но для для кейсов типа worker queue отправки уведомлений оно может быть не сильно страшно, но лучше поговорить с dba и учесть особенности конкретной базы типа поведения при select for update, необходимого режима consistency, видимости записи в разных режимах после этого, какие блокировки будет использоваться, как это будет держать wal и репликацию (для долгоживущих транзакций) и т.п.

Disclaimer: я ни пол раза не специалист по базам, но некоторые грабли видел и слышал. И если нужно сделать на базе рсубд что-то под что эта конкретная база не проектировалась, то полезу читать доки, списки рассылки и дёргать тех кто на нужных граблях уже попрыгал вдоволь.

По мне, это противостояние "велосипеды" vs "типовые решения". И я, на каком-то этапе своей карьеры, пришел к тому, что "велосипед" - это практически всегда зло. Поймите меня правильно, 100% свое кастомное решение может быть быстрее, лучше и дешевле (особенно, в глазах его разработчика). Проблема "велосипедов" зачастую не в показателях. Сложности начинаются когда проект начинает жить, когда это надо передать на поддержку/другой команде и тд. Для Kafka нет проблем подключить какой-то UI для администрирования, хранилище схем, двоичные протоколы, другие системы по готовым коннекторам, да мало ли что еще может потребоваться... А кастомное решение только тянет за собой все больше и больше разработки и это еще в варианте когда кастомный код объективно хорош...

Может быть статья не о том? В петпроектах или пилотных MVP нет смысла в нормальных инструментах, запустили на минималках, поняли тренд, внедрили правильную архитектуру? Я часто сталкиваюсь с тем что сперва долго выстраивается "как надо", а потом или не полетело или не успели за рынком

Кто в здоровом уме будет кафку в пет проекте использовать? Это оверинжиниринг

Так статья же как раз об этом, что не нужно сразу тыкать кафку, сперва MPV га постгресе поюзай.

Я не очень понимаю постановку вопроса. В сфере pub-sub есть достаточно много продуктов на разный вкус и потребности.

Kafka слишком тяжёлый? Есть NATS, который можно встроить в своё приложение на go. Нужна сложная логика маршрутизация? Используй RabbutMQ.

Какие именно существующие проблемы решает данный подход, из числа тех, которых невозможно решить с помощью существующих продуктов?

Иногда и pubsub особо не нужен, хватает и условной очереди на редиске. Она и так скорее всего используется, и легче в неё очередь добавить, чем поддерживать +1 сервис.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации