транзакция в БД прошла, в запись в кафку упала с ошибкой? (о чем Гари и пишет)
идемпотентно значит сколько раз ни вызывай, результат не изменится если процессинг будет идемпотентный, то неважно что с кафкой. но смысл именно в этом logic + write in db - вот тут нужна идемпотентность
Если на кухню несколько раз придёт указание "Сегодня готовим два шоколадных торта", то в любом случае будет приготовлено именно два торта. Если несколько раз придёт указание "Нужно приготовить ещё два торта", то количество приготовленных тортов будет разным. Первое - идемпотентно, второе - нет.
мой вопрос был, потому что по ссылке сказано: > There is no such thing as an idempotent (exactly once) consumer with Kafka. поэтому и хочется понять, какую проблему мы решаем
Сначала делать запись в кафку, а потом в БД. Если упадет, то в БД ничего не будет, а кафка дубли сама может разрулить, у нее же есть идемпотентность на уровне продюсера. Но это, конечно, не exactly-once.
в этом случае мы запишем данные в кафку 2 раза, так как с точки зрения кафки это были успешные записи
Посмотрите в сторону KafkaConnect
Если это будет в kafka-транзакции, то нет, идемпотентность на уровне продьюсера в кафка есть by default. Просто на уровне консьюмера нужно будет выстраивать ее ручками самому(Так как там не понятно, как ее реализовывать на уровне протокола, так как exactly-once теоритически не решенная задача). P.S. Об это Гари же и пишет.
телеграм мне почему-то не показывает твоё сообщение, на которое я отвечал. Мы сейчас все еще говорим о сценарии, когда мы прочитали сообщение из кафки, и потом хотим записать его одновременно в бд и в кафку? ты сказал что в этом случае можно писать сначала в кафку, а потом в бд, так? и в случае если сообщение не будет записано в БД, у нас все равно в топике окажется только 1 сообщение, даже после повторения процессинга? если я верно понял идею, можно попросить тебя показать кусок кода, как это должно работать?
Случайно удалил его, хотел подредачить. Ты имеешь в виду, что при полном ретрае будет новый PID и для кафки это будет уже новое сообщение? Ну тут да, хотя я бы глянул как в spring-kafka генерируется новый PID для сообщения, но в случае полного ретрая это не важно, да, был не прав, не углубился в вопрос.
"PID для сообщения" - речь идет про sequence number для сообщения? мое ожидание - это будет другое число, чем первое сообщение, так как первое мы успешно отправили уже к этому моменту (перед тем как неуспешно попытались записать данные в БД)
Да, видимо так, с учетом, что идемпотентность дефолтно включена, то я думаю, что это чисто техническое решение для ретраев ack, для бизнес-логики придется выстраивать идемпотентность самому.
Делать компенсирующую операцию в бд - есть шанс успеть. Но только шанс: если выключат свет между коммитом в бд и коммитом в кафку - получится неконсистентное состояние, с которым можно только смириться. К сожалению, объединить транзакции кафки и БД не получится, хотя в примерах spring-kafka есть такой. Поэтому если нужна строгая exactly once, то лучше подумать дважды об использовании внешних ресурсов и их ограничениях.
Я правильно понял, что idempotency продюсер нужен только для ретраев, когда мы не получили подтверждение, я глянул на исходники стандартного клиента и там TransactionManager, если он используется только для идемпотентности, при ретрае, когда не получили acknowledge, он оставляет в in flight батч только одно сообщение, чтоб гарантировать порядок, а брокер, я так понимаю, фильтрует дубли, но для ретраев в спринг кафка это работать не будет, так как там ретрай - это новый процессинг? И транзакциями тоже не получится это сделать? Я так понял, они нужны только, чтоб отправлять в несколько топиков транзакционно, но если есть что-то кроме кафки, то нужно самому делать идемпотентность?
> Я правильно понял, что idempotency продюсер нужен только для ретраев, когда мы не получили подтверждение ага > но для ретраев в спринг кафка это работать не будет, так как там ретрай - это новый процессинг? про детали спринга не в курсе > но если есть что-то кроме кафки, то нужно самому делать идемпотентность? ага. Тут наверное несколько опций есть. 1. Например, если БД умная, у нее есть Change feed API, можно его слушать и в кафку писатЬ 2. Если бд не такая умная, то часто есть возможность просто WAL читать, или быть "репликой", и на основе этого в кафку писать (например, mysql/pg) 3. можно поллить БД и писать в кафку от туда, но тут надо смотреть на сколько это дорога операция, и как много данных 4. ну или тот вариант, что Гари на SO описывал
Спасибо. А еще не могли бы подсказать, я правильно понимаю, что если я хочу гарантировать порядок при отправки сообщений батчами(условно, по 5 сообщений за раз), то мне нужно уже использовать транзакции? Так как идемпотентный продюсер в этом случае не спасет, если в середине будет сообщение, которое упадет при отправке, то будет нарушен порядок
Насколько мне известно - кафка сама по себе асинхронна и пытаться сделать из нее синхронное не очень хорошее решение. Но как я видел есть два варианта «обеспечения» ордеринга: 1. Идемпотентность тру, макс ин флай реквест 1 2. Идемпотентность тру, макс ин флай меньше 5, ретраи больше 0, акновледж олл
Продюсер асинхронный только потому что он возвращает фьючу? На ней же можно заблокироваться, если мне нужна гарантия доставки. Но мой вопрос в том, что если мне нужно соблюдать порядок, то я пишу в одну партицию, но если я пишу батчами, то тут, такое чувство, что без транзакций не обойтись, так как идемпотентный продюсер здесь не поможет(так как у него идемпотентность работает в рамках одного сообщения)
Можно конечно, но мой спич о том, что мы берем асинхрон и делаем из него синхрон *насчет ордера, что знал - накинул
Мне кажется, что продюсер кафки сложно назвать полностью асинхронным с учетом, что там даже fire-and-forget нет
При отправке пачки связанных сообщений транзакции обязательны. При этом надо убедиться что у консюмеров стоит настройка isolation.level=read_commited (по умолчанию read_uncommited). Иначе даже при откате транзакции консумеры вычитают сообщения
Обсуждают сегодня