Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

Szia Habr!

Emlékeztetünk arra, hogy a könyv nyomán kb Kafka ugyanilyen érdekes munkát adtunk ki a könyvtárról Kafka Streams API.

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

A közösség egyelőre csak tanulja ennek a hatékony eszköznek a korlátait. Nemrég tehát megjelent egy cikk, aminek a fordítását szeretnénk bemutatni. A szerző saját tapasztalatai alapján elmondja, hogyan lehet a Kafka Streams-et elosztott adattárolóvá alakítani. Élvezd az olvasást!

Apache könyvtár Kafka-folyamok világszerte használják a vállalatoknál az Apache Kafka mellett elosztott adatfolyam-feldolgozáshoz. Ennek a keretrendszernek az egyik alulértékelt aspektusa, hogy lehetővé teszi a szálfeldolgozáson alapuló helyi állapotok tárolását.

Ebben a cikkben elmesélem, hogy cégünk hogyan tudta nyereségesen kihasználni ezt a lehetőséget egy felhőalkalmazás-biztonsági termék fejlesztése során. A Kafka Streams segítségével megosztott állapotú mikroszolgáltatásokat hoztunk létre, amelyek mindegyike hibatűrő és magasan elérhető megbízható információforrásként szolgál a rendszerben lévő objektumok állapotáról. Számunkra ez előrelépést jelent mind a megbízhatóság, mind a támogatás egyszerűsége tekintetében.

Ha érdekel egy alternatív megközelítés, amely lehetővé teszi, hogy egyetlen központi adatbázis segítségével támogassa objektumai formális állapotát, olvassa el, érdekes lesz...

Miért gondoltuk, hogy itt az ideje megváltoztatni a megosztott állapottal való munkamódszerünket?

Különböző objektumok állapotát ügynöki jelentések alapján kellett karbantartanunk (például: támadták-e a webhelyet)? A Kafka Streamsre való átállás előtt gyakran egyetlen központi adatbázisra (+ szolgáltatás API-ra) hagyatkoztunk az állapotkezeléshez. Ennek a megközelítésnek megvannak a maga hátrányai: randevúzási intenzív helyzetek a konzisztencia és a szinkronizálás igazi kihívássá válik. Az adatbázis szűk keresztmetszetté válhat, vagy bekerülhet verseny állapota és a kiszámíthatatlanságtól szenvednek.

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

1. ábra: Egy tipikus osztott állapotú forgatókönyv, amely a következőre való átállás előtt látható
Kafka és Kafka Streams: az ügynökök API-n keresztül közlik nézeteiket, a frissített állapotot egy központi adatbázis számítja ki

Ismerje meg a Kafka Streams szolgáltatást, amely megkönnyíti a megosztott állami mikroszolgáltatások létrehozását

Körülbelül egy éve úgy döntöttünk, hogy alaposan megvizsgáljuk közös állapotforgatókönyveinket, hogy megoldjuk ezeket a problémákat. Azonnal úgy döntöttünk, hogy kipróbáljuk a Kafka Streams-et – tudjuk, hogy mennyire méretezhető, magasan elérhető és hibatűrő, milyen gazdag streaming funkciókkal rendelkezik (transzformációk, beleértve az állapotalapúakat is). Pont amire szükségünk volt, arról nem is beszélve, hogy mennyire kiforrott és megbízható lett az üzenetküldő rendszer Kafkában.

Az általunk létrehozott állapotalapú mikroszolgáltatások mindegyike egy meglehetősen egyszerű topológiájú Kafka Streams példányra épült. Ez a következőkből állt: 1) egy forrás 2) egy processzor állandó kulcsérték tárolóval 3) egy nyelő:

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

2. ábra: Az állapotalapú mikroszolgáltatások adatfolyam-példányainak alapértelmezett topológiája. Vegye figyelembe, hogy itt is van egy tárhely, amely tervezési metaadatokat tartalmaz.

Ebben az új megközelítésben az ügynökök a forrástémába betáplált üzeneteket állítanak össze, a fogyasztók pedig – mondjuk egy levélértesítési szolgáltatás – a fogadón (kimeneti téma) keresztül megkapják a kiszámított megosztott állapotot.

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

3. ábra: Új példa feladatfolyamat megosztott mikroszolgáltatásokkal rendelkező forgatókönyvhöz: 1) az ügynök generál egy üzenetet, amely a Kafka-forrástémához érkezik; 2) egy megosztott állapotú mikroszolgáltatás (Kafka Streams használatával) feldolgozza és a számított állapotot a végső Kafka-témába írja; ami után 3) a fogyasztók elfogadják az új állapotot

Hé, ez a beépített kulcsérték-tár valójában nagyon hasznos!

Ahogy fentebb említettük, a megosztott állapottopológiánk kulcsérték-tárolót tartalmaz. Számos lehetőséget találtunk a használatára, ezek közül kettőt az alábbiakban ismertetünk.

1. lehetőség: Használjon kulcsérték-tárolót a számításokhoz

Első kulcs-érték tárolónk tartalmazta a számításokhoz szükséges segédadatokat. Például egyes esetekben a megosztott államot a „többségi szavazatok” elve határozta meg. A lerakat tárolhatja az összes legfrissebb ügynökjelentést bizonyos objektumok állapotáról. Ezután, amikor új jelentést kaptunk egyik vagy másik ügynöktől, elmenthettük, lekérhettük az összes többi ügynöktől ugyanazon objektum állapotáról szóló jelentéseket a tárhelyről, és megismételhettük a számítást.
Az alábbi 4. ábra bemutatja, hogyan tettük ki a kulcs/érték tárolót a processzor feldolgozási metódusának, hogy az új üzenet ezután feldolgozható legyen.

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

