1. Архитектура Apache Kafka: брокеры, топики, партиции и кластеры
Архитектура Apache Kafka: брокеры, топики, партиции и кластеры
Разработка высоконагруженных микросервисов на Go редко обходится без надежной шины данных. Когда стандартные брокеры сообщений перестают справляться с потоком в сотни тысяч событий в секунду, архитекторы выбирают Apache Kafka. Для Middle Go-разработчика понимание внутренних механизмов этой системы — это не просто строчка в резюме, а необходимость для успешного прохождения секций по System Design и написания отказоустойчивого кода.
> Kafka — это не просто модная система для обработки данных, это реальная рабочая лошадка в мире потокового программирования. > > arenda-server.cloud
В основе высокой производительности системы лежит концепция append-only лога (журнала, работающего только на добавление). В отличие от классических реляционных баз данных, где данные постоянно перезаписываются, здесь новые события просто дописываются в конец файла. Это позволяет операционной системе максимально эффективно использовать кэш страниц и обеспечивает линейную скорость записи на диск, которая имеет сложность , где время выполнения операции не зависит от текущего объема данных в файле.
Брокеры и формирование кластера
Физической основой системы является брокер (broker) — отдельный сервер или контейнер, на котором запущен процесс Kafka. Брокер принимает сообщения от производителей, сохраняет их на диск и отдает потребителям по запросу.
Один сервер не может обеспечить высокую доступность и масштабируемость, поэтому брокеры объединяются в кластер (cluster). Внутри кластера один из брокеров берет на себя роль контроллера. Контроллер отвечает за управление состоянием системы: он отслеживает падения соседних узлов, переназначает лидеров для распределения нагрузки и хранит метаданные.
Долгое время для координации кластера использовалась внешняя служба ZooKeeper. Однако в современных версиях произошел переход на протокол KRaft (Kafka Raft), который позволил брокерам самостоятельно управлять метаданными, избавив администраторов от необходимости поддерживать дополнительную инфраструктуру.
Пример масштабирования: если ваш сервис на Go генерирует 50 000 логов в секунду, и один брокер начинает упираться в лимиты сетевого интерфейса (например, достигает пропускной способности в 1 Гбит/с), вы просто добавляете в кластер новый сервер. Система автоматически перераспределит часть нагрузки на новичка.
Топики и партиции: логика и физика
Чтобы разработчики могли разделять потоки данных (например, отделять логи авторизации от транзакций), используется топик (topic). Это логическое имя канала, куда публикуются сообщения. Но если бы топик хранился целиком на одном брокере, система не смогла бы масштабироваться.
Поэтому каждый топик разбивается на партиции (partitions). Партиция — это физический каталог с лог-файлами на жестком диске конкретного брокера. Именно партиция является минимальной единицей параллелизма в системе.
| Характеристика | Топик | Партиция | | --- | --- | --- | | Сущность | Логическая (категория/имя) | Физическая (файл на диске) | | Расположение | Распределен по всему кластеру | Находится на конкретном брокере | | Масштабирование | Не ограничено | Ограничено ресурсами одного сервера | | Гарантия порядка | Отсутствует | Строгая (сообщения упорядочены) |
Когда Go-приложение отправляет сообщение, оно должно решить, в какую партицию его положить. Если у сообщения нет ключа, используется алгоритм Round-Robin (по кругу). Если ключ есть (например, ID пользователя), применяется хеширование.
Математически выбор партиции описывается формулой:
Где — итоговый номер партиции, — ключ сообщения, — функция хеширования (обычно murmur2), а — общее количество партиций в топике.
Представим топик user-events с 4 партициями. Если мы отправляем события для пользователя с ID=42, хеш от числа 42 всегда будет давать один и тот же результат. Допустим, . Тогда . Все события этого пользователя гарантированно попадут в партицию №1 и будут обработаны строго последовательно.
Репликация и отказоустойчивость
В распределенных системах серверы неизбежно выходят из строя. Чтобы не потерять данные при сгорании жесткого диска, применяется репликация (replication). Каждая партиция имеет одного лидера (Leader) и несколько ведомых копий (Followers).
Все операции записи и чтения всегда идут только через лидера. Ведомые реплики просто копируют данные к себе в фоновом режиме. Те реплики, которые успевают за лидером и не отстают, образуют группу ISR (In-Sync Replicas).
Для расчета отказоустойчивости используется простая формула:
Где — количество брокеров, потерю которых кластер может пережить без потери данных, а — фактор репликации. Если фактор репликации равен 3, кластер продолжит работу даже при одновременном падении 2 серверов ().
В коде выше параметр acks="all" означает, что лидер ответит Go-приложению об успешной записи только после того, как все реплики из списка ISR сохранят сообщение на свои диски. Это снижает скорость, но гарантирует максимальную надежность.
Политика удержания (Retention Policy)
Классические очереди (например, RabbitMQ) удаляют сообщение сразу после того, как потребитель его прочитал. Здесь подход принципиально иной. Сообщения хранятся на диске независимо от того, прочитали их или нет. За очистку старых данных отвечает политика удержания (retention policy).
Существует два основных триггера для удаления старых данных:
retention.ms): например, хранить логи ровно 7 дней.retention.bytes): например, партиция не должна превышать 50 ГБ. Как только лимит превышен, самые старые сегменты файла удаляются.На собеседованиях часто спрашивают про альтернативный механизм — Log Compaction (сжатие лога). При его включении система хранит не все события за период времени, а только последнее актуальное состояние для каждого уникального ключа.
Например, если в топик балансов пользователей пришло три сообщения для ключа user_123: со значениями 100 руб., 150 руб. и 50 руб., то после сжатия на диске останется только последнее сообщение (50 руб.). Это идеальный паттерн для восстановления состояния in-memory кэшей в микросервисах после их перезапуска.
Понимание того, как брокеры распределяют партиции, как работает хеширование ключей и как настраивается репликация, является фундаментом. Без этих знаний невозможно правильно спроектировать архитектуру приложения, которое должно обрабатывать миллионы событий без сбоев и потерь.