Семь систем, из которых собирают бэкенд. Для каждой — как она устроена, когда её брать и когда она только помешает.
Листайте стрелками ← →, свайпом или кнопками внизу. В схемах нажимайте кнопки и двигайте ползунки.
Типичный бэкенд: приложение без состояния и несколько хранилищ вокруг, у каждого своя работа.
Нажмите на блок схемы, чтобы узнать, зачем он нужен. Не каждому проекту нужны все семь: многие живут на одном Postgres годами.
Реляционная база — источник правды для данных бизнеса. Её главное свойство — транзакции: несколько изменений применяются вместе или не применяются вовсе.
BEGIN;
UPDATE accounts SET balance = balance - 30
WHERE name = 'Алиса';
UPDATE accounts SET balance = balance + 30
WHERE name = 'Боб';
COMMIT;
Уроните сервер посреди перевода — с транзакцией и без. А если переводить, пока у Алисы не кончатся деньги, сработает ограничение CHECK (balance >= 0).
Без индекса запрос WHERE user_id = 42 перебирает каждую строку. B-дерево находит нужную за несколько чтений, даже среди миллиардов строк.
CREATE INDEX orders_user_idx ON orders (user_id);
EXPLAIN SELECT * FROM orders WHERE user_id = 42;
-- Index Scan using orders_user_idx on orders
У индекса есть цена: он занимает место и замедляет каждую вставку и обновление, ведь его тоже нужно менять. Индексируйте колонки, по которым действительно ищете.
JOIN, фильтрами и сортировкой.jsonb), полнотекстовый поиск, геоданные (PostGIS) и простые очереди.Redis хранит ключи и значения в оперативной памяти. Классическое применение — кэш перед базой: прочитали из Postgres один раз, а следующие запросы получают готовый ответ из памяти.
GET product:1 → (nil), промах
SELECT … FROM products → 30 мс
SET product:1 "…" EX 8 → живёт 8 секунд
GET product:1 → попадание, 0,4 мс
Самое сложное в кэше — инвалидация. Поднимите цену кофе: пока ключ жив, пользователи видят старую цену. Включите удаление ключа при изменении — или терпите устаревшие данные до конца TTL.
INCR атомарен.JOIN и произвольных фильтров, только доступ по ключу.Приложение не делает долгую работу само, а публикует сообщение. Брокер раскладывает его по очередям, воркеры забирают сообщения и подтверждают обработку (ack). После ack сообщение удаляется.
exchange "events" (topic):
order.* → очередь «склад»
order.paid → очередь «письма»
user.signup → очередь «письма»
Выключите воркер посреди обработки: сообщение без ack вернётся в очередь и достанется снова. Поэтому обработчик должен быть идемпотентным: повторная обработка не должна, например, дважды списать деньги.
FOR UPDATE SKIP LOCKED часто справляются. Хватит PostgreSQLKafka не раздаёт сообщения, а дописывает их в конец журнала — топика. Каждая группа потребителей сама помнит, до какого места дочитала (offset). Чтение ничего не удаляет: события хранятся заданное время (retention).
Топик делится на партиции — так Kafka масштабируется на миллионы событий в секунду. Порядок гарантирован только внутри партиции, поэтому события одного заказа отправляют с одним ключом.
Обе системы передают сообщения, но решают разные задачи. RabbitMQ — почтальон: доставил и забыл. Kafka — архив: записал, а читатели приходят сами.
Поисковый движок строит обратный индекс: для каждого слова — список документов, где оно встречается. Слова приводятся к основе, поэтому «красные» находит «красная».
LIKE '%…%' в обычной базе ищет точную подстроку и читает всю таблицу. Elasticsearch находит слова в любом порядке и в любой форме и сортирует результаты по релевантности. В демо упрощённый стемминг; настоящий умеет больше, включая поиск с опечатками.
Postgres хранит таблицу построчно: чтобы сложить одну колонку, он читает строки целиком. ClickHouse хранит каждую колонку отдельно и читает только нужные. Одинаковые значения подряд ещё и отлично сжимаются.
Каждая полоса в схеме — то, что лежит на диске подряд. Выберите запрос и сравните, сколько данных прочитает каждая база. Для поиска одной строки по ключу всё наоборот: построчное хранение выигрывает.
UPDATE и DELETE. Лучше PostgreSQLОбъектное хранилище: кладёте файл по ключу и получаете его по ключу через HTTP. Дёшево, почти безгранично, легко раздавать через CDN. Это может быть AWS S3 или совместимое хранилище: MinIO, Cloudflare R2, Yandex Object Storage.
-- в базе только ключ файла
INSERT INTO photos (user_id, s3_key)
VALUES (42, 'users/42/cat.jpg');
-- сам файл клиент загружает напрямую в S3
-- по временной подписанной ссылке (presigned URL)
Девять задач из реальных проектов. Выберите технологию и сравните с ответом.
У некоторых задач несколько разумных решений. Обратите внимание, как часто «Postgres тоже справится».
Выбирайте скучные технологии.Дэн Маккинли, «Choose Boring Technology»