Cassandra. Kuidas mitte surra, kui tunnete ainult Oracle'i

Tere Habr.

Minu nimi on Misha Butrimov, ma tahaksin teile Cassandrast veidi rääkida. Minu lugu on kasulik neile, kes pole kunagi NoSQL-i andmebaasidega kokku puutunud - sellel on palju rakendusfunktsioone ja lõkse, mida peate teadma. Ja kui te pole näinud midagi peale Oracle'i või mõne muu relatsiooniandmebaasi, päästavad need asjad teie elu.

Mis on Cassandras nii head? See on hästi skaleeritav NoSQL-i andmebaas, mis on loodud ilma ühegi tõrkepunktita. Kui teil on vaja mõne andmebaasi jaoks paar terabaiti lisada, lisage rõngasse lihtsalt sõlmed. Kas laiendada seda teise andmekeskusesse? Lisage klastrisse sõlmed. Kas suurendada töödeldud RPS-i? Lisage klastrisse sõlmed. See töötab ka vastupidises suunas.

Cassandra. Kuidas mitte surra, kui tunnete ainult Oracle'i

Milles ta veel hea on? See puudutab paljude taotluste käsitlemist. Aga kui palju on palju? 10, 20, 30, 40 tuhat taotlust sekundis pole palju. 100 tuhat taotlust sekundis salvestamiseks - ka. On ettevõtteid, kes ütlesid, et säilitavad 2 miljonit päringut sekundis. Tõenäoliselt peavad nad seda uskuma.

Ja põhimõtteliselt on Cassandral relatsiooniandmetest üks suur erinevus – see pole nendega üldse sarnane. Ja seda on väga oluline meeles pidada.

Kõik, mis näeb välja ühesugune, ei tööta samamoodi

Kord tuli üks kolleeg minu juurde ja küsis: „Siin on CQL Cassandra päringukeel ja sellel on valiklause, sellel on kus, sellel on ja. Kirjutan kirju ja see ei tööta. Miks?". Cassandra käsitlemine relatsioonilise andmebaasina on ideaalne viis vägivaldse enesetapu sooritamiseks. Ja ma ei propageeri seda, see on Venemaal keelatud. Sa lihtsalt kujundad midagi valesti.

Näiteks tuleb klient meie juurde ja ütleb: “Ehitame teleseriaalide jaoks andmebaasi või retseptikataloogi andmebaasi. Meil on seal toiduroad või telesarjade ja näitlejate nimekiri. Ütleme rõõmsalt: "Lähme!" Lihtsalt saatke kaks baiti, paar märki ja oletegi valmis, kõik töötab väga kiiresti ja usaldusväärselt. Ja kõik on hästi, kuni kliendid tulevad ja ütlevad, et perenaised lahendavad ka vastupidise probleemi: neil on toodete nimekiri ja nad tahavad teada, millist rooga nad tahavad valmistada. Sa oled surnud.

Seda seetõttu, et Cassandra on hübriidandmebaas: see annab samaaegselt võtmeväärtuse ja salvestab andmed laiadesse veergudesse. Java või Kotlini puhul võiks seda kirjeldada järgmiselt:

Map<RowKey, SortedMap<ColumnKey, ColumnValue>>

Ehk siis kaart, mis sisaldab ka sorteeritud kaarti. Selle kaardi esimene võti on reaklahv või partitsioonivõti – partitsioonivõti. Teine võti, mis on juba sorteeritud kaardi võti, on klastrite võti.

Andmebaasi jaotuse illustreerimiseks joonistame kolm sõlme. Nüüd peate mõistma, kuidas andmeid sõlmedeks jaotada. Sest kui me toome kõik ühte (muide, neid võib olla tuhat, kaks tuhat, viis - nii palju kui soovite), pole see tegelikult levitamine. Seetõttu vajame matemaatilist funktsiooni, mis tagastab arvu. Lihtsalt number, pikk int, mis jääb mingisse vahemikku. Ja meil on üks sõlm, mis vastutab ühe vahemiku eest, teine ​​teise ja n-s n-nda vahemiku eest.

Cassandra. Kuidas mitte surra, kui tunnete ainult Oracle'i

