Real-Time Backend
Kafka для real-time
Как LinkedIn прокачивает триллион сообщений в день, не теряя ни одного - и при чём здесь обычный текстовый файл на диске?
- LinkedIn обрабатывает 1 триллион+ сообщений в день через Kafka - активность пользователей, клики, обновления ленты - всё идёт через единый лог событий
- Uber использует Kafka Streams для расчёта surge pricing в реальном времени: события поездок → агрегация спроса/предложения по районам → динамический коэффициент тарифа за секунды
- Cloudflare логирует 10 миллионов запросов в секунду через Kafka: edge-узлы пишут события, WAF и аналитика читают независимо без блокировок друг друга
- Netflix использует Kafka для трекинга прогресса просмотра: даже при падении consumer группы данные не теряются - сервис догоняет пропущенные события по retention
Kafka Realtime
Apache Kafka - это распределённый лог событий, который хранит сообщения на диске и отдаёт их потребителям в порядке записи. В отличие от RabbitMQ или Google Pub/Sub, сообщения после чтения не удаляются: они лежат столько, сколько задаёт `retention.ms`. Это позволяет нескольким независимым сервисам читать один и тот же поток данных в разное время.
LinkedIn, где Kafka и родился, прокачивает через него свыше 1 триллиона сообщений в день - активность пользователей, клики, обновления фида. Cloudflare использует Kafka для логирования 10 миллионов запросов в секунду: каждый edge-узел пишет события в топик, аналитика и WAF-движок читают независимо, не блокируя друг друга.
Ключевое отличие от Pub/Sub: **retention**. Kafka хранит историю - можно перемотать на любой offset и воспроизвести события заново. Это критично для аудита, replay-тестирования новых сервисов и recovery после инцидента.
Cloudflare прокатила через Kafka WAF-движок и новый ML-аномалию-детектор. Оба читают топик `requests`. Если ML-детектор упал на 2 часа и потом поднялся - что произойдёт?
Consumer Lag
Consumer lag - разница между последним записанным offset (log end offset) и offset, который consumer group уже подтвердил. Если producer пишет 50 000 событий/сек, а consumer обрабатывает 40 000 - лаг растёт на 10 000 событий каждую секунду. Когда это происходит на Uber в момент surge pricing, задержка между поездкой и пересчётом тарифа начинает ощущаться пользователями.
Партиция 1 отстаёт на 35 000 событий - скорее всего, consumer, привязанный к ней, перегружен или завис. Мониторинг лага через Prometheus + `kafka_consumer_group_lag` метрику позволяет поставить алерт: если лаг превышает N и не снижается K секунд - страница on-call инженера.
- **Slow processing** - consumer тратит на одно сообщение больше времени, чем producer генерирует следующее
- **Consumer crash** - одна инстанция упала, rebalance занял несколько секунд, за это время лаг вырос
- **Traffic spike** - burst входящих событий превысил пропускную способность consumer группы
- **GC pause** - длинная Stop-the-World пауза у JVM-consumer заморозила обработку на сотни миллисекунд
Uber мониторит лаг consumer group `surge-pricing`. В 18:00 лаг вырос с 500 до 80 000 за 5 минут и продолжает расти. Что это означает?
Partitioning
Партиция - единица параллелизма в Kafka. Одну партицию читает ровно один consumer из группы одновременно. Если топик `ride-events` имеет 12 партиций, consumer group из 12 инстанций читает параллельно - каждая берёт по одной партиции. 13-я инстанция будет стоять без работы: партиций не хватит.
Ключ партиционирования определяет, в какую партицию попадает сообщение. Uber шардирует по `driver_id`: все события одного водителя гарантированно попадают в одну партицию, а значит обрабатываются в порядке прихода одним consumer-ом. Это критично для корректного расчёта маршрута и стоимости поездки.
**Количество партиций нельзя уменьшить** - только увеличить. При увеличении партиций тот же partition key может попасть в другую партицию (hash % new_count изменился), что нарушает ordering-гарантии. Планировать партиционирование нужно на этапе создания топика с запасом.
Uber использует `driver_id` как partition key. Почему именно такой выбор критичен для surge pricing?
Kafka Tuning
Kafka предоставляет три конфигурации надёжности producer-а через параметр `acks`. При `acks=0` producer не ждёт подтверждения - максимальный throughput, нулевые гарантии. При `acks=1` лидер-брокер подтверждает запись, но если он упадёт до репликации - сообщение потеряно. При `acks=all` все реплики ISR (in-sync replicas) подтверждают запись - полная durability, latency выше.
- **`linger.ms`** - время ожидания перед отправкой батча. Увеличение с 0 до 5 мс повышает throughput в 5-10 раз при минимальном росте latency
- **`batch.size`** - максимальный размер батча в байтах. По умолчанию 16KB; для высоконагруженных топиков - 64-256KB
- **`compression.type`** - snappy снижает объём на 50-70% при минимальной CPU нагрузке; lz4 быстрее; gzip компактнее но медленнее
- **`min.insync.replicas`** - минимум реплик для подтверждения при acks=all. Значение 2 из 3 реплик - стандарт для production
Больше партиций всегда означает лучшую производительность
Каждая партиция - это файл на диске и TCP-соединение; слишком много партиций увеличивает latency failover и нагрузку на ZooKeeper/KRaft
При падении брокера Kafka переназначает лидеров для всех его партиций. 10 000 партиций на брокер означают 10 000 операций переназначения - failover может занять десятки секунд. LinkedIn рекомендует не более 4000 партиций на брокер и 200 000 на кластер.
Stripe обрабатывает платёжные события через Kafka. Какую комбинацию `acks` и `idempotent` следует использовать для топика `payment-transactions`?
Итоги
- Kafka хранит сообщения как append-only лог с retention-периодом - несколько consumer groups читают один топик независимо, каждая со своим offset
- Consumer lag - разница между тем, что записано, и тем, что прочитано группой; растущий лаг означает, что consumer не успевает за producer-ом
- Количество партиций определяет максимальный параллелизм: один consumer из группы - одна партиция; partition key гарантирует ordering событий одной сущности
- Для надёжности финансовых данных: acks=all + idempotent=true; для аналитических логов: acks=1 + крупные батчи + сжатие
Связанные темы
Kafka встраивается в более широкие паттерны real-time архитектуры
- Горизонтальное масштабирование — Партиционирование Kafka - конкретная реализация sharding для потоков событий
- Event-driven архитектура — Kafka - основной transport layer для event sourcing и CQRS паттернов
- Мониторинг и observability — Consumer lag - ключевая метрика health check real-time пайплайна
Вопросы для размышления
- Если бы нужно было выбрать между Kafka и Redis Pub/Sub для системы аналитики с 10+ независимыми потребителями данных - какой фактор стал бы решающим?
- Uber шардирует события по driver_id. Что произойдёт с ordering-гарантиями, если завтра добавить партиций в топик без миграции данных?
- В каком сценарии высокий consumer lag - нормальная ситуация, а не повод для алерта?