Czy klucz jest wymagany podczas wysyłania wiadomości do platformy Kafka?

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

Obecnie wysyłam wiadomości bez klucza jako część wiadomości z kluczem, czy nadal będzie to działać delete.retention.ms? Czy muszę wysłać klucz jako część wiadomości? Czy dobrze jest tworzyć klucz jako część wiadomości?

gaurav
źródło

Odpowiedzi:

184

Klucze są najczęściej przydatne / niezbędne, jeśli potrzebujesz silnego porządku dla klucza i opracowujesz coś w rodzaju automatu stanowego. Jeśli chcesz, aby wiadomości z tym samym kluczem (na przykład unikalnym identyfikatorem) były zawsze wyświetlane we właściwej kolejności, dołączenie klucza do wiadomości zapewni, że wiadomości z tym samym kluczem będą zawsze trafiały do ​​tej samej partycji w temacie. Kafka gwarantuje porządek w partycji, ale nie między partycjami w temacie, więc alternatywnie brak klucza - co spowoduje dystrybucję okrężną między partycjami - nie utrzyma takiej kolejności.

W przypadku automatu stanowego klucze mogą być używane z opcją log.cleaner.enable do deduplikacji wpisów z tym samym kluczem. W takim przypadku Kafka zakłada, że ​​aplikacja dba tylko o najnowszą instancję danego klucza, a narzędzie do czyszczenia dziennika usuwa starsze duplikaty danego klucza tylko wtedy, gdy klucz nie jest pusty. Ta forma zagęszczania dziennika jest kontrolowana przez właściwość log.cleaner.delete.retention i wymaga kluczy.

Alternatywnie, bardziej powszechna właściwość log.retention.hours , która jest domyślnie włączona, działa poprzez usuwanie całych segmentów dziennika, które są nieaktualne. W takim przypadku klucze nie muszą być dostarczane. Kafka po prostu usunie fragmenty dziennika, które są starsze niż podany okres przechowywania.

To wszystko, co można powiedzieć, jeśli włączyłeś kompaktowanie dziennika lub wymagasz ścisłej kolejności wiadomości z tym samym kluczem, zdecydowanie powinieneś używać kluczy. W przeciwnym razie puste klucze mogą zapewnić lepszą dystrybucję i zapobiegać potencjalnym problemom z hot spotami w przypadkach, gdy niektóre klawisze mogą pojawiać się częściej niż inne.

kuujo
źródło
Jestem nowy w Kafce, dlatego zadaje tak wiele pytań: Jest kilka pytań na ten temat: pierwsze pytanie, czy możemy konsumować wiadomość na podstawie klucza, obecnie konsumuję wiadomość z MessagAndMetadata mm. czy też dobrze jest zignorować klucz w momencie konsumowania wiadomości. Używam konsumenckiego interfejsu API wysokiego poziomu.
gaurav
1
@kuujo Zakładam, że ta deduplikacja dotyczy tylko wpisów dziennika, niekoniecznie usuwa duplikaty wiadomości w kolejce tematów?
user1658296
2
@oblivion, aby wiadomości trafiały do ​​tej samej partycji sekwencyjnie, jest ważne dla obsługi aktualizacji innych niż idemponent, np. klient wybiera datę dostarczenia (jedna wiadomość), ale zmienia zdanie później (druga wiadomość). Jeśli wiadomości miałyby trafiać do różnych partycji, wówczas każda wiadomość może być przetwarzana jako pierwsza / ostatnia, np. Przy 2 odbiorcach konsumujących z każdej partycji. Jeśli obie wiadomości dotyczące tej samej dostawy trafiają do tej samej partycji, są przetwarzane jako pierwsze weszło-pierwsze wyszło, podając prawidłową ostateczną datę dostarczenia.
Kunal
3
Gwarancje kolejności nie pochodzą z klucza, ale z wiadomości znajdujących się w tej samej partycji. Kierowanie komunikatów do partycji nie musi być oparte na kluczach. Możesz jawnie określić partycję podczas tworzeniaProducerRecord
Malt
2
Rozumiem, że klient producenta jest odpowiedzialny za wybór partycji ( kafka.apache.org/documentation.html#design_loadbalancing ), która może, ale nie musi, być oparta na kluczu. Dlaczego więc mówisz, że klucze są potrzebne do zamówienia?
lfk
11

Oprócz bardzo pomocnej zaakceptowanej odpowiedzi chciałbym dodać kilka dodatkowych szczegółów

Partycjonowanie

Domyślnie Kafka używa klucza wiadomości do wybrania partycji, do której pisze. Odbywa się to w DefaultPartitionerBy

kafka.common.utils.Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;

Jeśli nie zostanie dostarczony żaden klucz, Kafka podzieli dane losowo w sposób okrężny.

W Kafce możliwe jest stworzenie własnego Partitionera poprzez rozszerzenie Partitionerklasy. W tym celu musisz nadpisać partitionmetodę, która ma podpis:

int partition(String topic, 
              Object key,
              byte[] keyBytes,
              Object value,
              byte[] valueBytes,
              Cluster cluster)

Zazwyczaj do wybrania partycji używany jest klucz wiadomości Kafka. Bez klucza musisz polegać na wartości, która może być znacznie bardziej złożona do przetworzenia.

Zamawianie

Jak podano w udzielonej odpowiedzi, Kafka ma gwarancje uporządkowania wiadomości tylko na poziomie partycji.

Załóżmy, że chcesz przechowywać transakcje finansowe swoich klientów w temacie Kafki z dwiema partycjami. Wiadomości mogą wyglądać następująco (klucz: wartość)

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}

