AppFabric Cache architektúra és alapfogalmak

(Bevezető)

A Windows Server AppFabric Cache egy explicit, eloszott, egységes, memóriabeli adat gyorsítótár.
(minden szó fontos! gondolkodjunk el rajta!)

Architektúra

veloarch

  • explicit-> én teszem be amit gyorsítani szeretnék, pl. rátesztelek hogy bent van e a chache-ben, ha nincs akkor beteszem….
    (vannak tervek úgymond read-through megoldásokra, amikor is én olvasok a chache-ből, és ha nincs benne akkor a cache oldja meg a cache-be hozatalt, pl. SQL-DB-ből)
  • eloszott-> tetszőleges fizikai gép (cache-node) kapcsolható a klaszterbe (cache-cluster), ezáltal skálázható (N gép 2gbyte-> N*2gbyte cache)
  • egységes-> nem kell foglalkozni a cluster fizikai mivoltjával, fentről nézve egységes a cache, vagyis bármelyik fizikai node-dal állok kapcsolatban ugyan úgy látom a cache-t, és hozzáférek mindenhez. A cluster miatti ügyeket a cache elrejti a programozó, a cache-kliens elől…
  • memóriabeli adat gyorsítótár-> memóriában tárolja a cache elemeket, nincs hdd,sql server, stb. kiirás. Adat alatt pedig bármit érthetünk: CLR objektumton át, byte[] adatokat, bármit ami szerializálható binárisan…

(Nem véletlen részleteztem ezeket így, fontos dolgok. Ezekből rengeteg minden következik, ha valamit hiányolunk, vagy valamit furcsának találunk ezekben megtalálhatjuk a magyarázatot.)

Miben más ez mint egyéb megoldások? Pl. van az ASP.Net-nek is cache megoldása?!? van de csak az adott kiszolgálón. Pl ha van egy webfarmunk, és egy adott kiszolgálón bekerül vanalmi a cache-be, akkor azt csak és kizárólag az a gép látja… Létezik továbbá olyan megoldás, hogy SQL serverbe perzisztáljuk az objektumokat, s így egy közös pontból elérheti mindenki által az adott objektumot. Pl. a 3.5-ös workflow-persistence szolgáltatásánál hasonló a helyzet: workflow services kiszolgálóból lehet N darab, de mind ugyan azt a pers. tárat használja, így bárhova érkezik be a kérés mindenki eléri a perzisztált workflow-t. (Persze ez nem cache, pusztán csak az elv az érdekes).
Ebben az esetben viszont az SQL server válik szűk keresztmetszetté… amit ugye nagyon nehéz skálázni…

Elhelyezkedés az architektúrában

(pl. egy hagyományos web-farm esetében:)

hol_legyen0

Az ábra érzékelteti, hogy normál esetben minden alkalmazás/kiszolgáló egyedileg kapcsolódik az adatbázishoz, közvetlenül ír-olvas belőle, ennek minden előnyével-hátrányával.

hol_legyen

A cache-réteg alkalmazása esetén az adatbázis és az alkalmazás réteg közé kerül az AppFabric cluster. Az alkalmazások normál esetben továbbra is kapcsolatban maradnak közvetlenül az erőforrások kiszolgálójával, kiszolgálóival ( a továbbiakban az erőforrás és az adatbázis/adattár fogalmakat keverve használom, mint ahogy írtam a cache-be bármilyen bináris adat bekerülhet, így pl. akár file gyorsításra is használható), de a cache-kliens-en keresztül a kapcsolatban áll a cluster-rel is. Ha nincs a cache-ben az adat (ez nagyon gyorsan kiderül, a későbbiekben részletezett módon), akkor felolvassa, majd beteszi a cache-be (és használja), és legközelebb már minden kliens eléri amikor szüksége van rá.

Adatok kategorizálása

Az előző bejegyzésben megfogalmazott követelmények alapján világosan látható hogy a különböző gyorsítandó erőforrásokkal szemben különböző követelmények állnak fent. Ezek koncepcionálisan megjelennek az egész AppFabric Cache architektúrában, így nagyon fontos hogy értsük és tisztában legyünk vele, továbbá fontos hogy egy saját megoldás implementálásakor ezt figyelembe vegyük, mind tervezéskor mind implementáláskor.
Vegyük sorba ezen kategóriákat!

