Cassandra očima .NET programátora

V poslední době je v módě termín NOSQL (Not Only Sql) a tak se i já o něm zmíním. Není to proto, že bych potřeboval být nutně cool, ale byl jsem nucen se na NOSQL podívat, protože nabízí efektivní řešení některých specifických úkolů, u kterých klasické relační databáze ztrácí dech. Je trošku zavádějící mluvit o NOSQL databázích (přestože to jsou báze dat), proto upřednostňuji termín NOSQL úložiště. NOSQL úložišť existuje mnoho typů, já se ale zaměřím jen na úložiště typu BigTable, konkrétně na Cassandru. Co zde popíšu ale do jisté míry platí i pro HBase.

V čem byste implementovali úložiště dat, aby bylo opravdu rychlé? C/C++? Asm? Některá NOSQL úložiště jdou touto cestou (např. MongoDB), ale Cassandra a HBase jsou implementovány v Javě. Ano, v tom strašné, pomalém a zdroježeroucím molochu, jak by Javu mnozí počastovali. Ale vězte, že na tomto molochu běží celý internet…tedy, ehm, Facebook 😉 Cassandra je totiž zopensourcovatělé jádro Facebooku, ale dnes ji používá i Twitter a další služby.
Implementace v Javě určila i ekosystém okolo těchto úložišť, takže prakticky všechny nástroje a knihovny okolo jsou také implementovány v Javě. A zde vyvstává otázka jak komunikovat s úložištěm z .NETu. Protože celá komunikace probíhá přes síť, není to nic složitého. Mnozí by očekávali nějaký známý protokol jako SOAP nebo OData, ale Cassandra i HBase používají (IMHO mezi .NET komunitou zcela neznámý) Thrift.

Thrift je síťový binární protokol pro RPC, který je ale i přes svou binárnost otevřený k rozšíření (není nutné se vázat na jednu verzi služby). Thrift ale není jen definice protokolu. Thrift dále přináší vlastní IDL (jazyk pro popis rozhraní služby), který umí dodávané nástroje transformovat do mnoha jazyků (C# nevyjímaje). Takže spolu s Cassandrou si stáhneme Thrift API a z toho si nagenerujeme klientské třídy v C#. Je to tedy stejný postup, jako když z WSDL generujeme třídy pro komunikace přes SOAP.

API Cassandry není moc bohaté a vlastně nám umožňuje jen vybírat hodnoty podle klíčů a hodnoty ukládat. Více v dokumentaci.

Datový model

Nejvyšší úrovní dělení je tzv. KeySpace (~databáze), který obsahuje ColumnFamilies (~tabulky). Každá ColumnFamily obsahuje řádky, které jsou identifikovány pomocí klíče. Každý řádek může obsahovat libovolný počet sloupců. Každý sloupec (identifikovaný jménem) má přiřazenu hodnotu a timestamp (který dodává aplikace!). Hodnotou sloupce nemusí být jen byte[], ale opět to může být další Mapa – pak mluvíme o tzv. SuperColumn.
Datový model pro programátory:
Map<byte[], Map<byte[], Map<byte[], Tuple<byte[], TimeStamp>>>>.
Neboli:

  • KeySpace name (typicky string) -> ColumnFamilies
  • ColumnFamily name (typicky string) -> Rows
  • Row key (byte[]) -> Columns
  • Column name (string) -> ColumnValue (byte[], timestamp)

Často se datový model vysvětluje (a je to tak přesnější) tak, že se obrátí ColumnFamily a řádek, tedy že řádek obsahuje ColumnFamilies.
Důležité je, že v konfiguraci se nastavují pouze KeySpaces a ColumnFamilies. Všechno ostatní je variabilní a může se to měnit – a to na každé úrovni. To mj. znamená, že každý řádek může mít libovolný počet sloupců a u každého řádku mohou být sloupce úplně jiné.
Data jsou fyzicky setříděná podle klíčů a sloupce také seřazeny podle názvů. Protože se všude pracuje s blobama byte[], máme možnost definovat, jakým způsobem se má třídit.

Velmi pěkný popis datového modelu Cassandry naleznete v tomto článku.

Jak jsem psal, Cassandří API je poměrně jednoduché a tak Vás možná napadne, že vybírání hodnot jen podle klíčů není dostatečné. A je to možné! Opravdu Vaše aplikace nemusí být vůbec vhodná pro nasazení na NOSQL úložišti. Ale i tak je vybírání podle klíčů poněkud svazující a proto byla ve verzi Cassandry 0.6 přidána podpora pro Hadoop.

Hadoop

Hadoop je v Javě napsaný open-source framework pro psaní spolehlivých, škálovatelných a distribuovaných výpočtů. Sestává se z několik částí, přičemž nás bude zajímat hlavně MapReduce, což je implementace MapReduce algoritmu. To je zjednodušeně řečeno algoritmus, který nám umožní položit dotazy, které se dají snadno paralelizovat.
Tento Map/Reduce se pak typicky využívá nad NOSQL úložištěm HBase (další část Hadoopu), které je postavené nad distribuovaným file systémem HDFS (také součást Hadoopu).

Když chceme zadat nějakou Map/Reduce úlohu, musíme předat do jobtrackeru jar, který obsahuje třídy implementující rozhraní Mapper a Reducer.
Pokud chceme dělat něco jednoduchého a nechce se nám kódit v Javě, můžeme použít Hadoop Streaming, což není nic jiného než konkrétní implementace Mapperu a Reduceru, která volá námi zadaný program a komunikuje s ním přes stdin/stdout. Konkrétně to funguje tak, že do Mapperu, resp. Reduceru, přichází řádky oddělené znakem nového řádku. Na řádku je nejprve klíč následovaný tabulátorem. Zbytek do konce řádku je hodnota.
Na jednoduché věci to určitě stačí, ale pokud chceme absolutní svobodu, pak musíme sáhnout po Hadoop Pipes. Jeho základem je opět implementace Mapperu a Reduceru, která tentokrát volá tenký wrapper v C++ (přes sockety). S tímto wrapperem je už možné komunikovat z téměř jakéhokoliv jazyka, protože je pro něj dostupné SWIG rozhraní (něco jako Thrift, ale funguje to lokálně). Takže díky tomuto můžeme psát Map/Reduce funkce v jakém jazyce chceme.

Psaní Map/Reduce dotazů se nám může ale pěkně zkomplikovat, zvláště když dotazy vyžadují více iterací. Pak můžeme sáhnout po projektu Pig (součást Hadoopu), který nám umožní zapsat dotazy v jazyce Pig Latin (ne nepodobný Linqu). Pig Front-end zadaný dotaz naparsuje, zoptimalizuje a vytvoří LogicalPlan, který popisuje, jak by se měl daný skript spustit. O samotné vykonání se pak postará Pig Back-end. Nyní existují dvě implementace Pig Back-endu – nad lokálním úložištěm (méně zajímavé) a nad Map/Reduce (obsahuje imlementaci Mapperu a Reduceru).
Abychom tedy mohli napsat Map/Reduce dotaz, nemusíme tedy nutně psát kód v Javě, ale místo toho předáme jen string obsahující skript v jazyce Pig Latin.

Podobný účel jako Pig má také projekt Hive, který přináší ještě vyšší stupeň abstrakce a umožňuje dotazovat do libovolného úložiště (pomocí jazyka QL), jehož strukturu jsme schopni popsat (musíme tedy zavést nad úložištěm strukturu). Hivem se ale nebudu teď zabývat, protože ještě není v production quality.

Shrnutí

Jak tedy pracovat s Cassandrou z .NET? Pokud si vystačíme s API, které nám nabízí Cassandří Thrift, pak si stačí nagenerovat třídy pro C# a máme vystaráno. Pokud Vám připadá Thriftové rozhraní příliš low-level, jsou k dispozici i nějaké nadstavby (třeba connection pooling je dobrý nápad).

Pokud chceme provádět Map/Reduce operace, je situace složitější, protože v jádru jde vždy o Javu.
Můžeme mít např. jednoduchou web-service, do které budeme posílat jary s Mapperem a Reducerem. Nebo můžeme mít na serveru předpřipravené jary a modifikovat soubor s parametry uložený uvnitř nich (je to jen zip).
Další možností je posílat do naší webové služby pouze dotazy v jazyce Pig Latin – pak už jsme blízko klasické situaci, kdy na SQL server posíláme dotazy v SQL.

Pokud se někdo rozhodne nasadit Cassandru na svůj projekt, měl by se nejprve důkladně obeznámit s jejím datovým modelem a zjistit, jestli bude mít k dispozici věci, které potřebuje a třeba je považuje za samozřejmost (díky SQL světu). Není to všespásný zlatý grál a nehodí se na všechny typy projektů.

Příspěvek byl publikován v rubrice Programování a jeho autorem je Augi. Můžete si jeho odkaz uložit mezi své oblíbené záložky nebo ho sdílet s přáteli.

10 komentářů u „Cassandra očima .NET programátora

  1. Nooo ale RavenDB (document storage) řeší úplně jiný typ úloh než Cassandra (column storage).

  2. Tej vety o vybere typu som si nevsimol:) A co tak nejaky use case sample, preco prave sa bavis s column storage?

  3. java pomala? zdroje zrouci? tady je nokdo totalne mimo … pojd sednout ke klavesnici a ukazame si jak moc se mylis 🙂 bez problemu kdykoliv dokazu i zaslepenemu MVP se slunecnimi brylemi pravdu

    Honza

  4. Tak jsem si precetl cely blog a par poznamek:
    1) zastav se v utery na osmem patre budu o “nosql” neco rikat

    2) java je zhruba stejne rychla jako C-cko – zastav se na osmem patre, ukazu ti to. Klidne prebootuju i do Windows 7 aby jsi nepojal podezreni, ze gcc by snad mohlo byt pomale

    3) java neurcial ekosystem – ucel ho urcil – kdyz mas problem, ktery musi bezet napric nejvetsimi datacetry sveta se 100% spolehlivosti, vykonem a bezpecnosti, tak nema nic lepsiho nez javu

    3) SOAP – videl jsi ho nekdy? Pokud ano, tak by jsi mel vedet proc se nepouziva. Pokdu to nevis, tak zagoogli – jde o to, ze SOAP ma uplne brutalni overhead. Kdyz na poslani 100B infomace potrebuju 1kB, tak propustim 1Gb sitovkou jen 10MB/s uzitecne informace, proto nikdo na velke veci nepouziva SOAP. Pravda, ze je trochu opruz, kdyz se ven bavim JSONem, scassandrou Thriftem, ta to dava hadoopu Avrem, do toho se s necim bavis Protocol Bufferama … trochu opruz, ale takovy je svet. BTW: Proc vzniknul nejen Thrift, ale i to Avro, Protocol Buffers, Kryo a dalsi? Myslis, ze to bylo tim, ze tu byla urcita potreba nebo proto, ze nemame vsichni nalepku od MS?

    4) konkretne cassandra je nejlepe receno “one hop DHT”, skalovatelna (na tisice stroju, petabajty dat a miliony requestu za vterinu), vzdy dostupna – vubec pokud nezminis CAP, tak se neni o cem bavit … no je dalsich 100 veci co by bylo potreba rict, ale coz … ach jo – nosql ocima .NET = “netusim ktera bije”

    5) pokud chces davat nejaky navod, tak rekni, ze pokud nema nekdo alespon nekolik TB dat a vice jak desitky milionu zaznamu na “tabulku” tak nechce “nosql”

    6) map reduce je neco “co jde paralelizovat”? to se da kdeco 🙂 slysel jsi nekdy o funkcionalnim programovani? vis, ze ten reduce je to co byva mimo “map reduce” termin oznacovano “fold”? vis, ze je mezitim desne dulezita cast “shuffle”?

    7) cassandra neni jadro facebooku, je to jen datastore pozuvany taky diggem, twitterem, rackspacem … uz pomalu i avastem … neni to o socialni siti, je to rychly, skalovatelny, vzdy dostupny datastore se snadnou volbou konzistence na kazdy dotaz a prakticky nulovou administraci

    BTW: ma to spoustu dalsich vyhod, ale nejsem si jisty, ze by to vubec nekdo na tomto blogu pochopil

    … mohl bych pokracovat, ale bohuzel je tam toho tolik na co upozornit, ze si to nemuzu zapamatovat naraz a nestoji to za to abych to poduhe cetl 🙂

  5. jan: Všechno je určitě super a jsi odborník na svém místě, škoda jen, že ses totálně diskreditoval tím, že vytrháváš věci z kontextu a píšeš naprosto nemístné poznámky. Příště zkus nejprve důkladně přečíst, co se v článku píše, než budeš brojit proti něčemu, co ve skutečnosti nezaznělo, a takovéhle výblitky si opravdu odpusť:
    “zaslepený MVP se slunečními brýlemi”, “SOAP – viděl jsi ho někdy?”, “nemáme všichni nálepku od MS”, “nosql očima .NET = netuším která bije”, “slyšel jsi někdy o funkcionálním programování?”, …

    a finální bomba: “nejsem si jistý, zda by to vůbec někdo na tomto blogu pochopil”

    No od tebe určitě ne, protože i pokud bys měl 100x pravdu, tak ten chaotický styl, vytrhávání věcí z kontextu a nemístné narážky nikdo nemůže brát bohužel vážně 😉 Ale určitě ti to ulevení si pomohlo k lepší psychické pohodě, a to ti upřímně přeji 🙂 Java FTW

  6. Honzo, jak se Ti prosím zobrazuje tag <em> v Tvém prohlížeči? Ta věta, na kterou jsi se zaměřil, je totiž napsána právě v tomhle tagu (takže kurzívou ve všech prohlížečích, které používám). A je napsána v kurzívě proto, že není myšlena vážně – je to jen odkaz na velmi rozšířený omyl/mýtus, který jsem se snažil dalšími větami vyvrátit. Bohužel jsi první, kdo tuhle nadsázku nepochopil…

    Takže pro Tvůj klid: Vím, jak na tom je výkonnově Java, .NET i nativní kód. A vím, že nyní ma Java výkonnově navrh nad .NET, resp. CLR. Obecně se netajím tím, že považuji v mnoha ohledech Javu za lepší platformu než .NET, viz třeba tenhle tweet (a netahej mě prosím za slovíčka – ve 140 znacích je člověk dost omezen).

    Při vší úctě, asi Ti ta nepochopená věta zatemnila mysl, protože další Tvoje reakce mi podsouvají něco, co jsem nikdy nevyřkl.

    2) Nemusíš mi to dokazovat, já to vím. Dokonce vím, že v některých situacích může být (stejně jako .NET) rychlejší nez Céčko. Nikdy jsem netvrdil opak.

    3) Zde evidentně reaguješ na větu “Implementace v Javě určila i ekosystém okolo těchto úložišť, takže prakticky všechny nástroje a knihovny okolo jsou také implementovány v Javě.“. Tou jsem chtěl říci jen to, že protože Cassandra je implementována v Javě, tak implementovat různé nadstavby a nástroje také v Javě bylo nabíledni.

    3) O SOAPu jsem se zmínil jako o jednom ze standardů pro RPC komunikaci a tím prostě je (i když se mi některé jeho vlastnosti nelíbí). SOAP samozřejmě znám, používám a uvědomuji si jeho vlastnosti. Jasně, že má velký overhead, ale ne vždy je jediným a nejdůležitějším cílem propustnost a proto má své místo a používá se.

    4) Cílem článku nebylo sepsat všechno o NoSQL databázích, co znám, protože to se v jednom článku prostě nedá, a ne všem aspektům pořádně rozumím (a nedělá mi problém to přiznat). Cílem článku bylo především popsat možnosti komunikace s Cassandrou z .NETu.
    Cílem tedy nebylo popisovat Cassandru nebo dokonce NoSQL obecně (narážím na CAP teorém) – to by bylo mimo rozsah tohoto článku (a necítím se na to dost fundovaný). Že jsem něco (CAP) nezmínil přece neznamená, že to neznám…

    5) Minimálně na dvou místech v článku jsem se zmínil, že by si měl člověk pořádně rozmyslet, jestli bude Cassandru používat.
    Dovolil bych si ale polemizovat s tím, že NoSql je vhodné jen pokud máme velké množství dat. Mnozí lidé u NoSql databází nehledají výkonnost, ale jen gumovost datového modelu, jejíž nepřítomnost je občas u relačních databází dosti svazující. Myslím, že i na takové lidi je mířena třeba MongoDB.

    6) Jak jsem už psal, cílem článku bylo popsat především komunikaci s Cassandrou z .NETu, takže výklad MapReduce (narážím hlavně na zmínku o shuffle fázi) je opět mimo rozsah článku. A i když jsem o tom nepsal, tak to přece neznamená, že o tom nevím.
    O funkcionálním programování něco vím – např. doc.RNDr. Josef Kolář, CSc. označil mou zkouškovou práci z funkcionálních jazyků za nejlepší, jakou kdy viděl (neměl mi co vytknout).

    7) A jaká je přesná definice jádra aplikace? IMHO je Cassandra jedním z pilířů Facebooku – však to nejcennější jsou jeho data…

    BTW: ma to spoustu dalsich vyhod, ale nejsem si jisty, ze by to vubec nekdo na tomto blogu pochopil
    Nikdo Tě nenutí to tady číst nebo dokonce reagovat, kór když jsme všichni takovej přiblblej póvl s nálepkou MS…

  7. augi:
    Tak to se moc omlouvam Augi! Pochopil jsem to spatne 🙁 Posledni dobou slycham od .NETaku takovy nesmysly (mysleny smrtelne vazne), ze jsem necekal, ze by si nekdo delal srandu 🙁 Proto jsem rad, ze po tech dvou prispevcich co jsme pripsali to snad nikdo nepochopi tak jako ja na prvni precteni 😉 Za ten ton se omlouvam. Promin!

    BTW: Nepis nektere veci prosim ani z legrace, protoze opakovani je “matka moudrosti” a lidi jsou pak neprijemne “moudri”.

    Presto si dovolim ctenare jeste jednou upozornit:
    Pokud jste jiz nekdy pouzili RDBMS, tak ani neuvazujte o prechodu na nic z “NoSQL” hypu, pokud nemate:
    1) terabajty dat
    2) desitky milionu zaznamu
    3) desetitisice zapisu za vterinu
    Pokud to udelate, tak prijdete o vice jak 99% funkcionality, flexibiliity a vyspelych nastroju. Nikdo z “NoSQL” nerika, ze jsou RDBMS spatne, jen je nikdo neumi naprogramovat tak, aby zvladli zatez web-scale aplikaci. Prijdete o transakce, silnou konzistenci, indexy, integritni omezeni, real-time dotazy, … nebudete mit normalizovane data ani nepouzijete linq.

    Pokud ale mate terabajty dat, miliardy zaznamu, atd. pak zase nepremyslejte o RDBMS 🙂

  8. Jj, NoSql není jen o výkonu – je to obecně o jiném přístupu k věci (Not Only SQL). Hodně lidí třeba nechce převádět svoje objektové modely do relačního světa, tak raději použití dokumentové nebo objektové databáze (které také spadají do NoSql kategorie). A vůbec neočekávají nějaký mega výkon oproti relační databázi.

Napsat komentář

Vaše emailová adresa nebude zveřejněna.