Ответ
Kafka гарантирует строгий порядок сообщений только в пределах одной партиции (partition).
Каждое сообщение в партиции получает уникальный, монотонно возрастающий порядковый номер — offset. Консьюмеры читают сообщения из партиции последовательно в соответствии с этим offset.
Порядок между разными партициями одного топика не гарантируется. Это фундаментальный компромисс, который позволяет Kafka достигать высокой пропускной способности и масштабируемости за счет параллельной обработки партиций.
Пример на Python (kafka-python):
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers='localhost:9092')
# Сообщения с одинаковым ключом попадут в одну и ту же партицию,
# их порядок будет сохранен.
producer.send('my-topic', key=b'user-123', value=b'event-1')
producer.send('my-topic', key=b'user-123', value=b'event-2')
# Сообщения с разными ключами могут попасть в разные партиции,
# порядок между ними не гарантирован.
producer.send('my-topic', key=b'order-abc', value=b'created')
producer.send('my-topic', key=b'order-xyz', value=b'shipped')
producer.flush()
Как обеспечить строгий порядок?
- Использовать один и тот же ключ (
key) для всех сообщений, которые должны быть обработаны последовательно. Kafka по умолчанию использует хэш ключа для определения партиции, поэтому сообщения с одинаковым ключом всегда попадают в одну и ту же партицию. - Использовать топик с одной партицией. Это гарантирует глобальный порядок для всех сообщений в топике, но полностью устраняет возможность параллельной обработки и становится узким местом системы.
Ответ 18+ 🔞
Ага, слушай, щас объясню про порядок в Кафке, как есть, без прикрас. Представь себе, что партиция — это такая очередь, как в совковом магазине за колбасой, блядь. Внутри одной очереди — всё чётко: кто встал первым, тот первый и получит свою докторскую, и номерок ему дадут, этот самый offset. Монотонно возрастающий, ёпта! То есть второй за первым, третий за вторым — идиллия, пиздец.
А теперь смотри сюда, умник. Ты же не один магазин, ты сеть, сука, «Колбасы №1», «Колбасы №2» и так далее. Это и есть разные партиции. И вот в первой очереди мужик уже сало получил, а во второй бабка ещё только справку на скидку ищет. Порядка МЕЖДУ очередями — НИХУЯ! Кто быстрее кассиршу обработает, тот и молодец. Это и есть тот самый фундаментальный компромисс, на котором всё и держится: скорость и масштабируемость в обмен на глобальный порядок. Хочешь быстро всех обслужит — делай много касс, но тогда не возмущайся, что кто-то с десятой кассы ушёл раньше, чем ты со второй.
Вот, глянь на код, тут всё наглядно:
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers='localhost:9092')
# Вот эти два сообщения — как два чела с одним ключом 'user-123'.
# Они оба пойдут в одну и ту же очередь-партицию, и event-2 всегда будет после event-1.
# Порядок гарантирован, как моё слово, блядь.
producer.send('my-topic', key=b'user-123', value=b'event-1')
producer.send('my-topic', key=b'user-123', value=b'event-2')
# А вот эти — с разными ключами. Их швырнёт в разные партиции, как охуевших.
# Может, 'created' улетит в партицию 5, а 'shipped' — в партицию 9.
# И кто из них на выходе раньше окажется — хуй его знает! Порядка нет.
producer.send('my-topic', key=b'order-abc', value=b'created')
producer.send('my-topic', key=b'order-xyz', value=b'shipped')
producer.flush()
Ну и как тогда, блядь, порядок навести?
- Ключ — твой царь и бог. Всё, что должно идти строго друг за другом (все события по одному юзеру, по одному заказу), — пихай с одинаковым ключом. Кафка по хэшу ключа определит одну и ту же партицию, и там уж порядок будет железный. Это как если бы ты всем своим родственникам дал один номерок на всю семью — стояли бы кучкой.
- Сделать одну партицию на весь топик. Это вариант для максималистов, блядь. Да, тогда ВСЕ сообщения будут в одной очереди, и глобальный порядок наступит. Но это же пиздец, а не производительность! Это как весь город послать в один магазин за той самой колбасой. Очередь до Луны, скорость — ноль ебать. Узкое место системы, одним словом. На такое решаются только в очень особых, извращённых случаях.
Вот так вот, ебанашка. Выбирай: либо скорость и масштаб, но без глобального порядка, либо порядок, но в одном потоке, как последний олдскульный перфекционист.