Раздел 26 · Data Engineering

Ключ партиционирования и порядок внутри партиции

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке мы разрезали топик на партиции, и консьюмеры поделили работу. Но у этого есть цена. Отто открыл табло и увидел заказ, который сначала доставили, а потом создали. Курьер не путешествовал во времени: просто статусы одного заказа попали в разные партиции. Разберёмся, как это предотвратить.

Почтовые ящики по фамилиям

В большом доме почту раскладывают по ящикам с буквами: А-Ж, З-О, П-Я. Все письма Иванову ложатся в ящик З-О в том порядке, в каком их принёс почтальон. Сколько бы писем ни пришло, Иванов прочтёт их по порядку: они в одном ящике.

Письма Иванову и Петрову лежат в разных ящиках. Какое из них пришло раньше, по ящикам уже не понять, но обычно это и не нужно.

А теперь в доме повесили четвёртый ящик и переделили алфавит. Иванов теперь получает почту в другой ящик. Старые письма лежат в старом, новые в новом, и если сначала открыть новый ящик, вчерашнее письмо прочтётся после сегодняшнего.

В Kafka ящики это партиции, а фамилия это ключ.

Порядок есть только внутри партиции

Kafka обещает одно: записи одной партиции читаются в том порядке, в каком их записали. Между разными партициями порядка нет. Консьюмер читает их параллельно или по очереди, как ему удобно, и запись из партиции 1 может обработаться раньше записи из партиции 0, хотя её отправили позже.

Чтобы события одного заказа шли по порядку, они должны лежать в одной партиции. Решает это ключ.

Ключ решает, куда ляжет запись

У каждого сообщения может быть ключ. Продюсер считает от ключа хеш и берёт остаток от деления на число партиций:

партиция = хеш(ключ) mod число_партиций

Эту работу делает партиционер продюсера. Одинаковый ключ даёт одинаковый хеш, значит, одну и ту же партицию. Ключом статусов заказа берут номер заказа: все статусы order-7 попадут в одну партицию и прочтутся по порядку.

А если ключа нет? Тогда партиционер раскладывает записи сам. С Kafka 2.4 он «липкий», а с 3.3 ещё и равномерный: копит записи без ключа в одной партиции, пока не наберёт пачку размером batch.size, а потом переходит к другой. Поэтому в маленькой песочнице записи без ключа часто оказываются в одной партиции. Это совпадение, а не обещание: на настоящем потоке соседние события одного заказа разъедутся по разным партициям.

урок из курса

Урок из курса «Data Engineering». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.