This media is not supported in your browser
VIEW IN TELEGRAM
SQLZap это прям находка
sqlzap.com — это онлайн-платформа для тренировок SQL-запросов в браузере. Что-то вроде интерактивного тренажёра
Идеально чтобы натаскать руку (как Leetcode, только для SQL)
👉 @BackendPortal
sqlzap.com — это онлайн-платформа для тренировок SQL-запросов в браузере. Что-то вроде интерактивного тренажёра
Идеально чтобы натаскать руку (как Leetcode, только для SQL)
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🔥2
Как TikTok справляется с миллионами коротких видео в реальном времени?
TikTok использует микросервисную архитектуру, где разные функции (загрузка видео, лента, комментарии, рекомендации) разбиты на независимые сервисы.
Когда вы открываете TikTok, ваш запрос проходит через балансировщики нагрузки и API-шлюзы, которые мгновенно направляют вас к нужному сервису.
Видео хранятся в распределенном облачном хранилище и доставляются через глобальные CDN (Content Delivery Networks). Это обеспечивает быструю загрузку ленты с минимальной буферизацией вне зависимости от вашего местоположения.
Ядро TikTok работает на ключевых сервисах (API). Сервис аутентификации управляет логинами и аккаунтами, сервис профилей пользователей хранит вашу активность, а сервис ленты формирует персонализированный список видео.
Знаменитая «For You Page» работает через сервис рекомендаций, который использует AI и машинное обучение для ранжирования и подбора видео. Отдельный сервис поиска помогает быстро находить тренды и авторов.
За кулисами TikTok обрабатывает огромные объемы данных. Поведение пользователей, лайки, время просмотра и взаимодействия постоянно поступают в модели машинного обучения, чтобы рекомендации обновлялись в реальном времени.
Базы данных специализированы: одни — для аккаунтов пользователей, другие — для метаданных видео, третьи — для аналитики.
Система спроектирована с учетом высокой доступности и отказоустойчивости, что позволяет TikTok работать стабильно даже при сбоях отдельных сервисов.
На глобальном уровне TikTok поддерживает сотни миллионов одновременных пользователей, используя облачную инфраструктуру и распределенные по миру CDN.
Технический стек TikTok:
👉 @BackendPortal
TikTok использует микросервисную архитектуру, где разные функции (загрузка видео, лента, комментарии, рекомендации) разбиты на независимые сервисы.
Когда вы открываете TikTok, ваш запрос проходит через балансировщики нагрузки и API-шлюзы, которые мгновенно направляют вас к нужному сервису.
Видео хранятся в распределенном облачном хранилище и доставляются через глобальные CDN (Content Delivery Networks). Это обеспечивает быструю загрузку ленты с минимальной буферизацией вне зависимости от вашего местоположения.
Ядро TikTok работает на ключевых сервисах (API). Сервис аутентификации управляет логинами и аккаунтами, сервис профилей пользователей хранит вашу активность, а сервис ленты формирует персонализированный список видео.
Знаменитая «For You Page» работает через сервис рекомендаций, который использует AI и машинное обучение для ранжирования и подбора видео. Отдельный сервис поиска помогает быстро находить тренды и авторов.
За кулисами TikTok обрабатывает огромные объемы данных. Поведение пользователей, лайки, время просмотра и взаимодействия постоянно поступают в модели машинного обучения, чтобы рекомендации обновлялись в реальном времени.
Базы данных специализированы: одни — для аккаунтов пользователей, другие — для метаданных видео, третьи — для аналитики.
Система спроектирована с учетом высокой доступности и отказоустойчивости, что позволяет TikTok работать стабильно даже при сбоях отдельных сервисов.
На глобальном уровне TikTok поддерживает сотни миллионов одновременных пользователей, используя облачную инфраструктуру и распределенные по миру CDN.
Технический стек TikTok:
🔸 Frontend: React, Node.js, TypeScript🔸 Backend: Golang, Python, Java, Scala🔸 API-коммуникация: gRPC, GraphQL🔸 Mobile: Swift (iOS), Kotlin (Android)🔸 Базы данных: MySQL, Redis, Cassandra, TiDB🔸 Messaging: Apache Kafka, Pulsar🔸 Обработка данных: Apache Flink, Hadoop, Spark, Hive🔸 Безопасность: собственная IAM, слои шифрования, мониторинг трафика🔸 Хранилище видео: распределенное облако + глобальный CDN (собственный CDN ByteDance)🔸 DevOps: Kubernetes, Docker, Prometheus, Grafana, Chaos Testing🔸 Машинное обучение: TensorFlow, PyTorch, собственные AI-фреймворки ByteDance
Please open Telegram to view this post
VIEW IN TELEGRAM
❤18
Каждый разработчик в растущем e-commerce сталкивался с этим вопросом:
Как масштабировать процесс создания заказов во время флеш-распродажи?
Есть 4 варианта.
Работает только один.
Разберём по порядку:
I. Синхронное создание заказа
. Запрос блокируется.
. Запись в БД в "горячем" пути.
. Ложится под нагрузкой.
. Не масштабируется.
II. Асинхронная обработка через очередь✅
. Принимаем заказ.
. Кладём его в очередь.
. Быстро возвращаем ответ.
. Обрабатываем позже.
Это развязывает API и нагрузку:
. Масштабируется.
. Переживает пиковые всплески.
. Даёт контроль.
. Работает, потому что очередь берёт удар на себя.
III. Централизованный сервис заказов
. Один большой сервис.
. Один большой bottleneck.
. Код проще, проблемы те же.
. Разваливается на масштабе.
IV. Сплошные микросервисы
. Вносит задержки, координацию и новые точки отказа.
. Всё ещё не сглаживает пиковую нагрузку.
. Инструмент не для этой задачи.
Компромиссы (они всегда есть):
I. Eventual consistency.
II. Нужна идемпотентность (и так критично).
III. Нужно мониторить состояние очереди.
IV. Требуются компенсирующие транзакции.
V. Очередь сама по себе не решает всё.
👉 @BackendPortal
Как масштабировать процесс создания заказов во время флеш-распродажи?
Есть 4 варианта.
Работает только один.
Разберём по порядку:
I. Синхронное создание заказа
. Запрос блокируется.
. Запись в БД в "горячем" пути.
. Ложится под нагрузкой.
. Не масштабируется.
II. Асинхронная обработка через очередь
. Принимаем заказ.
. Кладём его в очередь.
. Быстро возвращаем ответ.
. Обрабатываем позже.
Это развязывает API и нагрузку:
. Масштабируется.
. Переживает пиковые всплески.
. Даёт контроль.
. Работает, потому что очередь берёт удар на себя.
III. Централизованный сервис заказов
. Один большой сервис.
. Один большой bottleneck.
. Код проще, проблемы те же.
. Разваливается на масштабе.
IV. Сплошные микросервисы
. Вносит задержки, координацию и новые точки отказа.
. Всё ещё не сглаживает пиковую нагрузку.
. Инструмент не для этой задачи.
Компромиссы (они всегда есть):
I. Eventual consistency.
II. Нужна идемпотентность (и так критично).
III. Нужно мониторить состояние очереди.
IV. Требуются компенсирующие транзакции.
V. Очередь сама по себе не решает всё.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9
Клиентское кэширование в HTTP работает так
Сервер может отдавать два типа ресурсов — статические и динамические. Статические данные не меняются между запросами, поэтому их можно кэшировать на стороне клиента с помощью специальных HTTP-заголовков.
Когда клиент впервые делает GET-запрос к ресурсу, локальный кэш проверяет его наличие. Если ресурса нет, запрос уходит на сервер. Сервер в ответе указывает, что данные можно закэшировать -> заголовок Cache-Control задаёт время жизни ресурса, а ETag определяет его конкретную версию. Кэш сохраняет ответ и возвращает его клиенту.
При повторном запросе, если ресурс ещё актуален, кэш сразу отдаёт его клиенту, минуя сервер. Однако сервер может обновить ресурс до истечения срока жизни в кеше, поэтому данные в кеше и на сервере не всегда строго согласованы. Обычно это приемлемо, а чтобы гарантировать обновление, сервер просто меняет версию ресурса.
Если ресурс в кеше устарел, кэш отправляет новый запрос на сервер с условным заголовком, например If-None-Match, где указывает сохранённую версию. Если сервер имеет новую версию, он возвращает её. Если изменений не было, он отвечает кодом 304 Not Modified, и клиент продолжает использовать локальные данные.
👉 @BackendPortal
Сервер может отдавать два типа ресурсов — статические и динамические. Статические данные не меняются между запросами, поэтому их можно кэшировать на стороне клиента с помощью специальных HTTP-заголовков.
Когда клиент впервые делает GET-запрос к ресурсу, локальный кэш проверяет его наличие. Если ресурса нет, запрос уходит на сервер. Сервер в ответе указывает, что данные можно закэшировать -> заголовок Cache-Control задаёт время жизни ресурса, а ETag определяет его конкретную версию. Кэш сохраняет ответ и возвращает его клиенту.
При повторном запросе, если ресурс ещё актуален, кэш сразу отдаёт его клиенту, минуя сервер. Однако сервер может обновить ресурс до истечения срока жизни в кеше, поэтому данные в кеше и на сервере не всегда строго согласованы. Обычно это приемлемо, а чтобы гарантировать обновление, сервер просто меняет версию ресурса.
Если ресурс в кеше устарел, кэш отправляет новый запрос на сервер с условным заголовком, например If-None-Match, где указывает сохранённую версию. Если сервер имеет новую версию, он возвращает её. Если изменений не было, он отвечает кодом 304 Not Modified, и клиент продолжает использовать локальные данные.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2
Вопрос по системному дизайну
Как убедиться, что реплика синхронизирована с мастером и что данные корректны?
Мастер отправляет репликам логические операции, которые они применяют по порядку:
После того как реплика обработала эти изменения (добавила два яблока, удалила один апельсин), как проверить, что оба узла в итоге пришли к одному и тому же состоянию?
Требования:
• Проверка должна работать за O(delta), где delta — это набор применённых изменений
• Проверка состояния должна занимать минимально возможное количество памяти
Дополнительно:
• Должна быть поддержка операций удаления
• Может ли система определить, где произошло расхождение?
• Может ли она определить, когда произошло расхождение?
👉 @BackendPortal
Как убедиться, что реплика синхронизирована с мастером и что данные корректны?
Мастер отправляет репликам логические операции, которые они применяют по порядку:
{"op": "add", "id": "apple"}
{"op": "add", "id": "apple"}
{"op": "remove", "id": "orange"}После того как реплика обработала эти изменения (добавила два яблока, удалила один апельсин), как проверить, что оба узла в итоге пришли к одному и тому же состоянию?
Требования:
• Проверка должна работать за O(delta), где delta — это набор применённых изменений
• Проверка состояния должна занимать минимально возможное количество памяти
Дополнительно:
• Должна быть поддержка операций удаления
• Может ли система определить, где произошло расхождение?
• Может ли она определить, когда произошло расхождение?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Как backend-разработчику в 2025 году оставаться востребованным
Изучи эти 11 навыков
I. Проектирование API — REST, GraphQL, gRPC.
II. Аутентификация и авторизация — OAuth2, JWT, OpenID Connect, Passkeys.
III. Базы данных — SQL, NoSQL, шардинг, индексы, оптимизация запросов.
IV. Кэширование — Redis, CDN, стратегии edge-кэширования.
V. Событийно-ориентированные системы — Kafka, Pulsar, стриминговые пайплайны.
VI. Конкурентность и асинхронность — реактивное программирование, структурированная конкуренция.
VII. Распределённые системы — микросервисы, service mesh, eventual consistency.
VIII. Безопасность — HTTPS, шифрование, zero trust, OWASP top 10.
IX. Обсервабилити — логирование, трассировка, метрики, OpenTelemetry.
X. Облако и деплоймент — Docker, Kubernetes, serverless, GitOps.
XI. Интеграция ИИ — LLM API, векторные базы данных, retrieval-augmented системы.
Хватит прыгать с одного языка на другой.
👉 @BackendPortal
Изучи эти 11 навыков
I. Проектирование API — REST, GraphQL, gRPC.
II. Аутентификация и авторизация — OAuth2, JWT, OpenID Connect, Passkeys.
III. Базы данных — SQL, NoSQL, шардинг, индексы, оптимизация запросов.
IV. Кэширование — Redis, CDN, стратегии edge-кэширования.
V. Событийно-ориентированные системы — Kafka, Pulsar, стриминговые пайплайны.
VI. Конкурентность и асинхронность — реактивное программирование, структурированная конкуренция.
VII. Распределённые системы — микросервисы, service mesh, eventual consistency.
VIII. Безопасность — HTTPS, шифрование, zero trust, OWASP top 10.
IX. Обсервабилити — логирование, трассировка, метрики, OpenTelemetry.
X. Облако и деплоймент — Docker, Kubernetes, serverless, GitOps.
XI. Интеграция ИИ — LLM API, векторные базы данных, retrieval-augmented системы.
Хватит прыгать с одного языка на другой.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍5
Консистентность «read-your-writes» означает, что любая запись, сделанная в базу данных, сразу становится доступной для чтения тем же клиентом.
Звучит очевидно, но бывают ситуации, когда это правило не выполняется, особенно при работе на больших масштабах.
На сервере с одной нодой это легко гарантировать при использовании последовательных транзакций.
В среде с primary и replica всё сложнее. Во многих базах данных все записи и часть чтений обрабатываются на primary, а большая часть чтений выполняется на репликах. Из-за задержки репликации может возникнуть ситуация, когда клиент записывает данные в базу и тут же пытается их прочитать с реплики, но записи там ещё нет.
Такое возможно при использовании асинхронной или полусинхронной репликации, так как они не требуют, чтобы все реплики получили данные до ответа клиенту. При синхронной репликации primary отвечает только после того, как все реплики подтвердят получение записи.
Если используется асинхронная или полусинхронная репликация, чтения на реплики лучше направлять только тогда, когда консистентность «read-your-writes» не критична.
👉 @BackendPortal
Звучит очевидно, но бывают ситуации, когда это правило не выполняется, особенно при работе на больших масштабах.
На сервере с одной нодой это легко гарантировать при использовании последовательных транзакций.
В среде с primary и replica всё сложнее. Во многих базах данных все записи и часть чтений обрабатываются на primary, а большая часть чтений выполняется на репликах. Из-за задержки репликации может возникнуть ситуация, когда клиент записывает данные в базу и тут же пытается их прочитать с реплики, но записи там ещё нет.
Такое возможно при использовании асинхронной или полусинхронной репликации, так как они не требуют, чтобы все реплики получили данные до ответа клиенту. При синхронной репликации primary отвечает только после того, как все реплики подтвердят получение записи.
Если используется асинхронная или полусинхронная репликация, чтения на реплики лучше направлять только тогда, когда консистентность «read-your-writes» не критична.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Кэшировать или не кэшировать?
Это вопрос, с которым бэкендер сталкивается каждый день.
Большинство инженеров кэшируют слишком много.
Это ленивая инженерия.
Вот небольшой фреймворк, чтобы принимать решение правильно:
I. Данные часто запрашиваются?
II. Их дорого получать?
III. Они изменчивые?
IV. Объём данных большой?
V. Влияет ли это на воспринимаемую пользователем задержку?
VI. Безопасно ли кэшировать?
VII. Есть ли механизм протухания или инвалидации кэша?
👉 @BackendPortal
Это вопрос, с которым бэкендер сталкивается каждый день.
Большинство инженеров кэшируют слишком много.
Это ленивая инженерия.
Вот небольшой фреймворк, чтобы принимать решение правильно:
I. Данные часто запрашиваются?
II. Их дорого получать?
III. Они изменчивые?
IV. Объём данных большой?
V. Влияет ли это на воспринимаемую пользователем задержку?
VI. Безопасно ли кэшировать?
VII. Есть ли механизм протухания или инвалидации кэша?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6❤3
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Суперпонятные гайды по программированию: ООП, Docker, Kubernetes, Git, OAuth — всё объясняется на примере милых котиков! 🐱
👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤8🔥2
Бесплатный прирост производительности для full table scan в Postgres 17
Смотри, Postgres как и большинство баз данных работает с фиксированными по размеру страницами. В таком формате хранится всё, включая индексы и данные таблиц. Размер страницы 8КБ, каждая страница содержит строки или индексные кортежи плюс фиксированный заголовок. По сути, страницы это просто байты в файлах, которые читаются и кешируются в buffer pool.
Например, чтобы прочитать страницу 0, вызывается read с offset 0 и длиной 8192 байта. Чтобы прочитать страницу 1, выполняется ещё один системный вызов read с offset 8193 и длиной 8192. Страница 7 это уже offset 57 345 и так далее.
Если таблица занимает 100 страниц в файле, то для full table scan мы сделаем 100 системных вызовов. У каждого вызова есть накладные расходы
Фича в Postgres 17 в том, что теперь можно объединять I/O. Можно задать, сколько операций объединять. Технически можно просканировать всю таблицу за один системный вызов. Это не всегда хорошая идея, и я ещё расскажу почему.
Также здесь добавили vectorized I/O с помощью системного вызова preadv, который принимает массив офсетов и длин для рандомных чтений.
Основная сложность это не читать лишнего. Допустим, я делаю seq scan и ищу конкретное значение. Я читаю страницу 0, нахожу результат и выхожу. Дальше читать не нужно. А с этой фичей я могу прочитать сразу 10 страниц за один вызов, вытащить их содержимое в shared buffers и только потом обнаружить, что результат был уже на первой странице. В итоге я зря потратил диск, память и пропускную способность.
Балансировать это будет непросто.
Важно понимать, что настоящий Postgres делает системный вызов в ядро, чтобы прочитать по 8К за раз. При этом ядро можно настроить на read ahead. В этом случае оно будет читать немного больше и кешировать данные в файловом кеше.
👉 @BackendPortal
Смотри, Postgres как и большинство баз данных работает с фиксированными по размеру страницами. В таком формате хранится всё, включая индексы и данные таблиц. Размер страницы 8КБ, каждая страница содержит строки или индексные кортежи плюс фиксированный заголовок. По сути, страницы это просто байты в файлах, которые читаются и кешируются в buffer pool.
Например, чтобы прочитать страницу 0, вызывается read с offset 0 и длиной 8192 байта. Чтобы прочитать страницу 1, выполняется ещё один системный вызов read с offset 8193 и длиной 8192. Страница 7 это уже offset 57 345 и так далее.
Если таблица занимает 100 страниц в файле, то для full table scan мы сделаем 100 системных вызовов. У каждого вызова есть накладные расходы
Фича в Postgres 17 в том, что теперь можно объединять I/O. Можно задать, сколько операций объединять. Технически можно просканировать всю таблицу за один системный вызов. Это не всегда хорошая идея, и я ещё расскажу почему.
Также здесь добавили vectorized I/O с помощью системного вызова preadv, который принимает массив офсетов и длин для рандомных чтений.
Основная сложность это не читать лишнего. Допустим, я делаю seq scan и ищу конкретное значение. Я читаю страницу 0, нахожу результат и выхожу. Дальше читать не нужно. А с этой фичей я могу прочитать сразу 10 страниц за один вызов, вытащить их содержимое в shared buffers и только потом обнаружить, что результат был уже на первой странице. В итоге я зря потратил диск, память и пропускную способность.
Балансировать это будет непросто.
Важно понимать, что настоящий Postgres делает системный вызов в ядро, чтобы прочитать по 8К за раз. При этом ядро можно настроить на read ahead. В этом случае оно будет читать немного больше и кешировать данные в файловом кеше.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3
Ваша софтверная архитектура всегда так же сложна, как и ваша организация
Слышали про Закон Конвея? Это теория, сформулированная компьютерным учёным Мелвином Конвеем в 1967 году. Она гласит:
Другими словами, структура софтверной системы часто определяется структурой и паттернами коммуникации внутри команды, которая её разрабатывает.
Из-за этого архитектура может оказаться неоптимальной для решаемой задачи — команда невольно начинает ставить свои организационные ограничения выше потребностей системы.
Например:
- организация с небольшими распределёнными командами скорее всего придёт к модульной (сервисной) архитектуре,
- а организация с крупными коллокированными командами — к монолитной архитектуре.
В широком смысле можно даже сказать, что именно HR во многом определяет архитектуру софта.🤙
Чтобы обойти это ограничение, используют манёвр обратного Конвея (Inverse Conway Maneuver). Суть его в том, что архитекторы, инженеры и лиды вовлекаются в проектирование организационной структуры. Такой подход повышает шансы на более удачную архитектуру.
Тем не менее, многие компании игнорируют закон Конвея и живут в уверенности, что оргструктура и архитектура системы — вещи независимые. В итоге это оборачивается неприятными сюрпризами.
А теперь к вам, каков ваш опыт столкновения с Законом Конвея?👧
👉 @BackendPortal
Слышали про Закон Конвея? Это теория, сформулированная компьютерным учёным Мелвином Конвеем в 1967 году. Она гласит:
«Организации, которые проектируют системы, ограничены в своих возможностях создавать дизайны, являющиеся копиями их собственных коммуникационных структур».
Другими словами, структура софтверной системы часто определяется структурой и паттернами коммуникации внутри команды, которая её разрабатывает.
Из-за этого архитектура может оказаться неоптимальной для решаемой задачи — команда невольно начинает ставить свои организационные ограничения выше потребностей системы.
Например:
- организация с небольшими распределёнными командами скорее всего придёт к модульной (сервисной) архитектуре,
- а организация с крупными коллокированными командами — к монолитной архитектуре.
В широком смысле можно даже сказать, что именно HR во многом определяет архитектуру софта.
Чтобы обойти это ограничение, используют манёвр обратного Конвея (Inverse Conway Maneuver). Суть его в том, что архитекторы, инженеры и лиды вовлекаются в проектирование организационной структуры. Такой подход повышает шансы на более удачную архитектуру.
Тем не менее, многие компании игнорируют закон Конвея и живут в уверенности, что оргструктура и архитектура системы — вещи независимые. В итоге это оборачивается неприятными сюрпризами.
А теперь к вам, каков ваш опыт столкновения с Законом Конвея?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍4
Концепции API, которые обсуждают на собеседованиях, не пропускай, если ты backend-разработчик:
I. Идемпотентность: понимайте, почему PUT/DELETE идемпотентны, а POST — нет. Это помогает избегать случайных двойных записей.
II. Пагинация: offset работает до определённого масштаба. Для больших наборов данных используйте курсор/ключи
III. Версионирование: URI vs Header vs Query param. Единственно правильного способа нет, есть только компромиссы.
IV. Ограничение частоты запросов: Token bucket лучше простой фиксированной временной окна, если важна справедливость.
V. Контракты ошибок: 400 ≠ 422 ≠ 409. Не кидайте 500 повсюду.
VI. Кэширование: ETag + Cache-Control спасают от лишней нагрузки на БД.
VII. Безопасность: JWT истекают не просто так. Не храните в них PII пользователей.
VIII. N+1 запросы: убивайте их на ранней стадии. Используйте batching или join’ы при возврате вложенных ресурсов.
IX. Документация: OpenAPI/Swagger обязателен.
X. Консистентность: иногда кэшированных данных хватает.
👉 @BackendPortal
I. Идемпотентность: понимайте, почему PUT/DELETE идемпотентны, а POST — нет. Это помогает избегать случайных двойных записей.
II. Пагинация: offset работает до определённого масштаба. Для больших наборов данных используйте курсор/ключи
III. Версионирование: URI vs Header vs Query param. Единственно правильного способа нет, есть только компромиссы.
IV. Ограничение частоты запросов: Token bucket лучше простой фиксированной временной окна, если важна справедливость.
V. Контракты ошибок: 400 ≠ 422 ≠ 409. Не кидайте 500 повсюду.
VI. Кэширование: ETag + Cache-Control спасают от лишней нагрузки на БД.
VII. Безопасность: JWT истекают не просто так. Не храните в них PII пользователей.
VIII. N+1 запросы: убивайте их на ранней стадии. Используйте batching или join’ы при возврате вложенных ресурсов.
IX. Документация: OpenAPI/Swagger обязателен.
X. Консистентность: иногда кэшированных данных хватает.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍4
Новая подборка open source веб-проектов, которые уже работают в продакшене. Проекты разделены по языкам и фреймворкам: Python/Django, JS/NextJS, Go, PHP и другие.
Можно не только изучать кодовую базу, но и участвовать -> делать баг-репорты, пулл-реквесты или просто смотреть, как устроена архитектура, структура каталогов, CI/CD и другие процессы.
Отличный способ прокачать навыки и посмотреть, как реальные проекты живут в продакшене.👩💻
👉 @BackendPortal
Можно не только изучать кодовую базу, но и участвовать -> делать баг-репорты, пулл-реквесты или просто смотреть, как устроена архитектура, структура каталогов, CI/CD и другие процессы.
Отличный способ прокачать навыки и посмотреть, как реальные проекты живут в продакшене.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
Как Discord тянет миллион онлайна на одном сервере
По мере роста аудитории Discord отдельные сервера начали упираться в лимиты по пропускной способности и отклику. Нужно было масштабировать их не с десятков тысяч, а сразу до миллионов одновременных пользователей.
Каждое действие в чате вроде отправки сообщения или входа в канал требует обновления UI у всех онлайн. Внутри Discord сервер называется guild и работает в одном Elixir процессе. Отдельный процесс это session для каждого клиента. Guild хранит все сессии участников и управляет их действиями. Обновления из сессий отправляются через вебсокеты клиентам.
Главная проблема это одно сообщение должно улететь всем онлайн. Если на сервере тысяча человек и каждый напишет по сообщению получится миллион доставок.
Как они это решили
1. Passive sessions
Discord стал различать активные и пассивные соединения. Для пассивных клиентов обновления режутся до минимума. Это снизило нагрузку на fanout почти на 90 процентов в больших серверах.
2. Relays
Ввели систему relay что-то вроде многопоточности на уровне инфраструктуры. Fanout теперь распределяется по нескольким машинам. Guild держит только базовую логику а relay процессы подключаются к сессиям, проверяют права и рассылают данные.
3. Worker процессы и ETS
Чтобы не блокировать guild процесс тяжелые операции вынесли в отдельные воркеры. Для работы с огромными списками участников они используют ETS (Erlang Term Storage) быструю in-memory базу к которой безопасно обращаются сразу несколько процессов. Guild создаёт воркер, передаёт ему таблицу ETS и тот делает всю дорогую работу.
В результате логика распределена, нагрузка размазана по воркерам и релеям, данные отправляются только активным пользователям. Всё это вместе позволяет держать миллион и больше онлайна на одном сервере.
👉 @BackendPortal
По мере роста аудитории Discord отдельные сервера начали упираться в лимиты по пропускной способности и отклику. Нужно было масштабировать их не с десятков тысяч, а сразу до миллионов одновременных пользователей.
Каждое действие в чате вроде отправки сообщения или входа в канал требует обновления UI у всех онлайн. Внутри Discord сервер называется guild и работает в одном Elixir процессе. Отдельный процесс это session для каждого клиента. Guild хранит все сессии участников и управляет их действиями. Обновления из сессий отправляются через вебсокеты клиентам.
Главная проблема это одно сообщение должно улететь всем онлайн. Если на сервере тысяча человек и каждый напишет по сообщению получится миллион доставок.
Как они это решили
1. Passive sessions
Discord стал различать активные и пассивные соединения. Для пассивных клиентов обновления режутся до минимума. Это снизило нагрузку на fanout почти на 90 процентов в больших серверах.
2. Relays
Ввели систему relay что-то вроде многопоточности на уровне инфраструктуры. Fanout теперь распределяется по нескольким машинам. Guild держит только базовую логику а relay процессы подключаются к сессиям, проверяют права и рассылают данные.
3. Worker процессы и ETS
Чтобы не блокировать guild процесс тяжелые операции вынесли в отдельные воркеры. Для работы с огромными списками участников они используют ETS (Erlang Term Storage) быструю in-memory базу к которой безопасно обращаются сразу несколько процессов. Guild создаёт воркер, передаёт ему таблицу ETS и тот делает всю дорогую работу.
В результате логика распределена, нагрузка размазана по воркерам и релеям, данные отправляются только активным пользователям. Всё это вместе позволяет держать миллион и больше онлайна на одном сервере.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤3