Kafka: высокопроизводительный распределенный стриминг
Apache Kafka — это распределенное хранилище событий и платформа для потоковой обработки данных. Она разработана для обработки огромных объемов данных в реальном времени с низкой задержкой и высоко й пропускной способностью.
1. Основные концепции и EOS
Семантика Exactly-Once (EOS)
Kafka обеспечивает семантику «ровно один раз» (exactly-once) с помощью:
- Идемпотентные продюсеры: Гарантируют, что повторные попытки отправки не приведут к дублированию сообщений за счет присвоения порядкового номера каждому сообщению.
- Транзакции: Позволяют объединять несколько операций Kafka (в разных разделах/топиках) в единую атомарную единицу.
- Управление смещениями (offsets): При использовании Kafka Streams или транзакционных потребителей смещения фиксируются атомарно вместе с результатами обработки.
Проблемы:
- Требуется идемпотентность на стороне потребителя (обрабо тка одного и того же сообщения дважды, если фиксация смещения не удалась).
- Продюсеры должны включить
acks=allиenable.idempotence=true. - Увеличение задержки из-за накладных расходов на транзакционные записи и координацию.
2. High-Water Mark (HW)
- High-Water Mark (HW) — это последнее смещение, которое считается «зафиксированным» (committed) и может быть прочитано потребителями.
- Это обеспечивает согласованность: потребители не могут читать незафиксированные данные, которые могут исчезнуть в случае сбоя лидера.
- Если реплика-последователь (follower) отстает от HW, она не может быть выбрана лидером до тех пор, пока не догонит его.
3. Сбой лидера и сообщения в полете
- Kafka и спользует ZooKeeper или KRaft для выбора нового лидера из In-Sync Replicas (ISR).
- In-flight сообщения (с
acks=1илиacks=0) могут быть потеряны, если они не были реплицированы на последователя до падения лидера. - С
acks=allсообщение считается успешно отправленным только если оно было реплицировано на все ISR. - Крайний случай: Если нет доступных ISR, Kafka может приостановить запись, чтобы предотвратить потерю данных (в зависимости от настройки
min.insync.replicas).
4. Log Compaction vs. Retention
- Log Compaction (Уплотнение логов): Сохраняет как минимум последнюю версию для каждого ключа. Старые версии удаляются в процессе уплотнения. Полезно для хранения текущего состояния (changelogs).
- Retention Policies (Политики удержания): Удаляют сообщения на основе времени (
log.retention.ms) или общего размера (log.retention.bytes), независимо от ключа. - Сложный случай: Если потребитель был отключен дольше периода удержания, он может пропустить исторические обновления или изменения состояния.
5. Нечистый выбор лидера (Unclean Leader Election)
- Когда
unclean.leader.election.enable=true, последователь, не находящийся в синхронизации (не в ISR), может стать лидером. - Опасность: Это может привести к потере данных и несогласованности, так как новый лидер может не иметь всех зафиксированных сообщений от предыдущего лидера.
- В продакшене это значение обычно должно быть
false, если только доступность не важнее согласованности.