PostgreSQL misusage

Эпиграф

I didn't want to add complexity with Kafka, so we've also misused PostgreSQL as a message queue a bit.
написал один парень в твиттере

Внимание, длиннопост, вот тут TLDR

Сказка

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

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

Ну голь на выдумки хитра и мало ль мы чтоли всяких кандибоберов видели? Сам понимаю, иногда хочеться поиграться и похакать всякую фигню в своё удовольствие да изворотиться поизвилистей что б других программистов удивить и белый свет повеселить. Дело житейское, бывает.

Гордость и программирование

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

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

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

А если мы сервера с очередью поднимать не будем, то получится уже не шесть серверов, а всего три. И проблем в два раза меньше. Вот она, математика, алгебра, наука — не зря ж ВУЗы заканчивали, пригодились алгоритмы всё-таки. Упростили инфраструктуру и всех обхитрили. Программистам учить ничего не надо и серверов в два раза меньше. Экономия в чистом виде.

Dev vs Ops

В реальной жизни можно делать что-угодно. И пока удача на твоей стороне, то ошибки будут незаметны. Так можно и бекапы не делать — тоже серверов меньше и места дискового не занимает, а сэкономленные деньги можно пустить на развитие бизнеса: плестейшен в офис купить, например. И если ты достаточно удачлив, то бекапы тебе и не пригодятся никогда.

Но так считают только программисты. Потому что с рождения они отвечали не за стабильность, а за фичи. Вот и думают что всё по волшебству работает. С другой стороны мы — бывшие и современные опсы, сисадмины, поддержка. Грёбанная пехтура. Наша работа — стратегическое планирование в расставлении горшочков под программистские жепки, что б какашечки куда надо падали и ничего не ломали. И вроде была революция что б программисты сами под себя горшочки ставили, да вот не везде она прошла. Кто-то научился, а кто-то всем просто рассказал что научился. Особенно галерные разработчики себе в linkedin опыт devops написали, не проверит же никто. А у нас в итоге смотришь на человека-опса и судишь о его опыте не по искре в глазах, не по молодецкому задору, а по тому сколько он говна поел из-за ошибки чужой аль своей.

Как же смотрим на инфраструктуру мы? И почему мне покоя не давало высказывание об хитром упрощении инфраструктуры?

Что ж не так-то?

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

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

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

Ведь чем выше нагрузка, тем сильнее разные компоненты влияют друг на друга. И искать что на что влияет всегда весело и задорно. Надо смотреть логи, анализировать чужие коммиты, выяснять отношения — не жизнь, а сплошная романтика. А если ещё вспомнить что нагрузка обычно растёт не пропорционально, то вообще сказка. Была нагрузка на CPU 40%, обновил сервис который увеличивает нагрузку на 2% и всё упало - ух, вот это жизнь... И главное на графики только CPU load да RAM usage вывести. Больше ж ничего и не выведешь толкового.

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

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

Использовать самые свежие фичи...

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

К тому же в нашем случае программист очереди в глаза не видел и все его познания о очередях заключаются в знании как пишутся слова Сavka и RabitMKU. И скорее всего он предполагает что они все одинаковые и работают одинаково и именно так как этот программист ожидает. А другой ожидает по другому, третьий по третьему. И в случае юзания постгри в качестве очереди это ещё значит что и документации по багам (которые фичи) тоже нет. И опыта ни у кого тоже нет и взять его неоткуда.

А написанных очередей много: kafka, nats, redis, rabbitmq, activemq, zeromq, beanstalk, kestrel, celery, huey (с нами, но это имя проекта), ironmq, nsq, zaqar, тысячи их и все они друг от друга отличаются не только названиями, но и тем зачем они написанные, какие проблемы люди решали, какие баги-фичи напилили. Есть очереди с гарантированной и негарантированной доставкой, много к одному, один к многим, at least one delivery и наоборот, с записью на диск и без записи или вообще с хитрой записью на диск. Да перечислять долго можно. И это я ещё не начинал перечислять платные и облачные.

Любое легаси это система которую хотели сразу написать хорошо

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

Да и если со стороны человек прийдёт, то можно будет его приятно удивить архитектурой, когда монолит идёт в БД, берет оттуда строчку и в ту же БД кладёт, а потом за ней же в эту же БД идёт и читает. Ведь зачем позволять разработчикам нарабатывать универсальный опыт повсеместно используемых паттернов. И даже когда появится команда опытных разработчиков знакомых с очередями и умеющих их поддерживать, всё равно заставим их наше поделие юзать, потому что мы за универсальность и не зря же писали. Вот у гугла всё своё, всех разработчиков учат внутренним тулам и процессам, а наша конторка на 10 девелоперов не хуже гугла ведь, правда?

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

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

TLDR, пожалей нас, пожалуйста

Если вы используете одну и ту же БД на одних и тех же серверах под очередь и БД, то это уменьшает количество серверов и уменьшает количество новых слов которые надо выучить, но:

  1. Нагрузка на БД влияет на очередь и наоборот
  2. Ломается сразу всё и скопом
  3. Мониторинг становится намного сложнее
  4. И поиск того что всё поломало становится намного сложнее, длительнее и веселее
  5. Даже на инфраструктурной диаграмме всё начинает выглядеть сложнее (впрочем, слов становится меньше, но запутанных стрелочек — больше)
  6. Каждого нового человека надо своему костылю учить, а их опыт заиспользовать нельзя
  7. Атомарность обновлений становится недостижимой, увеличивается time-to-market
  8. И опять, всё влияет на всё без возможности этот клубок распутать
  9. Есть вероятность что это вырастет во внутренний сервис и библиотеки которые надо будет поддерживать, обновлять и тестировать. А также писать документацию на уровне уже написанной. Что тоже увеличивает time-to-market

Впрочем, мне обычно достаточно первого пункта чтобы крепко задуматься.

Так можно ли юзать PosgreSQL в качестве очереди

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

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

Ну или прокачивайте удачу.

P.S. спасибо большое ревьюверам, вы мне очень помогли :)