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

Как же расшифровывается DOLBIT?
DO - database-oriented (ориентированный на БД)
L - liable (ответственный)
B - business (бизнесовый)
I - infrastruture (инфраструктруный)
T - template (шаблон)
Возможно, вам понравится более короткое название SCUF:
S - sanity
(and)
C - consciousness
U - under
F - fire
Что переводится как "адекватность и сознание под угрозой". В это заложен смысл, что разработчики на проекте, построенном по этому подходу, сохраняют адекватность и сознание даже в экстремальных условиях.
По "database-oriented" вы могли понять, что основой стека является база данных. Это хорошо само по себе, особенно, когда в аббревиатуре DOLBIT есть слово "business", потому что данные - это самое ценное, что есть у бизнеса.
DOLBIT существует, чтобы эффективно решать следующий набор проблем, который мы обычно решаем кучей технологий и/или микросервисов:
бизнес-логика
schemaless-данные
key-value данные
кэш
геоданные
полнотекстовый поиск
очереди сообщений
отложенные задания
хранение файлов
Для примера реализации стека я выберу PostgreSQL, но думаю, что собрать свой DOLBIT вы можете на любой другой СУБД, поэтому он и "template". Делитесь своими вариантами DOLBIT в комментариях!
Итак, начнём же.
Бизнес-логика
CREATE [ OR REPLACE ] PROCEDURE name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] ) { LANGUAGE lang_name | TRANSFORM { FOR TYPE type_name } [, ... ] | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | SET configuration_parameter { TO value | = value | FROM CURRENT } | AS 'definition' | AS 'obj_file', 'link_symbol' | sql_body } ...
Зумеры не знали, а бумеры забыли ту мощь, волю, ярость, которую нам дают хранимые процедуры, триггеры и кастомные функции. Хранение кода рядом с данными, которые он обрабатывает, даёт меньшее latency запроса, чем в случае перекладывания JSON-ов через 100500 CRUD-ов.
Это основа, без осваивания или вспоминания которой, у вас не получится успешно реализовать DOLBIT.
Так как это теория, я не буду углубляться в детали: начните с официальной документации.
Schemaless-данные
ALTER TABLE mytable ADD COLUMN myjsonb JSONB;
Далеко не все данные укладываются в нормальные формы. Поэтому появилась MongoDB, но у неё более 9000 минусов, например, отсутствие join-ов и ACID-транзакций, высокое потребление диска и оперативной памяти. Поэтому, когда в Postgres появился тип jsonb, MongoDB стала не нужна, ведь теперь schemaless-данные живут в полноценной реляционной СУБД.
Key-value данные
CREATE TABLE mytable (h hstore);
INSERT INTO mytable VALUES ('a=>b, c=>d');
SELECT h['a'] FROM mytable;
Помимо schemaless данных, иногда требуются и key-value данные. Для Postgres может предложить hstore. Теперь вам не устроить спор о том, какой из форков и аналогов Redis лучше.
Кэш
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSION compression_method ] [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option ... ] } [, ... ]
] )
Но Redis часто используется не просто как key-value хранилище, а как хранилище кэша. Вместо Redis для этого можно использовать unlogged таблицы.
Геоданные
ALTER TABLE mytable ADD COLUMN geom geometry(LINESTRING,3005)
Теперь на очереди ещё один тип данных - геоданные. Можно использовать ElasticSearch или что-то ещё более специализированное, но у нас здесь так не принято но зачем, когда существует PostGIS.
Полнотекстовый поиск
ALTER TABLE mytable ADD COLUMN myvector tsvector;
Ранее упомянутый ElasticSearch в первую очередь известен как БД с фичами полнотекстового поиска. Но и здесь он Postges есть что предложить, причём из коробки - tsvector и gin-индексы. Так же, как и с Redis, теперь не нужно задумываться о форках и аналогах ElasticSearch - просто возьми то, что есть в стандартной поставке Postgres.
Очереди сообщений
pgq.create_queue(i_queue_name text) returns integer
Асинхронной взаимодействие - это необходимость создавать outbox-таблицы, воркеры для них, не упустить в коде, что бизнес-данные и события должны сохраняться в одной транзакции. Технологии, которые используются для брокеров, также сложны - например, Kafka. Попробуйте разобраться в обеспечении порядка сообщений, менеджменте zookeeper, масштабировании, Schema Registry - настоящий замок, который заставит усомниться в себе самом. В реализации DOLBIT-стека на Postgres эту проблему решает pgq. Посмотрите, насколько лаконичную документацию он имеет.
Отложенные задания
SELECT cron.schedule('0 5 31 2 *', $$select count(jokes) from articles where extract(MONTH from posted_at) = 4 and (DAY from posted_at) = 1$$ );
Даже если в проекте ещё нет фич, требующих асинхронного взаимодействия, то фичи требующие асинхронного выполнения, скорее всего есть. В обычной микросервисной среде для этого поднимается отдельный микросервис с cron-библиотекой. Отсылаясь к бизнес-логике в хранимых процедурах, возникает вопрос - зачем заниматься всем этим, если все параметры задач лежат в БД, рядом с данными, которые эти задачи будут обрабатывать. Используйте pg_cron.
Хранение файлов
ALTER TABLE mytable ADD COLUMN mybytea BYTEA;
Стандарт SQL дал нам типы данных BINARY и VARBINARY для хранения бинарных данных. В Postgres эти типы реализует bytea. Вы можете хранить блобы, не задумываясь о путях на дисках или в S3, а просто в таблицах, что снижает когнитивную нагрузку на разработчиков. Не нужен менеджмент доступов и отдельный девопс, как для упомянутой S3 - технологии, сменившей 3 версии, прежде чем стать популярной, вы вообще слышали об S1 или S2?
Заключение
Надеюсь, мне удалось показать, что SCUF/DOLBIT - это нормально. Одной PostgreSQL нам удалось заменить несколько технологий: Redis, MongoDB, ElasticSearch, Kafka и т.д., которые бы использовались десятком микросервисов.
А вообще, микросервисы это продукт капитализма - сейчас оба устарели и обходятся человечеству очень дорого. Микросервисы - это пропаганда дарвинистского подхода "разделяй и властвуй"! Ударим монументальным монолитом, не отчуждающим данные от средств их производства, по старорежимным избам микросервисов!
Подписывайтесь на канал DOLBIT!
