Начнем с того, что асинхронность — это конкурентное выполнение задач (мультизадачность, как если бы человек готовил обед и переключался на прочтение книги в перерывах), а синхронность — это последовательное выполнение задач (человек сначала приготовил обед, а потом уже читал книгу). Эти понятия часто путают. Теперь к делу!

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

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

⚙️ Аналогия: Представь крупный колл‑центр (Бэкенд), где оператор на первой линии никогда не заставляет тебя ждать. Его задача — за пару секунд выслушать проблему, быстро записать её на бланк и положить в стопку на столе (Redis). Как только бланк коснулся стола, оператор вежливо прощается и тут же принимает новый звонок, не тратя время на само решение. В это время в бэк‑офисе сидит специалист (Celery), который вообще не общается с клиентами, а просто по очереди берет бланки со стола и выполняет по ним сложную работу. Когда всё готово, он вписывает результат в отчет, и система мгновенно выдает тебе решение, при этом сам колл‑центр ни на секунду не переставал принимать новые обращения.

🚀 Теперь бэкенд принимает любые запросы быстро. Большие процессы стоят в режиме ожидания получения ответа, а мелкие запросы не блокируют друг друга за счёт асинхронности. Все запросы принимаются сразу и не остаются незамеченными, а вся большая нагрузка уходит на Celery. Зачем нам синхронность тогда нужна?

🔓 Во‑первых, если мы, как разработчики, вносим изменения в структуру базы данных (миграции), то тогда они применяются синхронно — строго по очереди, одна за другой. Сам бэкенд в этот момент остановлен и не принимает запросы, чтобы никакой процесс не успел записать данные в «старую» структуру пока она меняется.

📋 Во‑вторых, в Celery структура подразумевает синхронность процессов. Асинхронность не даёт прироста производительности, а только усложнит выполнение задач. В тоже время у нас в Celery нет потребности принять все задачи сразу, как в бэкенде — принять все запросы сразу. Поэтому выполнение задач в Celery в порядке их очереди (синхронно) — это отличная практика. Тем более раз один Celery — одна задача, то нагрузка на базу данных становится более предсказуемой, так как от Celery не прилетят тысячи запросов от разных сложных задач, а только запросы от одной конкретной.

🕷 Исключение: в моём проекте будет использоваться парсер, который будет брать данные у застройщиков. У каждого запроса больше всего времени будет уходить на ожидание ответа сайта застройщика. Здесь асинхронность сэкономит нам время, ведь пока мы ожидаем, мы можем совершить следующий запрос. ОДНАКО добавление этих данных в нашу базу данных мы будем делать синхронно, так как здесь нет ожидания и усложнения ни к чему. Разве что для оптимизации мы можем создавать записи пачками по 50 записей, чтобы обращений к базе данных стало в 50 раз меньше.

🗺 Подведём итог по архитектуре движения запросов в Losk Space на данном этапе:Простой запрос: Бэкенд (асинхронно принимает) ‑“ База Данных ‑“ Бэкенд (получает ответ)

Сложный запрос: Бэкенд (асинхронно принимает) ‑“ Redis (создает запись о задаче) ‑“ Celery (синхронно выполняет задачу и помечает в Redis её выполненной) ‑“ Бэкенд (получает ответ)

Миграции (изменение структуры Базы Данных): Бэкенд (останавливается) ‑“ База Данных (синхронно вносит изменения) ‑“ Бэкенд (продолжает работу в асинхронном режиме)

Парсер в Celery, который собирает данные о квартирах: Celery (асинхронно делает запросы к застройщикам) ‑“ Сайты застройщиков (с них собираются данные о квартирах) ‑“ Celery (синхронно отдаёт записи о квартирах в Базу Данных) ‑“ База Данных

🔜 P. S. На данный момент каждый из паттернов поведения находится в активной разработке. Когда они будут реализованы я посвящу этому отдельный пост.