Разглеждаме парадокса и гаранциите за доставка, предлагани от Kafka Producer, за да се справим с него.

Преди да навлезем в подробностите за продуцента на Кафка и проблема с 2 генерала. Нека опресним основите –

Kafka е разпределена система за съобщения с един или повечепроизводители, добавящи съобщения към брокераи една или повече групи потребителичетещи от брокера.

Данните се съхраняват в брокера. Има водещ брокер и за дълготрайност Kafka репликира данните и на други брокери, известни като брокери на последователи. В случай, че водещият брокер се провали, един от последователите се избира за нов лидер.

Доставката на съобщение от производител до потребител може да бъде разделена на 2 отделни процеса —

  1. Производител към брокер — Гаранциите за доставка се обработват с потвърждение от брокера.
  2. Посредник към потребителя — Въз основа на проучване, потребителят контролира колко пъти може да прочете и обработи съобщение.

По същата причина също разделих гаранциите за доставка на 2 статии— Схеми за доставка от производителите и обработка на съобщенията от потребителите.

Какъв е проблемът на 2 генерала?

Проблемът на 2 генерала взема примера на 2 части от армията, които планират да атакуват укрепен град от 2 различни посоки. За да успеят, 2-мата генерали трябва да могат да започнат координирана атака от двете посоки.

Проблемъте, че пратениците, носещи съобщението, трябва да преминат през долина, охранявана от силите на града. Тъй като съобщението се изпраща през враждебна територия, има възможност защитниците да прихванат/заловят/убият пратеника. Няма няма гаранция, че последното съобщение е достигнало до генерала от другата страна. Без тази гаранция и двамата генерали са в дилема — генерал А не знае дали съобщението за атака е достигнало до генерал Б. И генерал Б не знае дали потвърждението е достигнало до генерал А. Така и двамата ще се поколебаят да атакуват без да знае дали другата армейска част ще пристигне за координирания план за нападение.

Решението изглежда просто -

  1. Лидерът Генерал, Генерал А инициира съобщението за атака — „Ние атакуваме в 4 сутринта“
  2. Генерал Б трябва да потвърди това „Получих съобщението, атакуваме в 4 сутринта“

Обикновено това е достатъчно, за да се постигне консенсус, но генерал Б не знае дали генерал А е получил това съобщение. Така че трябва да има още едно потвърждение от генерал А, за да бъде „Прикачването потвърдено“. И това започва един безкраен цикъл от признания. Така че проблемът е неразрешим.

Има някои прагматични начини за справяне с него -

  1. Интензивни разходи — Ако има достатъчно пратеници, които да рискуват, Генералите могат да изпратят няколко пратеника наведнъж, надявайки се, че някои ще стигнат до другата страна. Да кажем 100 месинджъра, като всеки месинджър има свой пореден номер. Дори ако генералът от другата страна получи едно съобщение, той знае кога да атакува и липсващите поредни номера също казват на генерала колко безопасна е долината.
  2. Интензивно време — Ако няма достатъчно месинджъри, които да рискуват, може да има друг подход, при който липсата на съобщения изгражда увереност. Да приемем, че времето за пресичане на долината е 1 час, Генерал А продължава да изпраща съобщения до Генерал Б на всеки 1 час, докато не получи едно потвърждение от Генерал Б. Ако Генерал Б получи съобщение за няколко часа след изпращане на потвърждението, това означава, че генерал А е получил потвърждението.

Гаранции за доставка от Производителя до Брокера

Когато продуцентът произвежда послание към Кафка, той има някои възможности да избере, за да отговаря на контекста.

1. Без гаранция / пожар и забравяне:

Производителят не чака потвърждение, съобщението може да бъде загубено дори преди да бъде записано в постоянното хранилище на брокера.

Настройка на производителя: acks = 0

Няма няма гаранция за дълготрайност. Но е най-бързият.

