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

Используете Kafka с микросервисами? Скорее всего, вы неправильно обрабатываете повторные передачи

Время на прочтение16 мин
Количество просмотров17K
Всего голосов 18: ↑18 и ↓0+18
Комментарии17

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

Пойду-ка я обратно монолиты писать, извините.

Справедливости ради, там тоже встречаются те же самые проблемы, просто намного реже.

В монолитах есть готовые инструменты согласованности предоставляемые другими системами — реляционными СУБД. Навешал разных констрейнтов на данные и сиди довольный. А в микросервисах — только свои велосипеды.

Это только пока СУБД одна работает. И то не всегда, не любой инвараинт может быть выражен констрейнтом...


Кроме того, обсуждаемая проблема вообще не является проблемой, которую могут решить констрейнты.

НЛО прилетело и опубликовало эту надпись здесь

Идемпотентность, увы, не помогает против нарушения порядка сообщений.

НЛО прилетело и опубликовало эту надпись здесь
Возможно я не знаю какого-то красивого решения. Подскажите, пожалуйста, как сделать идемпотентным пример из статьи с сообщением о переименовании пользователя? Чтобы несколько таких сообщений перемешанных и повторённых давали правильный результат.

А обработка этого сообщения уже идемпотентная. Только не вполне понятно зачем об этом говорить.

НЛО прилетело и опубликовало эту надпись здесь
Например указывать версию, к которой применяется изменение. Либо полностью, либо номер (поколение), чтобы разрулить конфликты. Тогда при перемешивании и частичном применении можно отбросить транзакции, у которых версия ниже текущей. А вообще, такие вещи надо убивать на корню. СУБД создана, чтобы разруливать такие конфликты.
НЛО прилетело и опубликовало эту надпись здесь
Делал недавно, вариант с kafka exactly-once

Но у меня не завелось Timeout expired after 60000milliseconds while awaiting InitProducerId. Так не разобрался в чем причина. Без транзакций отправка работает, в итоге сделал отслеживание повторных передач через БД.
Неоднозначное решение, на мой взгляд.

Во-первых совершенно не факт, что надо вообще хранить данные для повтора в самой кафке и тем более в виде исходного сообщения, которое мы не смогли обработать, но почему-то решили, что сможем правильно скопировать. Да, можно сказать, что вдруг БД недоступна, но тогда не надо уходить на повторы, надо просто вызывать инженеров и чинить БД.

Во-вторых часто публикуется «полное» идемпотентное событие, таким образом когда мы обработали сообщение Zoiee, то обрабатывать Zoё уже просто не нужно.

Как альтернативное решение:
1. Проблемные события сохраняем в спец-таблицу БД как ID + партишен + оффсет
2. Удаляем из неё старое сообщение, как пришло новое сообщение с тем же ID

Бонусы:
— Размер таблицы есть метрика рассинхронизации состояний, по ней можно настроить алерты
— Не уложняем картину в кафке, в которой не всегда можно красиво разделить доступ
— Можно запускать вручную повторные попытки потребления отдельных сообщений
— Можно устроить сколь угодно сложную логику повторных попыток
Retry topic: популярное ходовое решение

Это годится, если трафик небольшой. Но вообще делать подобное на кафке это злое зло. Кафка это не брокер сообщений. Приходящие в топик сообщения из него не исчезают после прочтения, а живут там, пока их не прибьет политика по подчистке старых сообщений, которой будет пофиг, читал эти сообщения кто-то или нет. Если трафик большой, то мало того, что весь этот дополнительный поток сожрет дополнительные ресурсы у кафки (а переваривает она не так чтобы много топиков и партишенов). Так он еще будет забивать диски кучей дубликатов. Все эти разные retry топики будут хранить копии одних и тех же сообщений.

Если уж так хочется, то лучше эти повторы хранить где-то в другом месте, которое имеет необходимую семантику. Тот же полноценный брокер сообщений. Да или хоть редис банальный.
ИМХО, если retry topic начинает забивать диски, то проблема забитых дисков это меньшая из проблем в построенной системе.

PS: А какие проблемы с перевариванием топиков и партишенов в кафке? Вроде это одна из самых масштабируемых систем потоковой обработки данных.

Спасибо за статью. Сам испытываю проблемы с обработкой ошибочных сообщений из кафки, хотел прикрутить retry topic. У меня ситуация немного другая — кафка используется для асинхронного request-reply, т.е. есть, куда ответить об ошибке. Но с "плохими" сообщениями это дела не меняет.


Описанный подход выглядит логичным решением проблемы, разве что нужен механизм повторной публикации сообщений из отстойника.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий