ugrás a tartalomhoz

A NoSQL világa – 2. rész: Kulcs–érték tárolók

macat · 2011. Dec. 7. (Sze), 00.54

Ebben a részben a séma nélküli, jól skálázódó alkalmazásokat tekintjük át.

A sorozatban megjelent

Ezen rendszerekhez hasonlókkal szinte mindenki találkozott már. Segítségükkel az RDBMS rendszereket tűrhető módon lehet skálázni bizonyos fokig. A tipikus webes környezetet (alkalmazás + adatbázis) a jól ismert cache tárolókkal (bár a többes szám helyes, a memcache szinte egyeduralkodó) gyorsítjuk. Bemenő adatokból képzett kulcs alapján letároljuk a kimenő adatot, ezzel a köztes műveleteket megspóroljuk. Ezek az eszközök a sebesség miatt az adatokat a memóriában tárolják. Ha elfogy a beállított memóriahely, eldobják a régi bejegyzéseket: az adatok illékonyak.

Persze adódik a felvetés, miért ne lehetne ezt a sebességet kihasználni, és adatokat permanensen tárolni ezen alkalmazások segítségével. Az ötlet egyszerű, mindössze az eddig beégett alkalmazástervezési szokásokat kell hozzá átalakítani. Nagy és kombinált struktúrák helyett egyszerűen leírható objektumokra van szükség. A bonyolult és sok táblát összekapcsoló lekéréseket persze el kell felejteni, teljesen új megközelítésre van szükség adataink előhívásához. Mit nyerünk ezzel? Sebességet, magas rendelkezésre állást és általában egyszerűbb alkalmazás-szerkezetet.

A kulcs–érték tárolók nagyon egyszerű felépítésű, általában rövid programok (a Redis 20 000 sor). Alapkoncepciójuk, hogy az adatobjektumokat valamilyen kulcs segítségével érhetjük el. A kulcsok minden esetben egyediek. Az objektumok ezért lényegében O(1) sebességgel hozzáférhetőek. Más esetben a kulcs–érték elvet arra is felhasználhatják, hogy elosszák a hálózat tagjai között az objektumokat. A kulcsok jól meghatározott egységekre bontják a tárolt adatot, így válik egyszerűvé a megosztás a tároló végpontok között (sharding).

A kulcs–érték tárolók egy jelentős részét az ún. Amazon Dynamo specifikáció alapján fejlesztették. Ebben a dokumentumban írták le az Amazon mérnökei a problémákat és az általuk talált megoldásokat.

Fontos megfigyelés, hogy a kulcs–érték tárolók általában a skálázhatóság és a magas rendelkezésre állás miatt eldobják az ACID (atomicity, consistency, isolation, durability) tulajdonságokból a konzisztenciát. Vagyis a kliensnek fel kell készülnie, hogy a visszakapott érték nem a legújabb, és nem biztos, hogy nincs a hálózatban más érték ugyanazzal a kulccsal. Ekkor rendszerint az alkalmazás választja ki a legjobbat, esetleg összefésüli őket.

A legismertebb kulcsos tárolók

Név Fejlesztés Platform Szponzor Megjegyzés
Amazon Dynamo zárt Amazon Több fogalom bezetője, az egyik korai nagyban használt NoSQL rendszer.
Voldemort nyílt Java Sok szempontból az Amazon Dynamo egyik nyílt forrású megvalósítása.
Redis nyílt C VMware Sokan kulcs–adatstruktúra elvű tárolónak írják le, mivel többféle adatstruktúrát támogat.
Riak nyílt Erlang, C Basho Technologies Amazon Dynamo implementáció, ezen felül támogatja a Map–Reduce technológiát is.
Membase Dinamikus skálázódást biztosító tároló Memcached alapon megvalósítva.
ScalienDB nyílt C++ Scalien Magyar fejlesztésű tároló, paxos algoritmust használ.

Adatstruktúrák

Az adatok struktúrájáról szinte minden esetben a tárolót használó alkalmazás dönt. A tároló nem veszi figyelembe az értékként tárolt információ tartalmát, struktúráját, azt csak egy bájtfolyamként kezeli.

Az eltárolt értékhez kapcsolt kulcsot (hash) az alkalmazás és a tároló is meghatározhatja, mindkét megoldásra van példa.

Némely tároló verziókezelést is biztosít az objekumok számára. Ebben az esetben a kéréssel együtt a verziót is megkapja a kliens. A verzió segítségével válik lehetővé a problémás esetek felüldefiniálása.

Adatok elosztása szervereken – konzisztencia

Az adatok mennyisége és a konkurens lekérdezések miatt megnő a válaszidő. A növekvő adatmennyiség másrészt növekvő kockázatot is jelent, mivel meghibásodás esetén nagyobb mennyiségű adat válik elérhetetlenné. Ezeknek a problémának a kezelésére a kulcs–érték tárolók nagyrészt hasonló alapelven alapuló megoldásokat használnak: az adatokat a hálózat szereplői között valamilyen algoritmus segítségével elosztják, hogy mely objektum mely végpontra kerül, a kulcsot használó algoritmus dönti el. Egy adat egység kerülhet több gépre is, ekkor javul az adatelérés sebessége és biztonsága.

Változó válaszok születtek ezekre a problémákra, mi most két meghatározót vizsgálunk meg. A Dynamo specifikációban leírt gyűrűs és az egyszerűbb sharding megoldást.

A Dynamo ún. gyűrűbe szervezi a hálózat végpontjait. Így az egyes végpontoknak csak a szomszéd elemekkel kell foglalkoznia. Nincsenek propagált, kiemelt számítógépek, így a hálózat egyszerűen bővíthető. Ebben a modellben deklaráltak virtuális végpontokat is, ekkor egy számítógépen valójában több futó Dynamo is van, ez javítja az adatok elosztottságát–biztonságát. A hálózatban az adatelemek a konfigurációnak megfelelően több helyen találhatóak. A gyűrűben ezeket sorban egymásnak küldik tovább a hálózat tagjai.

A megoldás tartalmaz egy ún. vector clockot is, mellyel kezelve az adatobjektumok verzióit érik el, hogy a hálózat mindig írható állapotban van, nem törődve az esetleges kieső részekkel.

Egy másik népszerű megoldás, melyet akár kliens oldalon is meg lehet valósítani, hogy a tároló hálózat elemei nem állnak kapcsolatban. A kliens vagy egy összekötő elem dönti el, hogy a kulcsok mely végpontra kerülnek. Ebben az esetben a kieső számítógépek ellen csak a tükrözés jelent megoldást, amikor a tárolók mindegyikéből egyszerű master–slave replikációval több másolatot tartunk fenn a hálózatban.

Míg az első a szolgáltatásaival, magas rendelkezésre állásával lehet alkalmazásunk optimális kiszolgálója, a második esetben a sebesség és az implementáció egyszerűsége a fő tényezők a választáskor.

Egyéb érdekességek, előremutató fejlesztések

Bonyolultabb adatszerkezetek

Bár az alapkoncepciója a kulcs–érték tárolóknak az, hogy az érték struktúrájáról a tároló nem tud, bizonyos implementációban a kulcs lehet bonyolultabb. Ilyen tároló a Redis, mely megengedi, hogy az értékéket különböző adatszerkezetekbe (lista, hash, halmaz, rendezett halmaz) soroljuk. Ez továbbra is azt jelenti, hogy magát az értéket csak egy bájtfolyamnak tekinti, de a kulcsok lehetnek bonyolultabbak. Így a Redis egyes esetekben optimálisabb működést biztosíthat.

Tranzakciók

Bizonyos tárolók képesek tranzakciós blokkokat kezelni. Az adatok ilyesforma megváltoztatása hasonló a relációs adatbázisoknál alkalmazotthoz. Egy blokk kezdetét jelölni kell, amely után elindított módosító utasítások nem hajtódnak végre, míg a blokkot valamely utasítással nem fejezzük be. Ideális esetben a blokk befejezése után logikailag egy műveletben történik a módosítás, azt atominak lehet tekinteni. Természetesen lehetőség van az összes utasítás eldobására a tranzakciós blokkban. Tranzakciókat a Redis is támogat.

A tranzakciók használata olyan esetben merülhet fel, amikor egyszerre több objektumon kell hogy megtörténjen egyszerre, vagy a hibakezelési metódus miatt vissza kell vonnunk már elindított változásokat.

PUB/SUB

A weben is elterjedőben van a folyamatosan fenntartott kapcsolat. Ezzel a technikával a kapcsolat a szerver és a kliens között folyamatos, a szerveren történő változásokat a kliens azonnal megkaphatja. Évek óta léteznek kerülő megoldások, melyek egy hosszan fenntartott lekérdezéssel szimulálják a folyamatos kapcsolatot. A remélhetőleg hamarosan elterjedő websocket elhozhatja a Kánaánt ezen a téren, és a webalkalmazások valóban élő kapcsolatot tartanak majd fenn. A folyamatos kapcsolathoz elkerülhetetlen, hogy a szerveroldal is valamilyen szinten átalakuljon. A PUB/SUB megoldás egy olyan lehetőség, mellyel a kliensek feliratkozhatnak egy csatornára, és az oda beküldött adatcsomagokat mindenki megkapja. A feliratkozó a SUBSCRIBER, aki a csomagokat megkapja, a publikáló PUBLISHER, pedig a küldő szerepét játsza.

A Redis nyújt ilyen szolgáltatást. A kliensek a megadott csatornára a PUBLISH utasítással küldhetik az üzenetet, míg a feliratkozók a SUBSCRIBE-bal iratkozhatnak fel egy csatornára. Lehetőség van akár több csatornát egyszerre figyelni a PSUBSCRIBE utasítással.

 
macat arcképe
macat
2004 óta fejleszti aktívan a világhálót, kezdetben főállásúként majd 2006-tól szabadúszóként. Kisebb-nagyobb projektekben vett részt a web különböző területein. Habzsolja a zenei élményeket és a süteményeket, a reggeli kocogást pedig semmiért sem hagyná ki.
1

Az írás hasznos,

Hidvégi Gábor · 2011. Dec. 7. (Sze), 12.46
Az írás hasznos, köszönjük.

Az ismereteim valószínűleg hiányosak, de ellentmondást látok e két kijelentés között:
kulcsok minden esetben egyediek. Az objektumok ezért lényegében O(1) sebességgel hozzáférhetőek.
Az adatok mennyiségével együtt jelentősen megnő azok elérésének ideje.

Az "Egyéb érdekességek, előremutató fejlesztések" cím végén a <h3> nincs lezárva, ezért IE alatt ezután rosszul jelenik meg a szöveg. Továbbá légyszi rakjatok a cikk elejére egy linket az első részhez.
2

Kösz a jelzést, javítottam.

Joó Ádám · 2011. Dec. 8. (Cs), 00.45
Kösz a jelzést, javítottam.