В дополнение к очень полезному принятому ответу я хотел бы добавить еще несколько деталей
Разбиение
По умолчанию Kafka использует ключ сообщения для выбора раздела темы, в которую он записывает. Это делается в DefaultPartitionerВУ
kafka.common.utils.Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
Если ключ не указан, Kafka будет произвольно разбивать данные по циклическому алгоритму.
В Kafka можно создать свой собственный Partitioner, расширив Partitionerкласс. Для этого вам нужно переопределить partitionметод с подписью:
int partition(String topic,
Object key,
byte[] keyBytes,
Object value,
byte[] valueBytes,
Cluster cluster)
Обычно для выбора раздела используется ключ сообщения Kafka. Без ключа вам нужно полагаться на значение, которое может быть намного сложнее обработать.
Заказ
Как указано в данном ответе, Kafka гарантирует упорядочивание сообщений только на уровне раздела.
Допустим, вы хотите хранить финансовые транзакции для своих клиентов в теме Kafka с двумя разделами. Сообщения могут выглядеть так (ключ: значение)
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 2, "changeInBankAccount": +100}
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 1, "changeInBankAccount": -1337}
null:{"customerId": 1, "changeInBankAccount": +200}
Поскольку мы не определили ключ, два раздела предположительно будут выглядеть как
// partition 0
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 1, "changeInBankAccount": +200}
// partition 1
null:{"customerId": 2, "changeInBankAccount": +100}
null:{"customerId": 1, "changeInBankAccount": -1337}
Ваш потребитель, читающий эту тему, может в конечном итоге сказать вам, что баланс на счете составляет 600 в определенное время, хотя этого никогда не было! Просто потому, что он читал все сообщения в разделе 0 до сообщений в разделе 1.
С осмысленным ключом (например, с customerId) этого можно было бы избежать, поскольку разделение было бы таким:
// partition 0
1:{"customerId": 1, "changeInBankAccount": +200}
1:{"customerId": 1, "changeInBankAccount": +200}
1:{"customerId": 1, "changeInBankAccount": -1337}
1:{"customerId": 1, "changeInBankAccount": +200}
// partition 1
2:{"customerId": 2, "changeInBankAccount": +100}
Уплотнение бревен
Без ключа в составе ваших сообщений вы не сможете установить конфигурацию темы cleanup.policyна compacted. Согласно документации, «сжатие журнала гарантирует, что Kafka всегда будет сохранять по крайней мере последнее известное значение для каждого ключа сообщения в журнале данных для одного раздела темы».
Эта приятная и полезная настройка не будет доступна без ключа.
Использование ключей
В реальных случаях использования ключ сообщения Kafka может иметь огромное влияние на вашу производительность и ясность вашей бизнес-логики.
Например, ключ может использоваться естественным образом для разделения ваших данных. Поскольку вы можете управлять потребителями для чтения из определенных разделов, это может служить эффективным фильтром. Кроме того, ключ может включать в себя некоторые метаданные о фактическом значении сообщения, которые помогают вам контролировать последующую обработку. Ключи обычно меньше значений, поэтому удобнее анализировать ключ, а не все значение. В то же время вы можете применить все сериализации и регистрацию схемы, как это было сделано с вашим значением, также с ключом.
В качестве примечания, существует также концепция заголовка, который можно использовать для хранения информации, см. Документацию .