Online tárolás gyors skálázása több mint egymilliárd ChatGPT‑felhasználó számára (II. rész)
Így optimalizáltuk az Azure Cosmos DB-t a Habitat alkalmazásadat-tárolási platformunkban, hogy kezelni tudjuk a példátlan növekedést.
Minden OpenAI-terméknek gyors, megbízható adatelérésre van szüksége, amelyet tárolási platformunk, a Habitat biztosít. Több mint egymilliárd felhasználónak kell ezredmásodperceken belül válaszolnia, 40 földrajzi régióban. Infrastruktúránk rendkívüli kihívással nézett szembe: támogatnia kellett a robbanásszerű növekedést és az új felhasználási eseteket, miközben folyamatosan javítottuk a megbízhatóságot, a teljesítményt és a termékfejlesztés sebességét. Ehhez újra kellett gondolnunk online tárolási platformunk felépítését és üzemeltetését. Folyamatosan mérlegeltük a kompromisszumokat, ezt a sorrendet követve: először legyünk elég megbízhatóak a kritikus termékforgalomhoz, aztán elég gyorsak a globális felhasználói körnek, végül pedig működjünk hatékonyan óriási léptékben.
Ez a kétrészes sorozat bemutatja, hogyan fejlesztettük a Habitatot egyszerű klienskönyvtárból és adatbázisból több mint 500 petabájtnyi adatot kiszolgáló, globálisan elosztott tárolási platformmá. Az I. rész azt mutatta be, hogyan fejlődött a Habitat Python-kliensből szolgáltatássá. Kitért azokra a technikákra is, amelyekkel messze túljutottunk azon, amit sokan egy Python-alapú szolgáltatás észszerű határának tartanának.
Ebben a bejegyzésben, a II. részben az alapul szolgáló tárolási komponens, az Azure Cosmos DB skálázását mutatjuk be. Az Azure csapatával szorosan együttműködve működőképes, több-bérlős megoldást alakítottunk ki közösen felügyelt tárolókkal, amely óriási, globális léptékben is kiváló olvasási teljesítményt nyújt.
01. ábra · Mi az a Habitat?
Online tárolási platform
A Habitat az az online tárolási platform, amelyet azért építettünk, hogy az OpenAI termékei gyorsan és megbízhatóan hozzáférjenek a szükséges információkhoz.
- Kérés
- Válasz
- Változások (CDC)
A vállalatok növekedésével az infrastruktúra-csapatok gyakran egybérlős rendszerekről több-bérlős rendszerek üzemeltetésére térnek át. Az egybérlős működésben minden termékterület csapata saját rendszert tart fenn. Ez korlátozza a hibák hatókörét, egyértelmű felelősségi határokat teremt, és elkülöníti a munkaterheléseket. A csapatok és a termékterületek bővülésével azonban ez költségessé válik. Az egybérlős működés minden termékcsapatot felelőssé tesz a kapacitástervezésért, és gyakran jelentős túlméretezéshez vezet.
Ezzel szemben a több-bérlős működésben egy központi adatbázis-csapat irányít, amely több tudással és tapasztalattal rendelkezik az erőforrások kiosztásában. A több-bérlős működésnek viszont saját problémái vannak, például a zajos szomszédok: ilyenkor az egyik bérlő szokatlanul nagy részt fogyaszt az erőforrásokból a többiek rovására.
A Habitatnál mindezeket a kompromisszumokat mérlegelnünk kellett ahhoz, hogy nagy léptékben is megbízható, hatékony tárolási rendszert tervezzünk. Ma a Habitat számos OpenAI-termék több-bérlős adatbázisrétege, de ehhez egy kört tettünk meg: egyetlen több-bérlős Azure Cosmos DB-tárolóból indultunk, majd egybérlős háttértárolókat hoztunk létre, végül alapértelmezésként visszatértünk a több-bérlős tárolóhoz. A Habitat több-bérlős története még csak most kezdődik. Sokféle felhasználási esetet támogatunk, de az Azure Cosmos DB beépített alapelemeinek kihasználásával eddig el tudtuk halasztani az erre a területre fordítandó fejlesztéseket.
Mielőtt bemutatnánk az Azure Cosmos DB-vel megtett utunkat, néhány alapvetés:
Egy Azure Cosmos DB-fiók tárolók egy csoportját és egy replikációs szabályzatot határoz meg
Minden tárolóhoz meghatározott mennyiségű adatátviteli egységet foglalunk le, másodpercenkénti kérésegységben (RU/s) megadva
Az egyes tárolók adatai a szokásos módon, megadott logikai partíciókulcs alapján darabolva tárolódnak; a tárhely és az adatátviteli egységek korlátai logikai partíciókulcsonként dokumentáltak
Az Azure Cosmos DB a logikai partíciókulcsokat kevesebb háttérbeli fizikai partíció között osztja el. Ezeket több fizikai partícióra bontja, ha a tárhelyhasználat túllép egy küszöböt, vagy ha a lefoglalt adatátviteli egységek biztosításához több fizikai partícióra van szükség
Eredetileg minden kliensoldali terhelést átengedtünk, és a logikai partíciókulcsonként megadott 10 E RU/s korlátra bíztuk a bejövő terhelés visszafogását. Kezdetben fiókonként egyetlen alapértelmezett Azure Cosmos DB-tárolót használtunk. Ez elég jól működött, de több okból is problémásnak bizonyult:
Korai API-tervezési döntéseink miatt a logikai partíciókulcs kiválasztását közvetlenül a kliensekre bíztuk. Emiatt a gyakran használt partíciókulcsoknál, például a user_id vagy a workspace_id esetében rendszeresek az ütközések a különböző termékhasználati esetek között. Mivel ezekre ugyanazon logikai partíciókulcsok közös Azure Cosmos DB-korlátai vonatkoztak, a kialakítás korlátozta az egy felhasználó számára összesen elérhető adatátviteli egységeket.
A Habitat és az Azure Cosmos DB előtti időszakban a Postgres skálázásának gyakori problémája volt, hogy egy kiugró forgalmú szervezettől vagy kulcshoz érkező sok kérés – vagyis egyetlen, aránytalanul nagy terhelést generáló bérlő – az egész adatbázist leállíthatta. Jelentős közös munkát fordítottunk e kulcsok gyorsítótárazására és a gyorsítótár-melléfogásokhoz kapcsolódó bérleti mechanizmusok beépítésére, hogy a melléfogásokból eredő terhelés ne terhelje túl a mögöttes adatbázist.
Figure 02a · Logical partition key limits
Different clients, the same partition key
Bár a dokumentált adatméret- és adatátviteliegység-korlátok a logikai partíciókulcsokra vonatkoznak, a korlátok ténylegesen a fizikai partíció szintjén érvényesülnek. A gyakorlatban ez azt jelenti, hogy a logikai partíciók nem tudják elérni a 10 000 RU/s értéket. Ehelyett a fizikai partíció keretén osztoznak az ugyanott elhelyezett összes többi logikai partíciókulccsal.
Emiatt a zajos szomszédok sok, egymástól független logikai partíciókulcsra is hatottak: a szűk körben használt termékfunkciók adatain végzett feladatok megzavarták az alapvető bejelentkezési és regisztrációs folyamatokat.
Figure 02b · Noisy neighbors
Different users, the same physical partition
Egy adott fizikai partíció adatátviteliegység-korlátja is változó: az Azure Cosmos DB-tárolóhoz rendelt összes adatátviteli egységtől függ. A tárolóhoz lefoglalt adatátviteli egységek nagyjából egyenletesen oszlanak meg a tároló fizikai partíciói között.
Az adatmennyiség növekedésével a fizikai partíciók szétválnak, így nő a partíciók száma, miközben a lefoglalt adatátviteli egységek összmennyisége változatlan marad. Emiatt az adatméret növekedésével csökken a partíciónként ténylegesen elérhető adatátviteli egységek felső határa.
A legnagyobb tárhelyigényű, blobszerű adatokat kezelő felhasználási esetekben ez olyan hibához vezethet, amelynél önmagában a tárhelyhasználat növekedése csökkenti az aktív munkaterhelésekhez elérhető adatátviteli egységeket, miközben a kérések gyakorisága és a használat változatlan.
Figure 02C · Weak partitions
The limit falls below demand
A partition splits when it reaches its storage limit. Each child receives half the throughput capacity.
A külön tárolók részben megoldják a partíciókulcsok korlátait és a zajos szomszédok problémáját. Külön tárolók esetén mindegyik saját, független fizikai partíciókat kaphat. Így csak az adott tárolón belüli munkaterhelések válhatnak zajos szomszédokká, vagy fedhetik át egymást a partíciókulcsok terében. Hátrány viszont, hogy az új tárolók létrehozása többletmunkával jár: mindegyikhez külön kapacitástervezés kell. Ezért csak indokolt szolgáltatási vagy felhasználási határok mentén szeretnénk tárolókat létrehozni.
A legkritikusabb, erős elkülönítést igénylő új felhasználási esetekhez külön Azure Cosmos DB-tárolókat kezdtünk használni. Ezt egy, a gyenge partíciókat kezelő szkripttel egészítettük ki, amely az egyes tárolókhoz lefoglalt összes adatátviteli egységet a fizikai partícióik számához igazította. Így nagyrészt elkerültük a korábbi problémákat.
Mivel azonban egy alapértelmezett tárolóval indultunk, sok régi, kritikus felhasználási eset sajnos adatmigráció nélkül ott ragadt. A megosztott alapértelmezett tároló adataira épülő kritikus szolgáltatások védelmében gyakran azt tanácsoltuk a csapatoknak, hogy az új szolgáltatásokhoz vagy jelentősebb termékfunkciókhoz hozzanak létre külön tárolókat. A rendszer növekedésével nőtt az alapértelmezett tároló terhelése és az éles üzemi incidensek száma is. Minden új szolgáltatáshoz és nagyobb termékfunkcióhoz külön tárolót kezdtünk létrehozni, pusztán azért, hogy megóvjuk az alapértelmezett tárolót a további terheléstől.
Ez sok, a teljes rendszert érintő leállástól megóvott minket: a hibák hatása az egyes funkciók vagy szolgáltatások működési zavaraira korlátozódott. Az új tárolók létrehozásával járó többletmunka azonban idővel megbosszulta magát:
A régi, megosztott alapértelmezett tárolóban egy új felhasználási eset 0-ról 1 millió QPS-re növekedése valószínűleg nem változtatta meg jelentősen az összesített használatot. Egy elkülönített tárolóban viszont ugyanez akár 1000-szeres terhelést is jelenthetett a kizárólag belső termékhasználatból származó alapértékhez képest.
A dedikált tárolóknál a csapatoknak már előre gondoskodniuk kellett a bevezetéskor várható adatátviteli egységek lefoglalásáról. A termékcsapatok gyakran élesítették a funkcióikat, de elfelejtették előre bővíteni a kapacitást. Mi pedig a bevezetés napján incidenskezelő megbeszéléseken próbáltuk az utolsó pillanatban felskálázni a tárolókat.
A különféle munkaterhelések kiegyenlítő hatása a több-bérlős rendszerek alapvető előnye. Erről mondunk le a jobb elkülönítésért ezzel a tárolási stratégiával.
Figure 03 · Lack of stable aggregate growth
The same workload, different headroom
1K RU/s during load testing → 1M RU/s at launch
Idővel a dedikált tárolók használatának figyeléséhez is alapos termékismeret kellett: tudni kellett, mikor változik vagy nő a forgalom.
Egy egyszerű vezérlősík-szkripttel a növekedési trendek alapján bővíthetjük az egyes tárolókhoz lefoglalt adatátviteli egységeket. Az egyenletes összesített növekedés hiányában azonban a helyes skálázás lényegében az OpenAI minden termékcsapatát bevonta a kapacitástervezésbe.
Ez szervezeti szinten nem volt skálázható: nagyon eltérő volt, hogy az egyes szolgáltatásokért felelős csapatok mennyi figyelmet fordítottak az Azure Cosmos DB erőforrásainak kiosztására.
A szervezet növekedésével egyre nehezebb lett kezelni ezeket az üzemeltetési problémákat. Egyetlen központi tervezőcsapat hiányában sok csapat rosszul tervezett. Ezért végül visszatértünk a több-bérlős megoldás felé, és az Azure csapatával szorosan együttműködve, közös erőforrásokat használó kialakítással oldottuk meg az eredeti problémákat:
Ha először a legnagyobb forgalmú kulcsokat korlátozzuk, a zajos szomszédok nem fogyaszthatják el az adott fizikai partíció összes elérhető adatátviteli egységét. Ez mérsékli a zajos szomszédok hatását, amely miatt egyetlen túlterhelt kulcs az egész rendszerre kiható zavart okozhat.
A kéréseket osztályokba soroló QoS hasonlóan megakadályozza, hogy az offline munkaterhelések, például a tömeges beszúrások vagy adatkivonatok, felhasználják egy fizikai partíció összes adatátviteli egységét. E munkaterhelések kérései alacsonyabb prioritást kapnak, így először ezeket korlátozzuk. Ezzel elkerülhető a végfelhasználókat kiszolgáló, magasabb prioritású interaktív kérések korlátozása.
Az Azure Cosmos DB-nek már volt kiszolgáló nélküli módja, amely megoldotta volna a lefoglalt kapacitású módban tapasztalt gyenge partíciók problémáját. Ennek azonban volt egy komoly hátránya: csak a tárhelyhasználat alapján skálázott, az RU-használatot pedig fizikai partíciónként 5 E RU/s-ra korlátozta. Ez megoldotta volna a gyenge partíciók problémáját, de megakadályozta volna az RU-igényes felhasználási esetek felskálázását.
Az Azure Cosmos DB csapata egy továbbfejlesztett kiszolgáló nélküli módot készített nekünk. Ez minden fizikai partíciót 10 E RU/s-ig engedett skálázni, és a tárhelyhasználat mellett az RU-használat alapján is lehetővé tette a szétválást. Így felhagyhattunk a tárolók kézi felügyeletével és bővítésével.
E változtatásokkal visszatérhettünk egyetlen megosztott tárolóhoz. Ez jelentősen egyszerűsítette a termékcsapatok előzetes és folyamatos kapacitástervezését, miközben megőrizte a munkaterhelések elkülönítését. Az azóta eltelt hónapokban nem volt erőforrás-kiosztással vagy zajos szomszédokkal kapcsolatos incidensünk, pedig a termékfejlesztés tovább gyorsult.
Amikor egy vállalat eléri az OpenAI méretét, a felügyelt szolgáltatások kevésbé lesznek „felügyeltek”. Sok munkaterhelés kilóg a felhőszolgáltató infrastruktúrájának szokásos használati mintáiból. Ahogy az OpenAI az Azure Cosmos DB egyik legnagyobb felhasználójává vált, a sikeres üzemeltetés új működési módot igényelt: közös teszteket és irányítópultokat, közvetlen mérnöki kommunikációt, valamint közös felelősségvállalást a csak a mi léptékünkben jelentkező hibákért. Ma a legnagyobb Azure Cosmos DB-fiókunk több tíz petabájtnyi adatot tárol, és több mint 20 millió QPS-t szolgál ki. Tudomásunk szerint mi vagyunk az egyetlen vállalat, amely ilyen léptékben használja az Azure Cosmos DB-t.
2024 végén egy regionális leállás egyértelművé tette, miért szükséges ez az együttműködés. Ekkor áramszünet érte az egyik legnagyobb Azure Cosmos DB-fiókunk elsődleges Azure-régióját. Az ezt követő feladatátvétel során kiderült, hogy a legnagyobb fiókjaink másodlagos régióba történő átállása több órát igényelne. Ezt sem mi, sem az Azure Cosmos DB csapata nem tesztelte korábban a mi léptékünkben.
Nagyjából egy hónappal később, amikor ezeket a fiókokat visszaállítottuk az eredeti régióba, újabb súlyos leállást idéztünk elő. Az eredeti régióra zúduló kapcsolódási hullám túlterhelte az ottani Azure Cosmos DB-átjárót. Az átjáró módban működő Azure Cosmos DB-kliens feladatátvétel-kezelésének egy sajátossága miatt minden kliens azonnal kapcsolatot létesített az eredeti régióval, és oda küldte a kéréseit, noha a fizikai partícióknak még csak egy része került vissza oda.
Mindkét leállásnál az OpenAI és az Azure is végigvitte az incidenskezelési folyamatát, több kiváltó okot azonosított, és javításokat vezetett be. Ezek a leállások azonban egy mélyebb, rendszerszintű problémát jeleztek a mi csapatunk és az Azure Cosmos DB csapatának üzemeltetési és tesztelési gyakorlatában. Kezdetben a felügyelt szolgáltatások lehetővé tették, hogy gyorsan haladjunk, és az üzleti célokra összpontosítsunk. Nagy léptékben viszont ezek a szolgáltatások kevésbé felügyeltek, és a tervezéstől az üzemeltetésig minden szinten szoros integrációt igényelnek a szolgáltatóval.
Ma a Habitat és az Azure mérnökcsapatai közösen figyelik a Habitat minden rétegét, a szolgáltatási rétegeinktől az Azure Cosmos DB fizikai tárolási rétegeiig. Egy éles méretű, de nem éles üzemben működő Azure Cosmos DB-fiókot üzemeltetünk, és azon teszteljük a változtatásokat. Közösen teszteljük és fejlesztjük az SDK-kat, valamint meghatározzuk az Azure Cosmos DB-fiókjaink skálázásának és méretezésének bevált gyakorlatait. A Teamsen közvetlenül elérjük egymás mérnökeit, sőt közvetlen ügyeleti riasztásra is lehetőséget adtunk egymásnak, a támogatási szintek megkerülésével.
Az elmúlt évben jelentős közös munkával javítottuk az Azure Cosmos DB vezérlősíkjának és átjárójának skálázhatóságát. Az átjáróba túlterhelés elleni védelmet és különféle Azure Cosmos DB-metaadatok gyorsítótárazását építettük be a metaadat-partíció védelmére. Kapcsolatkészletekkel és a kapcsolatok gyakoribb újrafelhasználásával csökkentettük a Python-alapú habitat-service folyamataink okozta terhelést, ahol lehetett, egy helyre telepítettük a munkaterheléseket, a kritikus munkaterheléseket pedig külön VPC-kkel választottuk el az offline feladatoktól.
Ez a szoros mérnöki együttműködés kulcsfontosságú volt az Azure Cosmos DB stabilitásának megőrzéséhez az elmúlt évben. Minden kellően nagy vagy kritikus rendszer ilyen csapatmunkát igényel: le kell bontani a felelősségi körök közötti falakat, és a szervezeti határokon átívelve kell együtt dolgozni.
Ahogy az I. részben említettük, alapelvünk: előbb működjön, aztán legyen gyors, végül legyen olcsó. Először a megbízhatóság, aztán a teljesítmény, végül a hatékonyság. A Habitat az OpenAI kritikus infrastruktúrájává vált, ezért elsőként a megbízhatóságát kellett biztosítani. Ahogy 2025-ben stabilizálódott a rendszer, és az OpenAI világszerte terjeszkedett, a késleltetés vált a következő szűk keresztmetszetté a felhasználók és a termékcsapatok számára.
A számítási és tárolási kapacitás gyakran eltérő régiókban helyezkedett el, így elkerülhetetlenek voltak a régiók közötti kérések.
Figure 04 · Improving performance at a global scale
Global traffic
Compute and storage capacity were often located in different regions, making cross-region requests unavoidable.
A számítási és tárolási erőforrások földrajzi helyei csak szemléltető jellegűek.
A késleltetés nagymértékben függött attól, hol tároltuk az adatokat, és hol szolgáltuk ki a kérést. A Habitat-kérések felgyorsításához a termékfejlesztők további kliensoldali gyorsítótárazást és kötegelt kéréseket alkalmaztak, minimalizálták az adatbázis-olvasásokat és -írásokat, és ahol lehetett, kivették a munkát a kritikus végrehajtási útvonalból. Ez ugyan érdekes, az adatbázishibáknak jobban ellenálló termékmegoldásokat eredményezett, de bonyolultabbá tette a termékeket, és lassította a fejlesztési ciklusokat. Így nem teljesült a Habitat célja: gyors termékfejlesztést biztosítani anélkül, hogy a fejlesztőknek ismerniük kellene az adatbázis működését.
2026-ban kiemelt figyelmet fordítunk erre, és többrétegű stratégiát dolgoztunk ki a Habitat-kérések több mint 90%-át kitevő olvasások teljesítményének optimalizálására:
Világszerte több Azure-régióban működtetünk Azure Cosmos DB-fiókokat azoknak a felhasználóknak, akiknél követelmények vonatkoznak az adatok tárolási helyére. Az adatok felhasználókhoz közeli elhelyezése az alacsonyabb késleltetés révén akkor is javítja a felhasználói élményt, ha nincsenek szigorú előírások az adatok tárolási helyére.
A gyakorlatban ezt nem tudjuk széles körben megvalósítani az adatok tárolási helyére vonatkozó követelményekkel érintett eseteken túl, mert az elhelyezést korlátozza a felhő fizikai kapacitása. Adatkészleteink mérete miatt sok régió nem tudja biztosítani a rá eső felhasználói forgalomhoz szükséges hatalmas tárhelyet.
A korlátozott adatközponti kapacitással, áramellátással vagy hűtéssel rendelkező régiókban néha választanunk kell: helyi tárolásra foglaljuk le a kapacitást, csökkentve a Habitat késleltetését, vagy további kiszolgáló számítási kapacitásra használjuk, és távolabbra irányítjuk a tárolási kéréseket.
Az elhelyezési döntések ezért gyakran termékszintű kompromisszumot jelentenek A) a különböző termékek és felhasználói csoportok késleltetésének optimalizálása és B) a rendelkezésre álló tárolási és számítási kapacitás között.
A késleltetés szempontjából legkritikusabb munkaterheléseknél, például a minden kéréshez szükséges hitelesítési metaadatoknál, sok másodlagos régióba replikáló Azure Cosmos DB-fiókokkal csökkentjük a számítási környezet és a Habitat közötti oda-vissza út idejét (RTT). Egyes fiókok mind a 40 olyan Azure-régióba replikálnak, ahol forgalmat szolgálunk ki; mások kontinensenként legalább egy régióba.
A tervezettnél korábban kellett egy transzparens adatmozgatási és útválasztási réteget beépítenünk a Habitatba, hogy eltérő replikációs topológiájú fiókok között mozgathassuk az adatkészleteket.
Végső soron azonban ezt a megközelítést is korlátozza a kapacitás, ezért csak néhány gondosan kiválasztott adatkészletre alkalmazzuk.
A Habitat munkaterheléseiben döntő többségben vannak az olvasások: az alkalmazások folyamatosan beállításokat, állapotadatokat és más tulajdonságokat kérnek le. A forgalom aránytalanul nagy részét a gyakran elért típusok viszonylag kis aktív adatkészlete adja. Ez különösen alkalmassá teszi a rendszert az elosztott gyorsítótárazásra. A gyorsítótárazás már egyetlen régión belül is javítja a teljesítményt, de az előnye több régió esetén még nagyobb, mert „elrejtheti” a régiók közötti késleltetést.
Egy elosztott, oldalágon elért gyorsítótárréteget építettünk a Habitatba. Ez a nemrég elért objektumok és élek másolatát tárolja az infrastruktúránk olyan Valkey-kiszolgálóin, amelyek a felhasználói kérések feldolgozási helyéhez közel találhatók. Az ilyen gyorsítótárak jellemzően élettartamot (TTL) használnak, amely kompromisszumot teremt a találati arány és az adatok elavultsága között. A rövid TTL csökkenti az elavultságot, de mérsékli a gyorsítótárazás előnyét is, mert az elemek hamar lejárnak, és gyakrabban kell újra lekérni őket. A hosszabb TTL javítja a találati arányt, de hosszabb ideig szolgál ki elavult adatokat, ami rossz felhasználói élményhez és kiszámíthatatlan termékműködéshez vezet.
Másik megoldásként explicit érvénytelenítési műveleteket végezhetünk, amikor az alkalmazás ugyanazokat a mögöttes adatokat írja. Ez jelentősen javítja a gyorsítótárazott adatok frissességét, de nehéz lehet helyesen megvalósítani. Ráadásul továbbra is előfordulhatnak olyan szélső esetek, például részleges hibák, amelyek elavultan hagyják a gyorsítótárat. A több régiós telepítés súlyosbítja ezeket a gondokat: a régiók közötti hálózat kevésbé megbízható, a gyorsítótár és a mögöttes tároló replikációja között pedig versenyhelyzet alakulhat ki. TTL-lel kiegészítve korlátozható az elavultság maximális ideje, de a fent leírt alapvető kompromisszum így is megmarad.
Mi fejlettebb érvénytelenítési megoldást választottunk, olyan rendszerek példáját követve, mint a Meta TAO-ja. A Habitat integrált gyorsítótára az Azure Cosmos DB változáscsatornáján keresztüli adatváltozás-rögzítésre (CDC) épít. Így az érvénytelenítések másodperceken belül világszerte eljutnak a gyorsítótárakhoz, magas találati arányt és csekély elavultságot biztosítva. Infrastruktúránk egyik szolgáltatása feldolgozza ezt a változáscsatornát, és a mögöttes adatok frissítésekor érvényteleníti a helyi gyorsítótárak megfelelő bejegyzéseit. Ez a következő olvasáskor gyorsítótár-melléfogást eredményez, és a gyorsítótárba az adatok legfrissebb változata kerül.
A Habitat szolgáltatás saját többletterhelését is lefaragtuk, jelentősen csökkentve a késleltetést: az eredeti Python-kódot jobb teljesítményt nyújtó Rustban írtuk újra.
E változtatások együttesen körülbelül 120 ms-ról 10 ms-ra csökkentették a globális olvasások összesített p50 késleltetését. Ez 12-szeres javulás azóta, hogy az év elején a teljesítményre kezdtünk összpontosítani.
Figure 05 · Improving performance at a global scale
p50 latency for reads
Three major design changes improved read latency
Bár a gyorsítótárazás jelentősen csökkentette a medián késleltetést, a leglassabb kérésekhez továbbra is a mögöttes tárolóból kell lekérni a nem gyorsítótárazott adatokat, gyakran távoli régiókból. Ahogy új kapacitásokat állítunk üzembe és javítjuk a tárolás hatékonyságát, egy alapvetőbb kihívást is meg kívánunk oldani: az adatokat már eleve közelebb helyezni ahhoz, ahonnan majd elérik őket.
A megbízható, skálázható CDC – az adatbázis változásainak továbbítása a rá épülő rendszerekhez – nemcsak a Habitat gyorsítótárazási stratégiájában kritikus. Tárolók ezreiből és tárolópartíciók millióiból másodpercenként több millió rögzített változás áramlik át több mint száz Kafka-témán. Ezek táplálják az idővel konzisztenssé váló másodlagos indexeket, az adatmozgatási folyamatokat, az offline elemzéseket és más valós idejű termékfunkciókat is. Ahogy háttér-infrastruktúránk világszerte bővült, egyre bonyolultabbá vált a sorok változásainak figyelése. Ha egy kliens visszahívást szeretne regisztrálni a saját típusához tartozó sorok változásaira, előbb többek között meg kell határoznia, mely Cosmos-fiókok és tárolók tartalmazzák az adatait, és mely CDC-telepítések figyelik ezeket az adott régiókban. Emellett megfelelően kell méreteznie a CDC feldolgozófolyamatainak állományát, a Kafkát és a saját fogyasztóját. CDC-platformunk célja, hogy mindezt elrejtse a termékfejlesztők elől. Ehelyett egyszerű felületet ad: a kliensek regisztrálják a módosult sorokhoz meghívandó függvényt, mi pedig kezeljük a teljes háttérműködést és skálázást.
Egy belső vezérlősík folyamatosan biztosítja az összes szükséges tároló változásainak rögzítését, kiválasztja az olvasáshoz használt Cosmos-régiókat, és hatékonyan elosztja a munkát több földrajzi régió feldolgozófolyamatainak ezrei között. A replikarégiók és az alacsonyabb prioritású változáscsatorna-olvasások védik a késleltetésre érzékeny Habitat-forgalmat a háttérben zajló rögzítési munkaterhelésektől. Ekkora állományban folyamatosan előfordulnak feldolgozófolyamat-összeomlások, tárolóhibák, a bérleteket nyilvántartó tár hibái, érvénytelen konfigurációk és célrendszerhibák. Robusztusabbá tettük a CDC-feldolgozók életciklus- és bérletkezelését, elszigeteltük az adatfolyamok hibáit, és védelmi mechanizmusokat építettünk a konfigurációmódosítások és bevezetések köré. A kézbesíthetetlen üzeneteket külön várólistákba helyezzük, hogy a tartós kézbesítési hibák ne akasszák meg a sorban mögöttük álló elemek feldolgozását. A regionális leállásokat úgy kezeljük, hogy az olvasókat más Cosmos-régiókra állítjuk át. A mi léptékünkben még az Azure CDC SDK-ját is módosítanunk kellett az ellenőrzőpont-kezelés hatékonysága érdekében: az ellenőrzőpontokat memóriában kötegeljük, és csak időszakosan írjuk ki.
Bár a Habitat összetett módon használja az Azure Cosmos DB-t, értéke mindig abban rejlett, hogy az infrastruktúra részleteit elrejti a termékfejlesztők elől, felgyorsítva a fejlesztést. CDC-platformunk is ugyanezt teszi.
Egy kis csapat is képes volt támogatni egy gyorsan növekvő tárolási platformot azzal, hogy tudatosan szűken tartotta a tárolási API-t, folyamatosan skálázta a Python-szolgáltatást, és a legsürgetőbb mérnöki kihívásoknak adott elsőbbséget. Először a kritikus termékforgalom megbízható kiszolgálására, majd a globális felhasználói kör olvasási teljesítményére, végül a nagy léptékű üzemeltetés hatékonyságára összpontosítottunk. Ez a megközelítés gyors növekedést és új felhasználási eseteket tett lehetővé, miközben javult a megbízhatóság, a teljesítmény és a termékfejlesztés sebessége.
Ahhoz, hogy a Habitat és a beszélgetéstárolás a következő egymilliárd felhasználót is kiszolgálja, még nagyobb léptékben kell megoldanunk az adatok infrastruktúránkon átívelő replikálásának nehézségeit. Erre felkészülve saját, exabájtos léptékű online tárolási rendszert fejlesztünk, a Habitat nagy méretű adattípusaira optimalizálva. Ez a fejlesztés alatt álló rendszer a Rockset RocksDB Cloud magját Raft-alapú replikációval ötvözi. Ugyanazt a dokumentummodellt valósítja meg, mint az Azure Cosmos DB, de különválasztott tárolással és fizikai replikációval csökkenti a szükséges flashkapacitást, alacsonyabb QPS-csúcsértékért cserébe.
Ha szívesen dolgoznál ilyen, élvonalbeli léptékű adatinfrastruktúra-fejlesztéseken, nézd meg nyitott pozícióinkat.


