Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Партиции Kafka: распределение сообщений

Партиции Kafka: порядок, ключ и параллелизм

Партиции топика Kafka: гарантия порядка внутри партиции, выбор партиции по ключу, влияние числа партиций на параллелизм и перебалансировка.

Прямой ответ

Топик Kafka делится на партиции — упорядоченные журналы, в которые сообщения дописываются в конец. Порядок гарантируется внутри партиции, а не для топика в целом.

Топик orders
├── партиция 0: [o1, o4, o7, ...]
├── партиция 1: [o2, o5, o8, ...]
└── партиция 2: [o3, o6, o9, ...]

Выбор партиции определяется ключом сообщения:

producer.send("orders", key=order_id.encode(), value=payload)

Сообщения с одинаковым ключом попадают в одну партицию, поэтому события одного заказа обрабатываются последовательно. Сообщение без ключа распределяется по партициям для равномерности, и порядок между такими сообщениями не определён.

Способ отправки Партиция Порядок
С ключом Одна и та же для ключа Гарантирован для ключа
Без ключа Распределяется продюсером Не гарантирован
С явным номером Указанная Гарантирован в партиции

Число партиций определяет максимальный параллелизм группы консументов: в одной группе партиция обрабатывается одним консументом, поэтому число консументов сверх числа партиций не увеличивает скорость. О группах — в статье про consumer groups и перебалансировку.

Что влияет на выбор числа партиций

Число партиций задаётся при создании топика и увеличивается позже, но не уменьшается. Выбор определяется четырьмя факторами.

Требуемая пропускная способность. Каждая партиция обслуживается последовательно, поэтому общая пропускность пропорциональна числу партиций при достаточном числе консументов.

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

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

Стоимость перебалансировки. При изменении состава группы партиции перераспределяются, и время перебалансировки растёт с числом партиций.

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

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

О гарантиях порядка обработки — в статье про порядок обработки сообщений.

Практика: работа с партициями топика

1. Используйте ключ для связанных сообщений. События одной сущности попадают в одну партицию и обрабатываются последовательно.

2. Выбирайте ключ с равномерным распределением. Ключ с перекосом приводит к нагрузке на одну партицию при простаивающих остальных.

3. Закладывайте запас партиций при создании. Увеличение возможно позже, уменьшение — нет.

4. Учитывайте влияние на перебалансировку. Большое число партиций увеличивает время перераспределения при изменении состава группы.

5. Не превышайте число консументов числом партиций. Лишние консументы остаются без партиций и не участвуют в обработке.

6. Планируйте увеличение числа партиций. Для топика с ключевой маршрутизацией изменение нарушает порядок между старыми и новыми сообщениями.

7. Измеряйте нагрузку по партициям. Перекос виден по разнице смещений и объёма данных между партициями.

Рекомендации:

  1. Не используйте партицию как очередь задач. Партиция — журнал с чтением по смещению, а не очередь с удалением после обработки; о модели — в статье про основы Kafka.
  2. Учитывайте размер сообщения. Крупные сообщения снижают пропускную способность партиции, поэтому объём передаётся ссылкой.
  3. Проверяйте распределение ключей. Перекос по ключу приводит к тому, что одна партиция становится узким местом.
  4. Различайте порядок в партиции и порядок по времени. Сообщение, записанное позже, может попасть в партицию, обрабатываемую медленнее.
  5. Документируйте правило выбора ключа. Изменение ключа меняет распределение сообщений, поэтому правило фиксируется.

Практический сценарий: одна партиция перегружена при простаивающих остальных

Контекст: обработка сообщений отставала, при этом одна партиция накапливала отставание, а остальные обрабатывались без задержки.

  1. Диагностика. Смещение в одной партиции росло значительно быстрее, чем в остальных. Консумент, назначенный на эту партицию, не справлялся с объёмом, а другие консументы простаивали.
  2. Причина. Ключом сообщения служил идентификатор магазина, а один магазин формировал большую часть трафика. Все его сообщения попадали в одну партицию, поэтому нагрузка распределялась неравномерно.
  3. Действия. (а) Изменили ключ на составной: идентификатор магазина и идентификатор заказа, что распределило сообщения магазина по партициям; (б) проверили, что обработка не требует строгого порядка между заказами одного магазина, поскольку составной ключ его нарушает; (в) остановили запись на короткое время при увеличении числа партиций, чтобы избежать нарушения порядка между старыми и новыми сообщениями; (г) добавили метрику отставания по каждой партиции для раннего обнаружения перекоса; (д) зафиксировали правило выбора ключа в документации.
  4. Результат. Нагрузка распределилась по партициям, а перекос обнаруживается метрикой отставания до накопления задержки.

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

FAQ

Гарантируется ли порядок сообщений в топике? Нет. Порядок гарантирован внутри партиции, а между партициями не определён.

Можно ли уменьшить число партиций топика? Нет. Число партиций увеличивается, но не уменьшается, поэтому запас закладывается при создании.

Что произойдёт при числе консументов больше числа партиций? Лишние консументы остаются без партиций и не участвуют в обработке.

Нарушается ли порядок при увеличении числа партиций? Да, для сообщений с ключом, поскольку тот же ключ начинает отображаться в другую партицию.

Источники: Apache Kafka documentation (concepts, design, semantics) — ссылки в шапке.