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.
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.

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.

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 kÀivitame pÀringu testandmetel, on kÔik korras. Aga kui kÀivitate pÀringu tootmiskeskkonnas, kus meil on nÀiteks 4 miljonit kirjet, pole asjad nii head. Kuna filtreerimise lubamine on direktiiv, mis lubab Cassandral koguda kÔik selle tabeli andmed kÔigist sÔlmedest, kÔigist andmekeskused (kui selles klastris on neid palju) ja alles seejÀrel filtreeri need. See sarnaneb tÀieliku skaneerimisega ja ma kahtlen, et keegi sellest vaimustuses oleks.
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.

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