See number võetakse räsifunktsiooni abil, mida rakendatakse partitsioonivõtmele. See on veerg, mis on määratud primaarvõtme direktiivis ning see on veerg, mis on kaardi esimene ja kõige põhilisem võti. See määrab, milline sõlm milliseid andmeid vastu võtab. Cassandras luuakse tabel peaaegu sama süntaksiga kui SQL-is:

CREATE TABLE users (
	user_id uu id,
	name text,
	year int,
	salary float,
	PRIMARY KEY(user_id)

)

Esmane võti koosneb sel juhul ühest veerust ja see on ka partitsioonivõti.

Kuidas meie kasutajad toimivad? Mõned lähevad ühte sõlme, mõned teise ja mõned kolmandasse. Tulemuseks on tavaline räsitabel, tuntud ka kui kaart, Pythonis tuntud ka sõnastikuna või lihtne võtmeväärtuste struktuur, millest saame lugeda kõiki väärtusi, lugeda ja kirjutada võtmete kaupa.

Cassandra. Kuidas mitte surra, kui tunnete ainult Oracle'i

Valige: kui lubada filtreerimine muutub täielikuks skannimiseks või mida mitte teha

Kirjutame mõne valitud avalduse: select * from users where, userid = . Tuleb välja nagu Oracle’is: kirjutame select, täpsustame tingimused ja kõik toimib, kasutajad saavad kätte. Aga kui valite näiteks kindla sünniaastaga kasutaja, kurdab Cassandra, et ei saa palvet täita. Kuna ta ei tea üldse midagi sellest, kuidas me sünniaasta andmeid levitame – tal on võtmena märgitud vaid üks veerg. Siis ta ütleb: "Olgu, ma saan selle palve siiski täita. Lisa luba filtreerimine." Lisame direktiivi, kõik toimib. Ja sel hetkel juhtub midagi kohutavat.

Kui kasutame katseandmeid, on kõik korras. Ja kui täidate päringu tootmises, kus meil on näiteks 4 miljonit plaati, siis pole meil kõik väga hästi. Sest luba filtreerimine on direktiiv, mis lubab Cassandral koguda sellest tabelist kõik andmed kõikidest sõlmedest, kõikidest andmekeskustest (kui neid on selles klastris palju) ja alles siis filtreerida. See on Full Scani analoog ja vaevalt keegi sellega rahul on.

Kui vajaksime ainult ID-ga kasutajaid, oleks see hea. Kuid mõnikord peame kirjutama muid päringuid ja seadma valikule muid piiranguid. Seetõttu peame meeles: see kõik on kaart, millel on jaotusvõti, kuid selle sees on sorteeritud kaart.

Ja tal on ka võti, mida me kutsume klastrivõtmeks. See võti, mis omakorda koosneb meie valitud veergudest, mille abil Cassandra mõistab, kuidas tema andmed füüsiliselt sorteeritakse ja asuvad igas sõlmes. See tähendab, et mõne partitsioonivõtme puhul ütleb klastrivõti täpselt, kuidas andmed sellesse puusse lükata, mis koha need seal võtavad.

See on tõesti puu, seal kutsutakse lihtsalt komparaatorit, millele edastame objekti kujul teatud veergude komplekti ja see on määratud ka veergude loendina.

