---
title: "Symulator Kafki v1.1: zrozumieć semantykę producenta w Kafce"
date: 2026-07-14T00:00:00.000Z
author: "michal"
excerpt: "Symulator Kafki v1.1 dodaje dziesięć scenariuszy obejmujących batchowanie producenta, partycjonowanie, kompresję, backpressure, ponawianie prób i idempotentność."
---
Co dzieje się po tym, jak producent Kafki wywoła `send()`?

Brzmi to jak proste pytanie. Producent tworzy rekord, wysyła go do Kafki i otrzymuje potwierdzenie.

Pomiędzy tymi krokami może się jednak zdarzyć całkiem sporo.

Producent może poczekać na kolejne rekordy i utworzyć batch. Musi wybrać partycję. Może skompresować batch. Jeśli broker jest wolny, producentowi może zabraknąć miejsca w buforze. Jeśli żądanie się nie powiedzie, może je ponowić. Jeśli ponowienie zakończy się sukcesem po tym, jak pierwsze żądanie zostało już zapisane, Kafka może otrzymać ten sam batch dwukrotnie.

[Symulator Kafki](/kafka-simulator/) v1.1 skupia się na tej właśnie semantyce producenta.

Wydanie dodaje **10 nowych scenariuszy**, powiększając cały program nauczania do **23 ze 125 scenariuszy**.

## Co znajduje się w v1.1?

Osiem z dziesięciu scenariuszy skupia się na producencie. Pozostałe dwa rozszerzają ścieżkę anatomii logu: odczyt do high watermarku oraz log start offset.

Scenariusze producenta obejmują pięć obszarów:

- batchowanie z `linger.ms` i `batch.size`,
- partycjonery producenta,
- kompresję,
- backpressure z `buffer.memory` i `max.block.ms`,
- ponawianie prób i idempotentność.

Przyjrzyjmy się każdemu z nich.

## Batchowanie z `linger.ms` i `batch.size`

Producent Kafki niekoniecznie wysyła każdy rekord w osobnym żądaniu.

Rekordy przypisane do tej samej partycji mogą zostać zebrane w batch. Producent wysyła batch, gdy się zapełni albo gdy upłynie skonfigurowany czas oczekiwania.

To właśnie tu ważne stają się dwa ustawienia producenta:

- `batch.size` ogranicza rozmiar batcha,
- `linger.ms` pozwala producentowi poczekać na dodatkowe rekordy przed jego wysłaniem.

Kompromis polega na wyborze między opóźnieniem a przepustowością.

Większy batch zwykle oznacza mniej żądań i lepszą kompresję. Oczekiwanie na zapełnienie batcha może jednak zwiększyć opóźnienie pojedynczego rekordu.

Nowe scenariusze uwidaczniają to zachowanie. Możesz zobaczyć, kiedy rekordy trafiają do batcha, co powoduje jego wysłanie oraz jak zmiana konfiguracji wpływa na żądania generowane przez klienta.

## Partycjonery producenta

Zanim producent utworzy batch dla konkretnej partycji, musi ją wybrać.

Dla rekordów z kluczem to klucz decyduje o wyborze partycji. Rekordy z tym samym kluczem są więc zwykle przypisywane do tej samej partycji.

Dla rekordów bez klucza zachowanie jest inne. Producent może grupować rekordy zgodnie ze swoją strategią partycjonowania, zamiast wyliczać partycję z klucza.

Symulator pokazuje oba przypadki krok po kroku:

1. producent otrzymuje rekord,
2. partycjoner wybiera partycję,
3. rekord zostaje dodany do odpowiedniego batcha,
4. batch zostaje wysłany do lidera tej partycji.

Dzięki temu łatwiej dostrzec, dlaczego partycjonowanie wpływa zarówno na kolejność, jak i na batchowanie.

## Kompresja odbywa się per batch

Kompresja w producencie Kafki jest stosowana do batchy rekordów, a nie niezależnie do każdego rekordu.

To rozróżnienie ma znaczenie.

Kompresja jest zwykle skuteczniejsza, gdy batch zawiera wiele podobnych rekordów. Batch zawierający tylko jeden mały rekord może zyskać na kompresji bardzo niewiele. Większy batch z powtarzalnymi danymi może zostać skompresowany dużo wydajniej.

W efekcie kompresja jest powiązana z konfiguracją batchowania. Ustawienia takie jak `batch.size` i `linger.ms` mogą wpływać nie tylko na częstotliwość żądań, ale też na kształt i podatność na kompresję powstających batchy.

Nowe scenariusze pokazują rozmiary batchy przed i po kompresji, uwidaczniając tę zależność.

## Backpressure z `buffer.memory` i `max.block.ms`

Co się dzieje, gdy aplikacja produkuje rekordy szybciej, niż Kafka jest w stanie je przyjąć?

Producent nie może przechowywać w pamięci nieograniczonej liczby niewysłanych rekordów. Korzysta z ograniczonego bufora, konfigurowanego za pomocą `buffer.memory`.

Gdy w buforze nie ma wolnego miejsca, wywołanie `send()` może się zablokować w oczekiwaniu na zwolnienie pamięci.

