В дополнение к очень полезному принятому ответу я хотел бы добавить еще несколько деталей
Разбиение
По умолчанию 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 может иметь огромное влияние на вашу производительность и ясность вашей бизнес-логики.
Например, ключ может использоваться естественным образом для разделения ваших данных. Поскольку вы можете управлять потребителями для чтения из определенных разделов, это может служить эффективным фильтром. Кроме того, ключ может включать в себя некоторые метаданные о фактическом значении сообщения, которые помогают вам контролировать последующую обработку. Ключи обычно меньше значений, поэтому удобнее анализировать ключ, а не все значение. В то же время вы можете применить все сериализации и регистрацию схемы, как это было сделано с вашим значением, также с ключом.
В качестве примечания, существует также концепция заголовка, который можно использовать для хранения информации, см. Документацию .