Ponieważ nie zdefiniowaliśmy klucza, prawdopodobnie będą wyglądać dwie partycje

// 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}

Twój konsument czytający ten temat może w końcu powiedzieć Ci, że saldo na koncie wynosi 600 w określonym czasie, chociaż nigdy tak nie było! Tylko dlatego, że czytał wszystkie wiadomości w partycji 0 przed wiadomościami w partycji 1.

Dzięki rozsądnemu kluczowi (np. CustomerId) można tego uniknąć, ponieważ podział na partycje wyglądałby tak:

// 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}

Zagęszczanie kłód

Bez klucza jako części wiadomości nie będzie można ustawić konfiguracji tematu cleanup.policyna compacted. Zgodnie z dokumentacją „kompaktowanie dziennika zapewnia, że ​​Kafka zawsze zachowa co najmniej ostatnią znaną wartość dla każdego klucza wiadomości w dzienniku danych dla jednej partycji tematu”.

To miłe i pomocne ustawienie nie będzie dostępne bez klucza.

Korzystanie z kluczy

W rzeczywistych przypadkach użycia klucz wiadomości Kafka może mieć ogromny wpływ na wydajność i przejrzystość logiki biznesowej.

Klucz może być na przykład naturalnie używany do partycjonowania danych. Ponieważ możesz kontrolować konsumentów, aby czytali z określonych partycji, może to służyć jako skuteczny filtr. Klucz może również zawierać metadane dotyczące rzeczywistej wartości wiadomości, które pomagają kontrolować dalsze przetwarzanie. Klucze są zwykle mniejsze niż wartości i dlatego wygodniej jest przeanalizować klucz zamiast całej wartości. W tym samym czasie możesz zastosować wszystkie serializacje i rejestrację schematu, tak jak zostało to zrobione z wartością, również z kluczem.

Uwaga: istnieje również koncepcja nagłówka, który może służyć do przechowywania informacji, patrz dokumentacja .

mikrofon
źródło
0

Klucz z wiadomością jest zasadniczo wysyłany w celu uzyskania kolejności wiadomości dla określonego pola.

  • Jeśli klucz = null, dane są wysyłane w trybie okrężnym (do innej partycji i do innego brokera w rozproszonym środowisku i oczywiście do tego samego tematu).
  • Jeśli klucz zostanie wysłany, wszystkie wiadomości dla tego klucza będą zawsze kierowane do tej samej partycji.

Wyjaśnij i przykład

  • klucz może być dowolnym ciągiem znaków lub liczbą całkowitą itp. weź przykład liczby całkowitej identyfikator_pracownika jako klucz.
  • Zatem Employyee_id 123 zawsze będzie kierować się do partycji 0, Employy_id 345 zawsze do partycji 1. Decyduje o tym algorytm haszowania klucza, który zależy od liczby partycji.
  • jeśli nie wyślesz żadnego klucza, wiadomość może przejść do dowolnej partycji przy użyciu techniki okrężnej.
Pradeep Singh
źródło