Как добиться сохранения последовательности сообщений по одному документу в одной партиции Kafka
JavaKafkaпартициипоследовательность сообщений
Что проверяют
Понимаете ли вы, что порядок обеспечивается ключом, и знаете ли настройки, которые могут его нарушить даже при правильном ключе.
Как отвечать
Основное: ключом сообщения ставится идентификатор документа. Партиция выбирается по хешу ключа, значит все события одного документа попадают в одну партицию, а внутри неё порядок гарантирован.
producer.send(new ProducerRecord<>("documents", documentId, event));Но одного ключа мало, и вот что ещё нужно назвать:
- повторы могут переставить сообщения: если разрешено несколько неподтверждённых запросов в полёте и включены повторы, второе сообщение может обогнать первое. Лечится включением идемпотентного продюсера (
enable.idempotence=true), который сохраняет порядок и при повторах, либо ограничением числа запросов в полёте до одного; - число партиций менять опасно: при увеличении меняется соответствие ключей партициям, и события существующего документа начнут попадать в другую партицию, пока старые ещё лежат в прежней. Порядок на границе изменения нарушится;
- параллельная обработка у потребителя тоже ломает порядок: если из партиции читают в пул потоков, сообщения обработаются вперемешку. Тогда параллелят по ключу, а не по сообщениям;
- перебалансировка: при смене владельца партиции обработка приостанавливается, но порядок сохраняется, потому что чтение продолжается с зафиксированного смещения;
- свой разделитель нужен редко, но возможен, например когда хочется дробить горячий ключ на несколько партиций, и тогда порядок сохраняется уже не по документу.
Где спотыкаются
Ставят ключом случайное значение или оставляют его пустым и ждут порядка.
Включают повторы без идемпотентности.
Распараллеливают обработку внутри потребителя и теряют порядок, который бережно обеспечили на стороне отправителя.