Nie będzie jednak czekać w nieskończoność. Maksymalny czas blokowania kontroluje `max.block.ms`.

Daje nam to dwa możliwe rozwiązania:

- wystarczająco dużo danych zostaje wysłanych i potwierdzonych, zwalniając miejsce w buforze,
- przed upływem limitu czasu nie pojawia się wolne miejsce i wysłanie kończy się niepowodzeniem.

Symulator śledzi bufor producenta bezpośrednio. Możesz zobaczyć, jak pamięć jest alokowana przy dodawaniu rekordów i zwalniana wraz z zakończeniem żądań.

Jest to szczególnie przydatne w połączeniu z wolnym brokerem lub kwotą przepustowości. Zamiast traktować backpressure producenta jako abstrakcyjny problem konfiguracyjny, możesz obserwować, jak bufor się zapełnia, i zobaczyć dokładnie to wysłanie, które zostaje zablokowane.

## Ponawianie prób i problem duplikatów

Załóżmy, że producent wysyła batch do brokera.

Broker zapisuje batch pomyślnie, ale potwierdzenie ginie, zanim dotrze do producenta.

Z perspektywy producenta żądanie się nie powiodło. Nie może wiedzieć, czy broker zapisał dane. Ponowienie jest więc rozsądne.

Jeśli jednak pierwsze żądanie zostało zapisane pomyślnie, ponowienie może dopisać ten sam batch po raz drugi.

To właśnie problem duplikatów wywołany przez niejednoznaczne awarie.

Scenariusz ponawiania pokazuje oba żądania:

1. oryginalne żądanie dociera do brokera,
2. potwierdzenie ginie,
3. producent ponawia batch,
4. broker otrzymuje te same rekordy po raz drugi.

Bez idempotentności obie kopie mogą zostać dopisane.

## Semantyka producenta idempotentnego

Producent idempotentny pozwala Kafce rozpoznawać ponawiane batche.

Kafka nadaje producentowi tożsamość i śledzi numery sekwencyjne niezależnie dla każdej partycji. Gdy batch zostaje ponowiony z numerem sekwencyjnym, który broker już przetworzył, broker może go potwierdzić bez ponownego dopisywania rekordów.

Istotne jest rozróżnienie między ponowieniem a prawdziwym duplikatem.

Dwa rekordy mogą zawierać dokładnie ten sam klucz i wartość, a mimo to być dwoma osobnymi rekordami celowo wysłanymi przez aplikację. Kafka nie może takich rekordów usuwać.

Idempotentność deduplikuje ponowienia protokołu producenta. Nie deduplikuje danych aplikacji na podstawie ich zawartości.

Nowe scenariusze pokazują:

- identyfikatory producenta (producer ID),
- numery sekwencyjne partycji,
- udane ponowienia idempotentne,
- prawdziwe zduplikowane rekordy,
- wykrywanie sekwencji poza kolejnością.

## Dlaczego `max.in.flight.requests.per.connection` ma znaczenie?

Producent może mieć wiele żądań oczekujących na odpowiedź w tym samym czasie.

Poprawia to przepustowość, ale tworzy też potencjalny problem z kolejnością.

Załóżmy, że producent wysyła batch A, a następnie batch B. Batch A tymczasowo się nie powiódł, a batch B odniósł sukces. Jeśli A zostaje ponowiony po tym, jak B został już zapisany, rekordy mogą zostać dopisane w innej kolejności.

Idempotentność wykorzystuje numery sekwencyjne do wykrywania nieprawidłowej kolejności.

Symulator pokazuje to wprost. Możesz zobaczyć oczekiwany przez brokera numer sekwencyjny, numer niesiony przez przychodzący batch oraz moment, w którym broker odrzuca żądanie poza kolejnością.

## Wgląd w wewnętrzny stan producenta

Nowe scenariusze intensywnie korzystają z **inspektora** symulatora, który odsłania wewnętrzny stan producentów i partycji, w tym:

- liczniki ponowień,
- numery sekwencyjne producenta,
- numery sekwencyjne brokera,
- alokację bufora.

Zwykle te wartości są ukryte za metrykami producenta, logami i zachowaniem protokołu. W symulatorze można je badać bezpośrednio, przewijając scenariusz do przodu lub do tyłu.

## Poprawki modelu producenta

Dodanie nowych scenariuszy wymagało też uściślenia istniejącego modelu producenta.

### Ponowienia liczone są per batch

Kafka ponawia żądania produkujące, które zawierają batche rekordów.

Nieudane żądanie powinno więc zużywać jedno ponowienie dla całego batcha, a nie po jednym ponowieniu dla każdego rekordu w środku.

Symulator działa teraz zgodnie z tym modelem. Każdy rekord z nieudanego batcha jest wysyłany ponownie, a licznik ponowień zwiększa się jeden raz.

### Pamięć bufora jest zwalniana precyzyjnie

Pamięć bufora producenta jest teraz zwalniana wraz z napływaniem potwierdzeń.

