Чи потрібен ключ під час надсилання повідомлень Кафці?


93
KeyedMessage<String, byte[]> keyedMessage = new KeyedMessage<String, byte[]>(request.getRequestTopicName(), SerializationUtils.serialize(message)); 
producer.send(keyedMessage);

Наразі я надсилаю повідомлення без будь-якого ключа як частину повідомлень із ключами, чи буде воно все ще працювати delete.retention.ms? Чи потрібно надсилати ключ як частину повідомлення? Чи добре це робити ключем як частиною повідомлення?

Відповіді:


172

Ключі в основному корисні / необхідні, якщо вам потрібне надійне замовлення ключа і розробляється щось на зразок державного автомата. Якщо вам потрібно, щоб повідомлення з однаковим ключем (наприклад, унікальний ідентифікатор) завжди бачились у правильному порядку, приєднання ключа до повідомлень забезпечить, щоб повідомлення з однаковим ключем завжди надходили до одного розділу теми. Kafka гарантує порядок у розділі, але не між розділами у темі, тому, якщо не надавати ключ - що призведе до кругового розподілу між розділами - не буде підтримувати такий порядок.

У випадку державного автомата ключі можна використовувати з log.cleaner.enable для дедуплікації записів тим самим ключем. У такому випадку Кафка припускає, що ваша програма піклується лише про найновіший екземпляр даного ключа, а очищувач журналу видаляє старі дублікати даного ключа, лише якщо ключ не є нульовим. Ця форма ущільнення журналу контролюється властивістю log.cleaner.delete.retention і вимагає ключів.

Крім того, більш поширене властивість log.retention.hours , яке ввімкнено за замовчуванням, працює шляхом видалення повних сегментів журналу, які застаріли. У цьому випадку ключі надавати не потрібно. Kafka просто видалить фрагменти журналу, які є старшими за вказаний період зберігання.

Це все, щоб сказати, якщо ви ввімкнули ущільнення журналу або вимагаєте чіткого порядку повідомлень з тим самим ключем, тоді ви точно повинні використовувати ключі. В іншому випадку нульові ключі можуть забезпечити кращий розподіл і запобігти потенційним проблемам гарячого виділення у випадках, коли деякі ключі можуть відображатися більше, ніж інші.


Я новачок у Кафці, тому причина так багато запитань: Є кілька запитань щодо цього: Перше питання, чи можемо ми споживати повідомлення за ключовим принципом, в даний час я споживаю повідомлення від MessagAndMetadata mm. або чудово ігнорувати ключ під час споживання повідомлення. Я використовую Api рівня споживача високого рівня.
gaurav

1
@kuujo Я припускаю, що це видалення копій стосується лише записів журналу, і це не обов'язково видаляє копії повідомлень у черзі теми?
user1658296

2
@oblivion, коли повідомлення послідовно надходять у один і той же розділ, важливий для обробки неідемпонентних оновлень, наприклад, замовник вибирає дату доставки (одне повідомлення), але змінює думку пізніше (друге повідомлення). Якщо повідомлення повинні надходити до різних розділів, то будь-яке повідомлення може бути оброблене першим / останнім, наприклад, 2 споживачі споживають з кожного розділу. Якщо обидва повідомлення, що стосуються однієї і тієї ж доставки, потрапляють в один розділ, тоді вони обробляються "перший у першому", вказуючи правильну кінцеву дату доставки.
Кунал

3
Гарантії замовлення надходять не від ключа, а від повідомлень, що знаходяться в одному розділі. Маршрутизація повідомлень до розділів не повинна базуватися на ключах. Ви можете явно вказати розділ при створенніProducerRecord
солодовий

2
Я розумію, що клієнт-виробник відповідає за вибір розділу ( kafka.apache.org/documentation.html#design_loadbalancing ), який може базуватися на ключі, а може і не. То чому ви кажете, що ключі необхідні для замовлення?
lfk

5

На додаток до дуже корисної прийнятої відповіді, я хотів би додати ще кілька деталей

Розбиття

За замовчуванням Kafka використовує ключ повідомлення, щоб вибрати розділ теми, до якої він пише. Це робиться приблизно так

hash(key) % number_of_partitions

Якщо не вказано жодного ключа, тоді Кафка розподілить дані випадковим чином, круглим способом.

Замовлення

Як зазначено у даній відповіді, Кафка має гарантії щодо упорядкування повідомлень лише на рівні розділів.

Скажімо, ви хочете зберігати фінансові операції для своїх клієнтів у темі Кафки з двома розділами. Повідомлення можуть виглядати так (ключ: значення)

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 завжди зберігатиме принаймні останнє відоме значення для кожного ключа повідомлення в журналі даних для одного розділу теми.".

Цей приємний та корисний параметр буде недоступний без жодної клавіші.

Використання ключів

У реальних випадках використання ключа Кафки може мати величезний вплив на вашу ефективність та чіткість вашої ділової логіки.

Наприклад, ключ можна використовувати, природно, для розділення даних. Оскільки ви можете контролювати своїх споживачів читати з певних розділів, це може служити ефективним фільтром. Крім того, ключ може включати деякі метадані про фактичну вартість повідомлення, що допомагає контролювати подальшу обробку. Ключі зазвичай менші за значення, і тому зручніше аналізувати ключ замість цілого значення. У той же час ви можете застосувати всі серіалізації та реєстрацію схеми, як це зроблено зі своїм значенням, також за допомогою ключа.

Як примітка, існує також концепція заголовка, яка може використовуватися для зберігання інформації, див. Документацію .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.