CREATE TABLE users_by_year_salary_id (
	user_id uuid,
	name text,
	year int,
	salary float,
	PRIMARY KEY((year), salary, user_id)

Pöörake tähelepanu esmase võtme direktiivile; selle esimene argument (meie puhul aasta) on alati partitsioonivõti. See võib koosneda ühest või mitmest veerust, see pole oluline. Kui veerge on mitu, tuleb see uuesti sulgudes eemaldada, et keele eeltöötleja saaks aru, et see on Primary võti ja selle taga on kõik teised veerud Clustering Key. Sel juhul edastatakse need võrdlusseadmes nende ilmumise järjekorras. See tähendab, et esimene veerg on olulisem, teine ​​vähem oluline jne. See, kuidas me kirjutame, võrdub näiteks andmeklasside väljadega: loetleme väljad ja nende jaoks kirjutame, millised on suuremad ja millised väiksemad. Cassandras on need suhteliselt andmeklassi väljad, millele rakendatakse selle jaoks kirjutatud võrdseid.

Määrame sorteerimise ja kehtestame piirangud

Peate meeles pidama, et sortimisjärjekord (kahanev, tõusev, mis iganes) määratakse võtme loomisel samal hetkel ja seda ei saa hiljem muuta. See määrab füüsiliselt, kuidas andmeid sorteeritakse ja kuidas neid salvestatakse. Kui teil on vaja klastrivõtit või sortimisjärjekorda muuta, peate looma uue tabeli ja edastama sellesse andmed. Olemasolevaga see ei tööta.

Cassandra. Kuidas mitte surra, kui tunnete ainult Oracle'i

Täitsime oma tabeli kasutajatega ja nägime, et nad langesid rõngasse, algul sünniaasta järgi ja seejärel iga sõlme sees palga ja kasutajatunnuse järgi. Nüüd saame valida piiranguid kehtestades.

Meie töötav ilmub uuesti where, and, ja saame kasutajad ning kõik on jälle korras. Aga kui proovime kasutada ainult osa klastrivõtmest ja vähemtähtsat, siis Cassandra kaebab kohe, et ta ei leia meie kaardilt kohta, kus see objekt, millel on need nullkomparaatori väljad, ja see üks see oli just seatud , - kus ta lamab. Pean kõik andmed sellest sõlmest uuesti üles tõmbama ja need filtreerima. Ja see on sõlme täieliku skannimise analoog, see on halb.

Igas ebaselges olukorras looge uus tabel

Mida peaksime tegema, kui tahame sihtida kasutajaid ID, vanuse või palga järgi? Mitte midagi. Kasutage lihtsalt kahte tabelit. Kui teil on vaja jõuda kasutajateni kolmel erineval viisil, on kolm tabelit. Möödas on ajad, mil hoidsime kruvil ruumi kokku. See on odavaim ressurss. See maksab palju vähem kui reageerimisaeg, mis võib olla kasutajale kahjulik. Kasutajal on palju meeldivam midagi saada sekundiga kui 10 minutiga.

Kaupleme tarbetu ruumi ja denormaalsete andmetega, et saaksime hästi skaleerida ja töökindlalt töötada. Lõppude lõpuks suudab klaster, mis koosneb kolmest andmekeskusest, millest igaühel on viis sõlme ja millel on vastuvõetav andmete säilitamise tase (kui midagi ei lähe kaduma), täielikult üle elada ühe andmekeskuse surma. Ja veel kaks sõlme mõlemas ülejäänud kahes. Ja alles pärast seda algavad probleemid. See on päris hea koondamine, tasub paar lisa SSD-draivi ja protsessorit. Seega, et kasutada Cassandrat, mis pole kunagi SQL, milles puuduvad suhted, võõrvõtmed, peate teadma lihtsaid reegleid.

Kujundame kõik vastavalt teie soovile. Peaasi ei ole andmed, vaid see, kuidas rakendus nendega töötab. Kui sellel on vaja erinevaid andmeid erineval viisil vastu võtta või samu andmeid erineval viisil, tuleb need panna rakendusele sobival viisil. Vastasel juhul kukume Full Scanis läbi ja Cassandra ei anna meile mingit eelist.

Andmete denormaliseerimine on norm. Unustame tavavormid, meil pole enam relatsiooniandmebaase. Kui me paneme midagi 100 korda pikali, jääb see 100 korda pikali. See on ikka odavam kui peatumine.

Valime jaotamiseks võtmed nii, et need jaguneksid normaalselt. Me ei taha, et meie võtmete räsi langeks ühte kitsasse vahemikku. See tähendab, et sünniaasta ülaltoodud näites on halb näide. Täpsemalt on hea, kui meie kasutajad jagunevad normaalselt sünniaastate järgi, ja halb, kui räägime 5. klassi õpilastest - seal ei tule partitsioonid väga head.

Sortimine valitakse üks kord rühmitusvõtme loomise etapis. Kui seda on vaja muuta, peame värskendama oma tabelit teise võtmega.

Ja mis kõige tähtsam: kui meil on vaja samu andmeid hankida 100 erineval viisil, siis on meil 100 erinevat tabelit.

Allikas: www.habr.com

Lisa kommentaar