В настоящее время я пытаюсь разработать масштабируемую потребительскую архитектуру для kafka, и у меня возникают некоторые проблемы с координацией смещения. Для моего варианта использования важно, чтобы каждое сообщение, потребляемое kafka, обрабатывалось ровно один раз.
Для иллюстрации проблемы возьмем следующее:
- Потребитель получает сообщение от Kafka
- Сообщение о потребительских процессах (бизнес-логика, ура!)
- Потребитель завершает обработку, увеличивает локальное смещение
- Потребитель пытается передать компенсацию обратно в kafka
- Этот сетевой вызов завершился неудачно по X причине
- Вышеупомянутая ошибка или что-то еще вызывает сбой потребителя до того, как можно будет повторить фиксацию смещения.
- Системный оркестратор вызывает другого потребителя, который затем извлекает устаревшее смещение.
- То же сообщение извлекается и повторно обрабатывается (плохо!)
Те, у кого больше опыта в работе с распределенными системами, чем я, вы, вероятно, осознали, что это (более или менее) проблема двух генералов, применяемая к координации смещения / результатов работы Kafka.
Я думал о фиксации смещения и результат работы в транзакции (возможно, SQL) db, но это связывает эти реализации вместе, а также ограничивает мои параметры хранилища данных (а также, что мне делать, если я перемещаю свое хранилище данных во что-то без транзакций ?). Другое возможное решение - хеширование каждого сообщения и использование фильтров Блума для вероятностного предотвращения дублирования обработки, но теперь мы начинаем добавлять сложность, которой я бы предпочел избежать.