Naprawia to przypadki, w których symulator mógł zgłaszać backpressure, mimo że potwierdzone rekordy powinny były już zwolnić swoją pamięć.

To samo dotyczy przekroczeń limitu `max.block.ms`. Gdy zablokowane wysłanie przekroczy limit czasu, jego alokacja bufora zostaje uprzątnięta.

### `acks=all` jest śledzone per partycja

Trwałość w Kafce jest definiowana niezależnie dla każdej partycji.

Producent piszący do wielu partycji musi więc czekać, aż właściwa partycja spełni jego wymagania dotyczące potwierdzeń. Postęp w innej partycji nie może potwierdzić niezwiązanego żądania.

Symulator śledzi teraz ten stan osobno dla każdej partycji i tematu.

### Reset producenta czyści stan idempotentności

Broker przechowuje stan deduplikacji powiązany z producentem idempotentnym.

Gdy symulowany producent zostaje usunięty lub zresetowany, ten stan również musi zostać usunięty. W przeciwnym razie rekordy nowo utworzonego producenta mogą zostać błędnie zaklasyfikowane jako stare ponowienia.

Zachowanie resetu czyści teraz odpowiadający mu stan po stronie brokera.

### Przewijanie wstecz odtwarza stan ponowień

Scenariusze można przesuwać do przodu i przewijać wstecz po jednym kroku.

Przewijanie wstecz odtwarza teraz liczniki ponowień używane w każdej rundzie symulacji. Widoczny stan producenta jest więc spójny niezależnie od tego, czy scenariusz przesuwa się do przodu, czy do tyłu.

## Usprawnienia placu zabaw

Wydanie zawiera też kilka poprawek poza modelem producenta.

### Rebalansowanie grup konsumentów

Grupy konsumentów na placu zabaw otrzymały kilka poprawek poprawności:

- sticky assignor minimalizuje teraz przenoszenie partycji, zamiast przydzielać je od zera,
- statyczny członek grupy, który pozostaje nieobecny dłużej niż `session.timeout.ms`, jest usuwany jak każdy inny członek,
- zmiana liczby partycji tematu wyzwala teraz prawidłowy rebalans bez naruszania stanu członków,
- partycje nigdy nie są przydzielane członkowi, który już nie żyje.

### Konfiguracja tematów i kompaktowanie

Kafka nigdy nie zmniejsza liczby partycji tematu. Zmniejszenie usunęłoby dane i zepsuło partycjonowanie oparte na kluczach, dlatego `kafka-topics --alter` odrzuca je z błędem `InvalidPartitionsException`.

Plac zabaw stosuje teraz tę samą regułę. Zmniejszenie liczby partycji jest odrzucane z pouczającym błędem, zamiast po cichu usuwać partycje.

Tematy kompaktowane również zachowują się precyzyjniej:

- tombstone przetrwa, dopóki nie upłynie jego własne okno karencji `delete.retention.ms`,
- rekord bez klucza nie może zostać wyprodukowany do tematu kompaktowanego,
- przy `compact,delete` retencja czasowa odzyskuje teraz stare rekordy niezależnie od kompaktowania.

### Udostępniane linki zachowują cały scenariusz

Plac zabaw serializuje swoje akcje do adresu URL, aby scenariusz można było udostępnić innej osobie.

Kodek uwzględnia teraz wszystkie zmiany konfiguracji, w tym aktualizacje liczby partycji. Link żądający typu klastra z późniejszego pakietu wydania przełącza się teraz na obsługiwaną topologię, zamiast renderować bezużyteczny klaster.

Otwarcie udostępnionego linku powinno więc odtwarzać ten sam scenariusz, który został pierwotnie zbudowany.

### Poprawki interakcji

Poprawiono również kilka drobniejszych problemów placu zabaw:

- identyfikatory encji nie kolidują już po usunięciu i ponownym utworzeniu encji,
- rozmieszczanie producenta działa poprawnie na szerszych siatkach brokerów.

### Nagłówki bezpieczeństwa

Strona wysyła teraz Content Security Policy oraz Permissions Policy.

## Dlaczego zacząć od producenta?

Gwarancje Kafki omawia się często z perspektywy brokera: replikacja, przynależność do ISR, high watermark i przełączanie awaryjne lidera.

Gwarancja obserwowana przez aplikację zależy jednak również od producenta.

Którego trybu potwierdzeń używa? Czy ponawia próby? Czy włączona jest idempotentność? Ile żądań może być w locie? Co się dzieje, gdy jego lokalny bufor się zapełni?

Te ustawienia decydują o tym, czy zapis jest szybki, trwały, uporządkowany, zduplikowany, zablokowany czy odrzucony.

Właśnie dlatego pierwszy większy pakiet scenariuszy Symulatora Kafki skupia się na producencie.

Gdy batchowanie, potwierdzenia, ponowienia i idempotentność stają się widoczne, późniejsze scenariusze dotyczące replikacji, trwałości i transakcji mają wyraźniejszy fundament.

Otwórz [Symulator Kafki](/kafka-simulator/), wybierz ścieżkę producenta i wypróbuj scenariusze awarii krok po kroku.