4. ábra: Megnyitjuk a hozzáférést a processzor feldolgozási metódusának kulcsérték tárolójához (ezt követően minden megosztott állapottal működő szkriptnek implementálnia kell a metódust doProcess)

2. lehetőség: CRUD API létrehozása a Kafka Streams tetején

Az alapvető feladatfolyamunk kialakítása után elkezdtünk egy RESTful CRUD API-t írni megosztott állapotú mikroszolgáltatásainkhoz. Azt akartuk, hogy lekérhessük néhány vagy az összes objektum állapotát, valamint beállítsuk vagy eltávolítsuk egy objektum állapotát (hasznos háttértámogatás esetén).

Az összes Get State API támogatása érdekében, amikor a feldolgozás során újra kellett számítanunk az állapotot, hosszú ideig egy beépített kulcsérték-tárolóban tároltuk. Ebben az esetben meglehetősen egyszerűvé válik egy ilyen API megvalósítása a Kafka Streams egyetlen példányával, amint az az alábbi listában látható:

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

5. ábra: A beépített kulcsérték tároló használata egy objektum előre kiszámított állapotának lekérésére

Egy objektum állapotának API-n keresztüli frissítése is könnyen megvalósítható. Alapvetően nem kell mást tennie, mint létrehozni egy Kafka producert, és elkészíteni vele egy olyan lemezt, amely tartalmazza az új állapotot. Ez biztosítja, hogy az API-n keresztül generált összes üzenetet ugyanúgy dolgozza fel, mint a többi előállítótól (pl. ügynököktől) kapott üzeneteket.

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

6. ábra: Egy objektum állapotát a Kafka producer segítségével állíthatja be

Kis bonyodalom: Kafkának sok partíciója van

Ezt követően meg akartuk osztani a feldolgozási terhelést, és javítani akartuk a rendelkezésre állást azáltal, hogy forgatókönyvenként megosztott állapotú mikroszolgáltatások fürtjét biztosítjuk. A telepítés gyerekjáték volt: miután beállítottuk az összes példányt, hogy ugyanazzal az alkalmazásazonosítóval (és ugyanazzal a bootstrap-kiszolgálóval) fussanak, szinte minden más automatikusan megtörtént. Azt is meghatároztuk, hogy minden forrástéma több partícióból álljon, így minden példányhoz hozzá lehet rendelni az ilyen partíciók egy részhalmazát.

Azt is megemlítem, hogy bevett gyakorlat biztonsági másolatot készíteni az állapottárolóról, hogy például hiba utáni helyreállítás esetén ezt a másolatot átvigye egy másik példányba. A Kafka Streams minden egyes állami boltjához egy replikált témakör jön létre változásnaplóval (amely nyomon követi a helyi frissítéseket). Így Kafka folyamatosan biztonsági másolatot készít az állami boltról. Ezért az egyik vagy másik Kafka Streams-példány meghibásodása esetén az állapottároló gyorsan visszaállítható egy másik példányon, ahová a megfelelő partíciók kerülnek. Tesztjeink azt mutatták, hogy ez pillanatok alatt megtörténik, még akkor is, ha több millió rekord van a boltban.

Egyetlen megosztott állapotú mikroszolgáltatásról mikroszolgáltatások fürtjére lépve kevésbé triviális lesz a Get State API megvalósítása. Az új helyzetben az egyes mikroszolgáltatások állapottárolója az összképnek csak egy részét tartalmazza (azokat az objektumokat, amelyek kulcsai egy adott partícióhoz lettek leképezve). Meg kellett határoznunk, hogy melyik példány tartalmazza a szükséges objektum állapotát, és ezt a szál metaadatai alapján tettük meg, az alábbiak szerint:

Nem csak feldolgozás: Hogyan készítettünk elosztott adatbázist a Kafka Streamsből, és mi lett belőle

7. ábra: Az adatfolyam metaadatainak felhasználásával meghatározzuk, hogy melyik példányból kérdezzük le a kívánt objektum állapotát; hasonló megközelítést alkalmaztak a GET ALL API-val

Fő megállapítások

A Kafka Streams állami üzletei de facto elosztott adatbázisként szolgálhatnak,

  • állandóan replikálják Kafkában
  • Egy CRUD API könnyen ráépíthető egy ilyen rendszerre
  • Több partíció kezelése kicsit bonyolultabb
  • Lehetőség van egy vagy több állapottároló hozzáadására is a streaming topológiához a kiegészítő adatok tárolására. Ez az opció a következőkhöz használható:
  • A számításokhoz szükséges adatok hosszú távú tárolása a folyamfeldolgozás során
  • Az adatok hosszú távú tárolása, amely hasznos lehet a streaming példány következő kiépítésekor
  • sokkal több...

Ezek és más előnyök miatt a Kafka Streams kiválóan alkalmas a globális állapot fenntartására egy olyan elosztott rendszerben, mint amilyen a miénk. A Kafka Streams nagyon megbízhatónak bizonyult a termelésben (gyakorlatilag nem volt üzenetvesztésünk a bevezetés óta), és bízunk benne, hogy képességei nem állnak meg itt!

Forrás: will.com

Hozzászólás