На пальцах, что происходит во время работы с транзакциями:
- транзакции существуют только в воображении потребителя. Поставщики пишут в партицию метки "транзакцию начал / закончил".
- для каждого сообщения в отдельности выяснить его транзакционный статус нельзя - он определяется предыдущими / последующими метками, записываемыми в ту же последовательность
- потребитель читает последовательность и фильтрует не подтвержденные сообщения. При этом гарантируется, что сообщения будут прочитаны в том же порядке, что и отправлялись
Из этого происходят многочисленные забавные эффекты
- Cлужебные метки потребляют смещения. Прочитать сообщения по ним нельзя - там нет сообщений, просто технические метки. Поэтому в последовательности вычитываемых сообщений наблюдаются дырки в смещениях. А Grafana начинает по всем партициям показывать lag минимум в одно значение.
- допустим сервис А read_committed и читает транзакционные сообщения сервиса Б. Если сервис Б сломался и начинает откатывать свои сообщения, то сервису А действительно читать нечего. Но сообщения в партиции есть (вместе с метками, кстати), они потребляют смещения. Поэтому через некоторе время прибегают админы с воплями "Ааааааааааааа! сервис А перестал потреблять сообщения, видите на графике Grafana нарисовался gap длинной много тысяч долларов, почините его срочно". Так вот, с сервисом А все нормально, а вот у нас с вами большая головная боль, так как Grafana в принципе не способна различить плохие и хорошие gap-ы, то есть происходящие от непотребленных сообщений и сообщений, которые действительно не должны быть потреблены
- если сервис начал транзакцию и записал метку, то потребитель ждет, пока не появится вторая метка о закреплении / откате транзакции. Во-первых, только вторая метка предоставит ему необходимую для продолжения информацию. Во-вторых, сообщения должны быть потреблены в порядке поступления. В документации читаем: "Further, the consumer does not need to any buffering to wait for transactions to complete. Instead, the broker does not allow it to advance to offsets which include open transactions." Соответственно, если один из сервисов начал транзакцию и завис / тормозит, то как минимум одна партиция будет блокирована и потребитель будет ждать окончания транзакции, чтобы продвинуться дальше. Опять-таки имеем gap и никаких инструментов понять, что же собственно происходит. Если тормозящий сервис в процесс транзакции обычно высылает множество сообщений, то у него есть шанс заблокировать топик целиком. Для топиков, в которые одновременно пишут много сервисов это достаточно серьезная потенциальная проблема.
Мораль: Кафка не для enterprise систем, она для больших стабильных потоков нетразакционных данных, часть которых в случае чего не будет больно потерять. Например, технологические логи или информация о поведении пользователей.
В смысле Event Driven Architecture наше все это по-прежнему JMS, ну или на худой конец (если ваши продажники сначала продают модные решения, а потом уже думают) CDC решения типа Debezium.