От гледна точка на производителя, това може да се счита за доставка най-много веднъж, тъй като съобщенията могат да бъдат загубени, но не се дублират.

2. Само Leader Broker запазва съобщението и го потвърждава.

Брокерът потвърждава, когато водещият брокер е написал съобщението в своето постоянно хранилище. Данните ще бъдат репликирани на последователните брокери своевременно.

Настройка на производителя: acks = 1

Издръжливостта е много по-подобренано има малък шанс съобщението да се изгуби, ако се провеждат избори за лидер, докато съобщението се създава.

Забавянето е по-дълго, тъй като има двупосочно пътуване между водещия брокер и производителя клиент.

3. Най-силна гаранция. Всички (insync) брокери запазват съобщението и го потвърждават.

Брокерът потвърждава, когато всички реплики на брокера (по-точно синхронизирани реплики) са записали съобщението в своето постоянно хранилище.

Настройка на производителя: acks = всички

Издръжливостта е най-силна. Забавянето е около 2,5 пъти повече от просто лидер.

От гледна точка на производителя това може да се счита за доставка поне веднъж, тъй като съобщенията никога не се губят (но могат да бъдат доставени отново).

Как проблемът на 2 генерала може да повлияе на Kafka Producer?

Сега, както знаем от проблема на 2 генерала, когато генералът не получи потвърждението, той не знае дали самото съобщение е неуспешно или потвърждението е неуспешно. За да бъде сигурен в доставката, той изпраща съобщението няколко пъти, което води до дублиране на съобщения.

По същия начин, когато Kafka producer е конфигуриран да получава потвърждения и ако не получи потвърждението, няма друг избор освен да изпрати отново съобщението. Ако съобщението вече е написано от брокера и липсва само потвърждението, това може да доведе до дублиране на съобщения. Следователно това води до това, че съобщенията се доставят повече от веднъж на потребителя.

Какво може да се направи, за да се избегне създаването на дублиращи се съобщения?

На първо място, дублиращите се съобщения могат или не могат да бъдат проблем. Ако са желани схеми точно веднъж, производителят на Kafka поддържа идемпотентна опция за доставка, която гарантира, че повторното изпращане няма да доведе до дублиращи се записи. Това позволява на производителя да прави повторни опити, докато успее без възможност за дублиране.

Кафка прозрачно ги открива и игнорира. За да постигне това, брокерът присвоява на всеки производител идентификатор и дедупликира съобщенията, като използва пореден номер, който се изпраща от производителя заедно с всяко съобщение.

От гледна точка на производителя това е Схема точно веднъж.

Идемпотентният производител се нуждае от acks = all и други ограничения за настройките за повторни опити и MaxInFlight.

Важно: За поведението по подразбиране проверете документацията на SDK за специфичен език. За Java е вярно по подразбиране във версия ≥ 3.0.0 KAFKA-10619 Разрешете идемпотентността на производителя по подразбиране.

Но за .NET по подразбиране е изключено https://docs.confluent.io/platform/current/clients/confluent-kafka-dotnet/_site/api/Confluent.Kafka.ProducerConfig.html#Confluent_Kafka_ProducerConfig_EnableIdempotence.

Резюме

  1. 2 Generals“ е проблем, който демонстрира предизвикателствата на разпределените изчисления поради възможни повреди. Прагматичните решения на проблема приемат факта и се опитват да го смекчат.
  2. Производителят на Kafka предлага 3 вида гаранции за доставка.
  3. При липса на потвърждение продуцентът на Kafka може да създаде дублиращи се съобщения. Ако точно веднъж са желани схеми, може да се включи. Проверете специфичния за език SDK за поведение по подразбиране.

Надявам се статията да ви е харесала. В следващия ще покрия гаранциите за доставка за потребителя.

Справка и допълнително проучване

2 Проблем на генералите — https://finematics.com/two-generals-problem/

Kafka Producer гарантира — https://developer.confluent.io/courses/architecture/guarantees/