Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Хей Хабр!

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

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Засега общността просто научава границите на този мощен инструмент. И така, наскоро беше публикувана статия, с чийто превод бихме искали да ви запознаем. От собствения си опит авторът разказва как да превърне Kafka Streams в разпределено хранилище на данни. Наслади се на четенето!

Библиотека на Apache Потоци на Кафка използвани в световен мащаб в предприятия за обработка на разпределен поток върху Apache Kafka. Един от недооценените аспекти на тази рамка е, че ви позволява да съхранявате локално състояние, произведено въз основа на обработка на нишки.

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

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

Защо решихме, че е време да променим начина, по който работим със споделеното състояние

Трябваше да поддържаме състоянието на различни обекти въз основа на доклади на агенти (например: атакуван ли е сайтът)? Преди да мигрираме към Kafka Streams, често разчитахме на една централна база данни (+ API на услугата) за управление на състоянието. Този подход има своите недостатъци: ситуации с интензивни срещи поддържането на последователност и синхронизация се превръща в истинско предизвикателство. Базата данни може да се превърне в тясно място или да попадне там състезателно състояние и страдат от непредсказуемост.

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Фигура 1: Типичен сценарий на разделено състояние, наблюдаван преди прехода към
Kafka и Kafka Streams: агентите съобщават своите възгледи чрез API, актуализираното състояние се изчислява чрез централна база данни

Запознайте се с Kafka Streams, което улеснява създаването на микроуслуги със споделено състояние

Преди около година решихме да разгледаме подробно нашите споделени сценарии за състояние, за да се справим с тези проблеми. Веднага решихме да пробваме Kafka Streams - знаем колко е мащабируем, високодостъпен и устойчив на грешки, каква богата стрийминг функционалност има (трансформации, включително такива със състояние). Точно това, от което имахме нужда, да не говорим колко зряла и надеждна е станала системата за съобщения в Kafka.

Всяка от микроуслугите със състояние, които създадохме, беше изградена върху екземпляр на Kafka Streams с доста проста топология. Състои се от 1) източник 2) процесор с постоянно хранилище ключ-стойност 3) приемник:

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

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

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

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Фигура 3: Нов примерен поток от задачи за сценарий със споделени микроуслуги: 1) агентът генерира съобщение, което пристига в темата източник Kafka; 2) микроуслуга със споделено състояние (използвайки Kafka Streams) го обработва и записва изчисленото състояние в крайната Kafka тема; след което 3) потребителите приемат новото състояние

Хей, това вградено хранилище за ключ-стойност всъщност е много полезно!

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

Опция №1: Използвайте хранилище ключ-стойност за изчисления

Първото ни хранилище за ключ-стойност съдържаше спомагателните данни, необходими за изчисленията. Например в някои случаи споделеното състояние се определяше на принципа на "мнозинството гласове". Хранилището може да съдържа всички най-нови доклади на агенти за състоянието на даден обект. След това, когато получим нов отчет от един или друг агент, можем да го запазим, да извлечем отчети от всички други агенти за състоянието на същия обект от хранилището и да повторим изчислението.
Фигура 4 по-долу показва как изложихме хранилището за ключ/стойност на метода на обработка на процесора, така че новото съобщение да може да бъде обработено.

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Илюстрация 4: Отваряме достъп до хранилището на ключ-стойност за метода на обработка на процесора (след това всеки скрипт, който работи със споделено състояние, трябва да имплементира метода doProcess)

Опция №2: Създаване на CRUD API върху Kafka Streams

След като установихме нашия основен поток от задачи, започнахме да се опитваме да напишем RESTful CRUD API за нашите микроуслуги със споделено състояние. Искахме да можем да извличаме състоянието на някои или всички обекти, както и да задаваме или премахваме състоянието на обект (полезно за поддръжка на бекенда).

За да поддържаме всички API за получаване на състояние, винаги когато трябваше да преизчислим състоянието по време на обработка, ние го съхранявахме във вградено хранилище за ключ-стойност за дълго време. В този случай става доста лесно да се приложи такъв API с помощта на един екземпляр на Kafka Streams, както е показано в списъка по-долу:

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Фигура 5: Използване на вграденото хранилище за ключ-стойност за получаване на предварително изчисленото състояние на обект

Актуализирането на състоянието на обект чрез API също е лесно за изпълнение. По принцип всичко, което трябва да направите, е да създадете продуцент на Kafka и да го използвате, за да направите запис, който съдържа новото състояние. Това гарантира, че всички съобщения, генерирани чрез API, ще бъдат обработени по същия начин като тези, получени от други производители (напр. агенти).

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Фигура 6: Можете да зададете състоянието на обект с помощта на производителя на Kafka

Малко усложнение: Кафка има много дялове

След това искахме да разпределим натоварването на обработката и да подобрим наличността, като предоставим клъстер от микроуслуги със споделено състояние за всеки сценарий. Настройката беше лека: след като конфигурирахме всички екземпляри да работят под един и същ идентификатор на приложение (и същите сървъри за стартиране), почти всичко останало беше направено автоматично. Също така уточнихме, че всяка тема на източника ще се състои от няколко дяла, така че на всеки екземпляр да може да бъде присвоено подмножество от такива дялове.

Ще спомена също, че е обичайна практика да се направи резервно копие на държавното хранилище, така че, например, в случай на възстановяване след повреда, да прехвърлите това копие в друг екземпляр. За всяко хранилище на състояние в Kafka Streams се създава репликирана тема с регистър на промените (който проследява локалните актуализации). Така Кафка непрекъснато подкрепя държавния магазин. Следователно, в случай на повреда на един или друг екземпляр на Kafka Streams, състоянието на хранилището може бързо да бъде възстановено на друг екземпляр, където ще отидат съответните дялове. Нашите тестове показаха, че това става за няколко секунди, дори ако в магазина има милиони записи.

Преминавайки от единична микроуслуга със споделено състояние към клъстер от микроуслуги, внедряването на Get State API става по-малко тривиално. В новата ситуация хранилището на състоянието на всяка микроуслуга съдържа само част от цялостната картина (тези обекти, чиито ключове са картографирани към конкретен дял). Трябваше да определим кой екземпляр съдържа състоянието на обекта, от който се нуждаехме, и направихме това въз основа на метаданните на нишката, както е показано по-долу:

Не само обработка: Как направихме разпределена база данни от Kafka Streams и какво се получи от това

Фигура 7: Използвайки метаданни на потока, ние определяме от коя инстанция да направим запитване за състоянието на желания обект; подобен подход беше използван с GET ALL API

Основни констатации

Държавните магазини в Kafka Streams могат да служат като де факто разпределена база данни,

  • непрекъснато репликиран в Кафка
  • CRUD API може лесно да бъде изграден върху такава система
  • Работата с множество дялове е малко по-сложна
  • Също така е възможно да добавите едно или повече хранилища на състояние към стрийминг топологията за съхраняване на спомагателни данни. Тази опция може да се използва за:
  • Дългосрочно съхранение на данни, необходими за изчисления по време на обработка на потока
  • Дългосрочно съхранение на данни, които могат да бъдат полезни при следващото предоставяне на стрийминг екземпляра
  • много повече...

Тези и други предимства правят Kafka Streams много подходящи за поддържане на глобално състояние в разпределена система като нашата. Kafka Streams доказа, че е много надежден в производството (нямаме практически никакви загуби на съобщения, откакто го внедрихме) и сме уверени, че неговите възможности няма да спрат дотук!

Източник: www.habr.com

Добавяне на нов коментар