types_of_data_webshop

  1. Referenciális jellegű adatok (Reference data)
    Magyarul katalógus-adatok. Tipikusan pl. termékkatalógusok statikus része: nevek, leírások, képek, stb.
    Jellemzők: elsősorban read-only, ritkán változik az adat, és ha változik, akkor se feltétlen okoz világméretű katasztrófát, ha a változásnak átfutása van…
    Elvárások: NAGYON gyors legyen (elérés-áteresztőképesség), ha kiesik a cache-ből valami, vagy kiesik egy node, akkor nem dől össze a világ.
  2. Aktivitás jellegű adat (Activity data)
    Pl. bevásárló-kosár, egy felhasználó/session adatai.
    Jellemzők: írandó-olvasandó adat, de nem megoszottan (nincs konkurencia és ebből fakadó katasztrofális következmény)
    Elvárások: atom-biztos legyen. ha kiesik egy node (legyen az a cache-cluster-ben, esetleg a webfarm-ban) akkor azt ne vegye észre az alkalmazás és a felhasználó. (ha másik gépre téved a web-farmban akkor ott is elérhető legyen a kosár a tartalmával, ill. ha kiesik egy(N) node a cache-cluster-ből akkor is elérhető legyen az adat.
  3. Erőforrás jellegű adatok (Resource data)
    pl. raktárkészlet, helyre szóló jegyek. (a legnehezebb dió)
    Jellemzők: írandó-olvasandó adat, mindez konkurens módon. (Egyszerre akar sok ember ugyan arra a repülőgépre foglalni, és minden jegyet pontosan egyszer lehet csak eladni)
    Elvárások: legyen konkurenciakezelés.

Hogy oldjuk meg ezeket?

partitioning

1. Particionálunk. N darab cache-kliens elkezdi önteni az adatok a clusterbe, és valami logika szerint valemelyik node tárolja az adott elemet. Nő a sebesség? Nő ‘hát! N gép Nx annyi memória, Nx annyi processzor és Nx annyi sávszélesség.
Hogyan működik ez fizikailag?
(eddig még nem beszéltünk az API-ról, de itt a lényeg hogy minden cache elem egyedi azanosítóval rendelkezik, amit a programozó ad neki. továbbá adhatok régiókat, ami egyfajta kategorizálása az adatoknak, ez fontos szerepet játszik a fizikai megvalósításban is)

partition_keys

Ha nem adok meg régiót, akkor egy előre meghatározott, számunkra érdektelen, logika szerint automatikusan régióba kerül az adat, majd ez alapján bekerül egy range-be, és ez alapján egy adott cache(Velocity)-node-ra. Ebben az elosztásban nagy szerepet játszanak a hash algoritmusok amikkel könnyen kivitelezhető ez a csoportosítás. A lényeg ebben hogy egy régióba tartozó cache adatok egy szerverre kerülnek. Továbbá a hash alapján a kliens villámgyorsan el tudja érni az kívánt adatot, és nem fog gondot, overhead-et okozni a cluster-ben való tájékozódás.

2. Fail-over

partition_ha

Fail-over biztosítására (kiesik N darab cache-node, mert a takarítónű kihuzta a dugót a konnektorból) nincs más teendőnk, mint hogy megmondjuk hogy az adott named-cache-en (egy cache-cluster-en bármennyi cache lehet, ezek egyedileg azonosítottak a nevük alapján) mennyi gép kiesését szeretnénk elviselni. Ha pl. egyet, akkor 2 helyen lesz tárolva az adat, ha kettőt, akkor hármon, és így tovább… Minden elemnek van tehát N darab másodlagos példánya, aminek szerepe csak akkor van ha kiesik az elsődleges:

partition_ha_bug

Látható hogy pl az A objektum a Server1-en előlépett elsődlegessé, ill. a kiesett F-E-C másodlagos elemekből újra készült másodlagos példány a Server1 ill. a Server2-n (Server 2 hősi halála esetén).
Mindez automatikusan, aszinkron módon türténik, nekünk csak 2-3 konfigurációs bejegyzést kell tenni. Persze ekkor ha van 10 gépünk 2 gbyte memóriával, és 2 gép kiesését szeretnénk elviselni, akkor 10*2/3 gbyte hely áll rendelkezésünk.
Ennyit el kell viselnünk, de amúgy szerintem zs-e-n-i-á-l-i-s!!!

3. Konkurencia.
Ennek megvalósítása biztos nem volt egyszerű, de szerencsére nekünk a fizikai működéssel nem kell foglalkoznunk, pusztán a már jól megismert optimista vagy pesszimista konkurencia kezelés közül választani, és ez alapján írni a kódót.
Pl. pesszimista konkurencia kezelés (az lokkolás):

locking_pess
(az API-ról a továbbiakban lesz szó, de a fenti ábrán látható hogy a van Get() and GetAndLock() metódus ami értelemszerűen végzi a dolgát, tehát nekünk csak meg kell tervezni és ez alapján implementálni az elvártakat)

Optimista konkurencia kezelés esetén pedig “visszaíráskor” kerül ellenőrzésre hogy az “eredeti” állapot van e még a cache-ben. Ha igen akkor mi vagyunk az elsők így mehet az írás. Ha nem, akkor így jártunk, valaki megelőzött. Ekkor a programozó dolga hogy kezelje a különböző lehetőségeket.

Összefoglalás

A fent megismert koncepciók véleményem szerint az egész AppFabric-Cache megoldás alap-pillérei. Nagyon fontos hogy e képességeket/lehetőségeket figyelembe vegyük amikor döntünk a használata mellett. És ha már döntöttünk, akkor ezt az adott architektúrába illesztéskor kellő gondossággal tegyük.

A továbbiakban látni fogjuk részletesen az AppFabric Cache használatát (API), azt hogy hogy illeszük ezt egy meglévő rendszerbe, ill ha olyan szerencsés helyzetben vagyunk hogy most építünk 0-ról rendszert, akkor miként tervezzük azt úgy hogy bármikor, akár generikus módon, egy cache-réteg legyen “beszúrható” a rétegek közé.
 load_test
(00:45 +1 server online betétel a clusterbe, 2:00 +1 server online betétele a clusterbe)
(láthatü a közel lineáris áteresztő-képesség növekedés, 3. servernél már a test-kliensek véges száma miatt nem lineáris az érték, ill. latency végtelenségig nem csökkenthető, van egy fizikai korlát)

És persze nem elhanyagolható a biztonság, ill. a menedzselhetőség kérdése sem, a mindenféle load- és fail-over teszt mellett. Különben mi értelme lenne bonyolítani az architektúrát?!?
Ezek következnek most!

Kategória: AppFabric | Közvetlen link a könyvjelzőhöz.

Hozzászólás