Перейти к содержанию

Kafka transactions и idempotent producers

Глубокие темы · Раздел03

Тип материала: архитектурный разбор. Схемы и примеры иллюстративные, если не указано иное.

Версии в источниках: Kafka/Connect/Streams 4.1, Debezium 3.3, Flink 1.20.3, Spark 4.0.1 и Airflow 3.1 либо явно названная система. Непроверенные вопросы и ограничения runtime — в журнале (архив рабочего проекта).

Механизм

Idempotence подавляет protocol retry duplicates с producer ID/epoch/sequence. Kafka transaction связывает writes нескольких partitions/topics и поддерживаемые group offsets. Это разные уровни: idempotence не dedup business ID, transaction не включает произвольную внешнюю БД.

flowchart TB
  Input[Kafka records] --> Begin[Begin transaction]
  Begin --> Output[Produce Kafka output]
  Output --> Offsets[Add input group offsets]
  Offsets --> Commit[Commit or abort]
  Commit --> Visible[read_committed visibility]
  Output -. outside boundary .-> HTTP[External HTTP effect]

Пошаговое объяснение

init_transactions получает transactional identity и fencing → begin_transaction → produce derived records → send_offsets_to_transaction с group metadata → commit_transaction. Downstream read_committed читает committed records. При abort input offsets не продвигаются как successful transaction, data не публикуется как committed.

Failure scenarios и recovery

Crash/timeout после commit request даёт неопределённость клиента; library error flags определяют retry/abort/fatal actions. Новый active producer с тем же transactional.id fence старый. Разные независимые writers не должны случайно делить этот ID; recovery одного logical writer требует стабильной identity.

Trade-offs и эксплуатация

Transactions добавляют coordinator state, markers, timeout/fencing и задержку visibility. Длительная open transaction удерживает stable visibility. Exactly-once Kafka pipeline не предотвращает repeated HTTP charge, исполненный до abort; outbox/idempotent endpoint решают иной boundary.

Практический пример

Python producer показывает basic/idempotent/transactional modes. Специально повторённая строка input остаётся новым business send, даже при enable.idempotence=true.

Типичные ошибки проектирования

Смешивать source/state/sink boundaries, скрывать failed records и неопределённый исход timeout; применять retry без identity/version и retention contract. Конкретные ограничения разобраны выше.

Вопросы на собеседовании

acks=all равно transaction? Нет, acknowledgement durability и atomic group publication различаются.

Почему aborted SQL effect не исчез? SQL не участвовал в Kafka transaction.

Практические упражнения

Составьте matrix commit/abort/fenced/unknown response. Для каждого опишите безопасное действие клиента без выдуманного глобального EOS.

Дополнительные источники