Как стать автором
Обновить

Комментарии 7

НЛО прилетело и опубликовало эту надпись здесь
Скажите, пожалуйста, как реализация механизма exactly-once в Kafka обходит задачу двух генералов ( https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%B4%D0%B2%D1%83%D1%85_%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D0%BB%D0%BE%D0%B2 ), которая неизбежно возникнет, если, например, ненадежна сеть? Или накладываются дополнительные требования к системе?

Как Kafka различит ситуации, что клиент умер до обработки сообщения и сообщение нужно переотправить и ситуацию, когда клиент обработал сообщение и умер в момент отправки подтверждения обработки, следовательно сообщение переотправлять нельзя? В обоих случаях Kafka уведомления не получает, но в одном случае для гарантии exactly-once сообщение необходимо отправить повторно, а в другом нет.
не уверен что понял вопрос точно
В кафке есть 2 типа «клиентов» — producer (кто сохраняет события в кафку) и consumer (потребляет события)
Механизм exactly-once — он только для producer-ов, то есть если producer по какой-то причине не уверен, сохранилось ли сообщение в кафку (например разрыв соединения), он просто перепошлёт сообщение в кафку с тем же ID и механизм exactly-once гарантирует, что event не будет продублирован

Полагаю что вопрос всё же был про consumer-ов.
Здесь кафка не даёт гарантий exactly-once и consumer должен сам позаботиться чтобы не обработать одну и ту же запись несколько раз. Для этого можно использовать offset, который есть у каждого event-а и который монотонно растёт. То есть клиент может у себя в хранилище сохранять последний обработанный offset и по нему фильтровать дубли
Вопрос Вы поняли правильно.

> он просто перепошлёт сообщение в кафку с тем же ID и механизм exactly-once гарантирует, что event не будет продублирован.
А тогда понятно. exactly-once получается не сквозной на стыке producer-кафка, а только для кафки, которая всего лишь будет игнорировать дубли по ID за счет какой-либо внутренней «базы» прошедших ID.

С точки зрения producerа получается никакого exactly-once нет, так как он может перепосылать сообщения, которые далее будут отбрасываться, как дубли и в худшем случае будет делать это до бесконечности, так как гарантировано узнать факт доставки он не может.

> Полагаю что вопрос всё же был про consumer-ов.
> Здесь кафка не даёт гарантий exactly-once
Это логично, так как эта гарантия теоретически невозможна в распределенной системе.

Однако, тогда получается, что в статье есть одно обобщение, которое приводит к неправильному ее пониманию:
> Семантика exactly once («строго однократная доставка»).
> Даже при повторной попытке продюсера отправить сообщение, сообщение доставляется строго один раз.

Не указано, что есть доставка и кому оно доставляется. Скорее это утверждение понимается, как доставка конечному потребителю (consumerу) от источника (producerа), так как кафка и ее абстракции это по сути промежуточный буфер, а не часть бизнес логики и не цель доставки/обработки сообщений.
На самом же деле под доставкой понимается только доставка до кафки от источника, что совсем не одно и тоже и что гораздо более слабая гарантия, чем кажется на первый взгляд.
По-моему непонимание происходит из-за того, что вы воспринимаете кафку как очередную message queue.
В обычных message queue producer кидает событие в очередь, consumer (обычно один) получает это сообщение из очереди и выполняет свою работу и если всё ok, отвечает очереди что сообщение обработано (если это at-least-once) и это сообщение удаляется из очереди.

Кафка может быть использована как очередь сообщений, но в целом это более универсальная штука — распределённый лог событий. Producer добавляют в лог событие. Если кафка отвечает ему ok, это значит что она получила это событие и сохранила его на диск в указанный topic. Всё! Это сообщение больше не потеряется, кафка сохранила его на диск, producer может на этом успокоиться и больше не посылать это сообщение в кафку.

Далее в ход идут consumers. Одно сообщение в кафке может быть обработано несколькими разными consumer-ами.
То есть например юзер оплатил товар, система сохранила в кафку в topic ORDERS, что такой-то юзер оплатил такой-то товар, который надо доставить по такому-то адресу. Один consumer занимается тем что формирует заявку для склада, другой — добавляет это событие в финансовые отчёты, третий — сохраняет это событие в систему бизнес-аналитики. 3 разных консумера обрабатывают одно и то же событие. И после того как они обработают его, событие из кафки никуда не удаляется, оно там остаётся в течение какого-то времени (день, неделя, месяц — как настроите).

Если в одном из консумеров нашёлся баг, можно исправить баг и перезапустить консумера по всем данным которые есть в topic ORDERS — например перезалить данные в систему бизнес-аналитики.

В такой системе producer вообще не знает, обработано ли его сообщение, потому что он не знает, сколько consumer-ов его обработают и когда они должны его обработать.

Семантика exactly-once на стороне producer-а решает немного другую проблему.
В предыдущем комменте я писал:
consumer должен сам позаботиться чтобы не обработать одну и ту же запись несколько раз. Для этого можно использовать offset, который есть у каждого event-а и который монотонно растёт. То есть клиент может у себя в хранилище сохранять последний обработанный offset и по нему фильтровать дубли

эта штука работает нормально только если в самой кафке нет дублей. То есть в старых версиях могла быть ситуация, когда producer мог сохранить одно и то же сообщение в кафке дважды. В этом случае у этих 2-х сообщений будут разные offset-ы и эта схема дедупликации не сработает (можно делать дедупликацию вручную, зная какие данные у тебя в событии, но тогда для каждого события должен быть свой код для дедупликации)
Спасибо за развернутый ответ!

> По-моему непонимание происходит из-за того, что вы воспринимаете кафку как очередную message queue.
Не совсем.
На самом деле не обязательно рассматривать сквозную гарантию уровня producer-consumer, чтобы увидеть двойственность возможной трактовки.

Даже если рассмотреть связку producer-кафка отдельно, то возникает двоякая трактовка смысла exactly-once.
Первую описали Вы, а вторая возможная — это сквозной exactly-once для связки producer-кафка. Когда, если producer что-то отправил, то он либо данные у себя удаляет без риска потери, либо перепосылает их пока данные не придут в кафку, но в обоих случая данные приходят в кафку только один раз и producer не тратит лишние ресурсы на хранение у себя тех данных, которые отправлены, успешно доставлены, но подтверждение доставки от которых затерялось. С точки зрения кафки в этом случае exactly-once тоже соблюдается неотличимо от первой трактовки.

А ресурсы для хранения повторно пересылаемых данных на практике могут требоваться значительные и таких лишних ресурсов может просто не быть, а единственным решением проблемы отсутствия такой сквозной гарантии уровня producer-кафка будет ответ от аналитиков, как менее болезненно для целей всей задачи терять сообщения producerа.
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий