Cassandra. Si të mos vdesësh nëse e di vetëm Oracle

Përshëndetje, Habr.

Më quajnë Misha Butrimov, dhe do të doja të flisja pak rreth Cassandra-s. Tregimi im do të jetë i dobishëm për ata që nuk kanë pasur asnjëherë përvojë me bazat e të dhënave NoSQL, pasi ka shumë veçori dhe pengesa të fshehura që duhet të njihni. Dhe nëse keni parë vetëm Oracle ose ndonjë bazë tjetër relacional, këto gjëra do t'ju shpëtojnë jetën.

ÇfarĂ« e bĂ«n Cassandra kaq tĂ« mirĂ«? Ajo Ă«shtĂ« njĂ« bazĂ« tĂ« dhĂ«nash NoSQL, e projektuar pa asnjĂ« pikĂ« tĂ« dĂ«shtimit, qĂ« shkallĂ«zohet mirĂ«. NĂ«se keni nevojĂ« tĂ« shtoni disa terabajt pĂ«r ndonjĂ« bazĂ«, thjesht shtoni node nĂ« rreth. DĂ«shironi ta zgjeroni atĂ« nĂ« njĂ« qendĂ«r tĂ« dhĂ«nash tjetĂ«r? Shtoni node nĂ« klaster. DĂ«shironi tĂ« rrisni RPS-nĂ« tuaj? Shtoni node nĂ« klaster. Punon gjithashtu nĂ« tĂ« kundĂ«rtĂ«n.

Cassandra. Si të mos vdesësh nëse e di vetëm Oracle

ÇfarĂ« ka tjetĂ«r ajo? Ajo Ă«shtĂ« e shkĂ«lqyer pĂ«r tĂ« procesuar shumĂ« kĂ«rkesa. Por shumĂ« Ă«shtĂ« sa? 10, 20, 30, 40 mijĂ« kĂ«rkesa nĂ« sekondĂ« — kjo Ă«shtĂ« pak. 100 mijĂ« kĂ«rkesa nĂ« sekondĂ« pĂ«r shkrim — gjithashtu. Ka kompani qĂ« kanĂ« thĂ«nĂ« se mbajnĂ« deri nĂ« 2 milion kĂ«rkesa nĂ« sekondĂ«. KĂ«tyre, ndoshta, duhet t'u besojmĂ«.

Dhe nĂ« principe, Cassandra ka njĂ« dallim tĂ« madh nga tĂ« dhĂ«nat relacional — ajo nuk i ngjan aspak atyre. Dhe kjo Ă«shtĂ« shumĂ« e rĂ«ndĂ«sishme pĂ«r t'u mbajtur mend.

Jo gjithçka që duket e njëjtë, funksionon njësoj.

Njëherë erdhi një koleg dhe më pyeti: «Këtu është gjuha e pyetjeve Cassandra (CQL), dhe ka një komandë select, ka një where, ka një and. Unë shkruaj shkronjat, dhe nuk punon. Pse?». Nëse e merrni Cassandra si një bazë të dhënash relacional, kjo është një mënyrë ideale për të përfunduar jetën tuaj në një vetëvrasje të dhunshme. Dhe nuk e propagandoj, është e ndaluar në Rusi. Thjesht do të projektosh diçka gabim.

Për shembull, një klient vjen dhe thotë: «Le të ndërtojmë një bazë të dhënash për serialet, ose një bazë të dhënash për një udhëzues receptesh. Do të kemi atje pjata me produkte ose një listë serialesh dhe aktorësh brenda». Ne themi me gëzim: «Le të bëjmë!» Kjo është dy byte për të dërguar, disa tabela dhe gjithçka është gati, do të funksionojë shumë shpejt, me besueshmëri. Dhe gjithçka është në rregull derisa klientët të vinë dhe të thonë se plakat e shtëpisë duan të zgjidhin gjithashtu problemin e kundërt: kanë një listë produktesh, dhe duan të dinë se cila pjatë duan të gatuan. Ju jeni të vdekur.

E gjithë kjo sepse Cassandra është një databazë hibride: ajo është njëkohësisht si key-value dhe ruan të dhënat në kolona të gjera. Nëse flasim në gjuhën Java ose Kotlin, mund ta përshkruajmë kështu:

Map<RowKey, SortedMap>

KĂ«shtu qĂ« kemi njĂ« mapĂ«, brenda sĂ« cilĂ«s ndodhet njĂ« mapĂ« tjetĂ«r e renditur. ÇelĂ«si i parĂ« i kĂ«saj mape Ă«shtĂ« Row key ose Partition key — çelĂ«si i partitimit. ÇelĂ«si i dytĂ«, i cili Ă«shtĂ« çelĂ«si pĂ«r mapĂ«n e renditur, Ă«shtĂ« Clustering key.

PĂ«r tĂ« ilustruar shpĂ«rndarjen e databazĂ«s, le tĂ« vizatojmĂ« tre nod. Tani duhet tĂ« kuptojmĂ« se si tĂ« shpĂ«rndajmĂ« tĂ« dhĂ«nat nĂ« nod. Sepse nĂ«se do tĂ« fusnim gjithçka nĂ« njĂ« (ato mund tĂ« jenĂ« njĂ« mijĂ«, dy mijĂ«, pesĂ« — sa tĂ« dojĂ«), kjo nuk Ă«shtĂ« shumĂ« lidhur me shpĂ«rndarjen. Prandaj, na nevojitet njĂ« funksion matematikor qĂ« do tĂ« kthente njĂ« numĂ«r. Thjesht njĂ« numĂ«r, njĂ« int tĂ« gjatĂ«, qĂ« do tĂ« bie nĂ« ndonjĂ« gamĂ«. Dhe njĂ« nod do tĂ« pĂ«rgjigjet pĂ«r njĂ« gamĂ«, tjetra — pĂ«r tĂ« dytĂ«n, n-ta — pĂ«r n-Ă«.

Cassandra. Si të mos vdesësh nëse e di vetëm Oracle

Ky numër merret nëpërmjet një funksioni hash, i cili aplikohet pikërisht në atë që quajmë Partition key. Ky është ai kolona që tregohet në direktivën Primary key, dhe ky është ai kolona që do të jetë çelësi i parë dhe më themelor i mape. Ai përcakton se cilat të dhëna do të shkojnë në cilën nod. Tabela krijohet në Cassandra pothuajse me të njëjtin sintaksë si në SQL:

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

)

Primary key në këtë rast përbëhet nga një kolonë, dhe ajo është gjithashtu çelësi i partitimit.

Si do të shpërndahen përdoruesit? Një pjesë do të përfundojë në një nod, një pjesë në tjetrën, dhe një pjesë në tretën. Ajo që rezulton është një tabelë e zakonshme hash, e cila është një mapë, e cila në Python është një fjalor, po ashtu është një strukturë e thjeshtë Key-value, nga e cila mund të lexojmë të gjitha vlerat, të lexojmë dhe të shkruajmë sipas çelësit.

Cassandra. Si të mos vdesësh nëse e di vetëm Oracle

Select: kur allow filtering shndërrohet në skanimin e plotë, ose si nuk duhet ta bëni

Le tĂ« shkruajmĂ« ndonjĂ« deklaratĂ« select: select * from users where userid = Duket se Ă«shtĂ« pikĂ«risht si nĂ« Oracle: shkruajmĂ« njĂ« select, caktojmĂ« kushtet dhe gjithçka funksionon, pĂ«rdoruesit nxirren. Por nĂ«se zgjedhim, pĂ«r shembull, njĂ« pĂ«rdorues me njĂ« vit tĂ« caktuar lindjeje, Cassandra ankohet qĂ« nuk mund ta ekzekutojĂ« kĂ«rkesĂ«n. Sepse ajo nuk di asgjĂ« rreth ndarjes sĂ« tĂ« dhĂ«nave pĂ«r vitin e lindjes — siç tregon, si çelĂ«s ka vetĂ«m njĂ« kolonĂ«. AtĂ«herĂ« ajo thotĂ«: "MirĂ«, mund tĂ« vazhdoj tĂ« ekzekutoj kĂ«tĂ« kĂ«rkesĂ«. Shtoni allow filtering". Ne e shtojmĂ« drejktivĂ«n, gjithçka funksionon. Dhe nĂ« atĂ« moment ndodh njĂ« e keqe.

Kur e testojmĂ« me tĂ« dhĂ«na testuese, gjithçka Ă«shtĂ« nĂ« rregull. Por kur ekzekutoni njĂ« kĂ«rkesĂ« nĂ« prodhim, ku kemi, pĂ«r shembull, 4 milion regjistra, atĂ«herĂ« gjithçka nuk shkon shumĂ« mirĂ«. Sepse allow filtering — Ă«shtĂ« njĂ« drejktivĂ« qĂ« i lejon Cassandra tĂ« mbledhĂ« tĂ« gjitha tĂ« dhĂ«nat nga kjo tabelĂ« nga tĂ« gjitha nodet, tĂ« gjitha qendrat e tĂ« dhĂ«nave (nĂ«se ka shumĂ« nĂ« kĂ«tĂ« grup), dhe pastaj filtron. Kjo Ă«shtĂ« si njĂ« Full Scan, dhe me siguri askush nuk Ă«shtĂ« i kĂ«naqur me tĂ«.

NĂ«se do na duheshin pĂ«rdoruesit vetĂ«m sipas identifikatorĂ«ve, do na pĂ«rshtatej. Por ndonjĂ«herĂ« na nevojitet tĂ« shkruajmĂ« kĂ«rkesa tĂ« tjera dhe tĂ« vendosim kufizime tĂ« tjera nĂ« ndarje. Prandaj, pĂ«rkujtojmĂ«: kjo Ă«shtĂ« njĂ« mapĂ«, e cila ka njĂ« çelĂ«s ndarĂ«s, por brenda saj — Ă«shtĂ« njĂ« mapĂ« e renditur.

Dhe ajo gjithashtu ka një çelës, të cilin e quajmë Clustering Key. Ky çelës, i cili, nga ana tjetër, përbëhet nga kolonat që ne do të zgjedhim, me të cilin Cassandra kupton se si të dhënat e saj do të renditen fizikisht dhe do të vendosen në çdo nodë. Pra, për një çelës ndarës, Clustering Key do të tregojë se si saktësisht të dhënat të futen në këtë pemë, çfarë vendi do të zënë aty.

ËshtĂ« vĂ«rtet njĂ« pemĂ«, aty thjesht thirret njĂ« komparator, nĂ« tĂ« cilin ne kalojmĂ« njĂ« set tĂ« caktuar kolonash si objekt, dhe ai gjithashtu caktuar nĂ« formĂ«n e enumerimit tĂ« kolonave.

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

Kujdesi nĂ« lidhje me direktivĂ«n Primary key, argumenti i saj i parĂ« (nĂ« rastin tonĂ« viti) gjithmonĂ« shkon si Partition key. Ai mund tĂ« pĂ«rbĂ«het nga njĂ« ose mĂ« shumĂ« kolona, kjo nuk ka rĂ«ndĂ«si. NĂ«se ka disa kolona, duhet ta vendosim pĂ«rsĂ«ri nĂ« kllapa, nĂ« mĂ«nyrĂ« qĂ« preprocessori i gjuhĂ«s tĂ« kuptojĂ« se kjo Ă«shtĂ« pikĂ«risht Primary key, ndĂ«rsa pas saj janĂ« tĂ« gjitha kolonat e tjera — Clustering key. NĂ« kĂ«tĂ« rast, ato do tĂ« kalohen nĂ« komparator nĂ« rendin nĂ« tĂ« cilin janĂ«. KĂ«shtu, kolona e parĂ« Ă«shtĂ« mĂ« e rĂ«ndĂ«sishme, e dyta — mĂ« pak e rĂ«ndĂ«sishme dhe kĂ«shtu me radhĂ«. Ashtu siç shkruajmĂ« pĂ«r data classes, pĂ«r shembull, fushat equals: rendisim fushat, dhe pĂ«r to shkruajmĂ« se cilat janĂ« mĂ« tĂ« mĂ«dha dhe cilat mĂ« tĂ« vogla. NĂ« Cassandra, kĂ«to janĂ«, nĂ« mĂ«nyrĂ« tĂ« kushtezuar, fushat e data class, pĂ«r tĂ« cilin do tĂ« aplikohet equals-i i shkruar pĂ«r tĂ«.

Vendosim renditjen, vendosim kufizimet

Duhet të mbani mend se rendi i renditjes (N decreasing, N increasing, nuk ka rëndësi) përcaktohet në momentin kur krijohet çelësi, dhe nuk do të jetë e mundur ta ndryshoni atë më vonë. Ai fizikisht përcakton se si do të klasifikohen të dhënat dhe se si do të jenë të vendosura. Nëse do të duhet të ndryshoni Clustering key ose rendin e renditjes, do të duhet të krijoni një tabelë të re dhe të derdhni të dhënat në të. Nuk do të mundesh kështu me tabelën ekzistuese.

Cassandra. Si të mos vdesësh nëse e di vetëm Oracle

Ne e mbushëm tabelën tonë me përdorues dhe përcaktuam se ata janë organizuar në një rreth fillimisht sipas vitit të lindjes, dhe më pas brenda çdo node sipas pagës dhe ID-së së përdoruesit. Tani mund të selektojmë, duke vendosur kufizime.

Rivjen prapĂ« funksionimi ynĂ« ku, dhe, dhe pĂ«rdoruesit na del, dhe gjithçka Ă«shtĂ« mirĂ« pĂ«rsĂ«ri. Por nĂ«se pĂ«rpiqemi tĂ« pĂ«rdorim vetĂ«m njĂ« pjesĂ« tĂ« Clustering key, dhe ajo Ă«shtĂ« mĂ« pak e rĂ«ndĂ«sishme, Cassandra do tĂ« protestojĂ« menjĂ«herĂ« se nuk mund tĂ« gjejĂ« nĂ« hartĂ«n tonĂ« vendin ku ndodhet ky objekt, i cili ka kĂ«to fusha pĂ«r komparimin null, dhe ky, qĂ« sapo e pĂ«rcaktuam, — ku ndodhet. MĂ« duhet tĂ« ngre pĂ«rsĂ«ri tĂ« gjitha tĂ« dhĂ«nat nga kjo nodĂ« dhe t'i filtroj ato. Dhe kjo Ă«shtĂ« analoge me Full Scan brenda nodĂ«s, Ă«shtĂ« e keqe.

Në çdo situatë të paqartë krijoni një tabelë të re

NĂ«se duam tĂ« jemi nĂ« gjendje tĂ« nxjerrim pĂ«rdoruesit sipas ID-sĂ«, moshĂ«s, ose pagĂ«s, çfarĂ« tĂ« bĂ«jmĂ«? AsgjĂ«. Thjesht pĂ«rdorim dy tabela. NĂ«se do tĂ« duhet tĂ« nxjerrim pĂ«rdoruesit nĂ« tri mĂ«nyra tĂ« ndryshme — do tĂ« kemi tre tabela. KohĂ«t kur kursonim hapĂ«sirĂ«n nĂ« disqet kanĂ« kaluar. Ky Ă«shtĂ« burimi mĂ« i lirĂ«. Ai kushton shumĂ« mĂ« pak se koha e pĂ«rgjigjes, e cila mund tĂ« jetĂ« fatale pĂ«r pĂ«rdoruesin. PĂ«rdoruesit ndihen mĂ« mirĂ« tĂ« marrin diçka brenda njĂ« sekonde sesa brenda 10 minutash.

Ne shkëmbejmë hapësirën e tepërt që zënë të dhënat denormalizuara për mundësinë e një shkallëzimi të mirë dhe funksionimi të sigurt. Së vërtetë, një kluster që përbëhet nga tre qendra të dhënash, secila me pesë nodë, me një nivel të pranueshëm të ruajtjes së të dhënave (kur nuk humbet asgjë), është në gjendje të mbijetojë shkatërrimin e një qendre të dhënash tërësisht. Dhe akoma dy nodë në secilën nga dy qendrat e tjera. Dhe vetëm pas kësaj do të fillojnë problemet. Kjo është një rezervim mjaft i mirë, i cili kushton disa SSD të tepërta dhe procese. Prandaj, për të përdorur Cassandra, e cila nuk është SQL asnjëherë, në të cilën nuk ka marrëdhënie, çelësa të jashtëm, duhet të dihet rregullat e thjeshta.

Ne e projektojmë gjithçka nga kërkesa. Ajo që është e rëndësishme nuk janë të dhënat, por si aplikacioni do të punojë me to. Nëse ai duhet të marrë të dhëna të ndryshme në mënyra të ndryshme apo të njëjtat të dhëna në mënyra të ndryshme, ne duhet t'i vendosim ato në mënyrë që të jetë e qartë për aplikacionin. Në të kundërt, do të bie në Full Scan dhe asnjë avantazh nga Cassandra nuk do të na ndihmojë.

Denormalizimi i të dhënave është norma. Harrojmë për format normale, tani nuk kemi më baza rrelacionale. Nëse vendosim diçka 100 herë, ajo do të jetë aty 100 herë. Kjo është gjithsesi më e lirë sesa të ngadalësohemi.

Zgjidhim çelĂ«sat pĂ«r partitimin nĂ« mĂ«nyrĂ« qĂ« ato tĂ« shpĂ«rndahen normalisht. Nuk na nevojitet qĂ« hash i çelĂ«save tanĂ« tĂ« bjerĂ« nĂ« njĂ« interval tĂ« ngushtĂ«. Pra, viti i lindjes nĂ« shembullin e mĂ«sipĂ«rm — Ă«shtĂ« njĂ« shembull jo i mirĂ«. NĂ« tĂ« vĂ«rtetĂ«, ai Ă«shtĂ« i mirĂ«, nĂ«se pĂ«rdoruesit janĂ« tĂ« shpĂ«rndarĂ« normalisht sipas vitit tĂ« lindjes, dhe i keq, nĂ«se flasim pĂ«r nxĂ«nĂ«sit e klasĂ«s sĂ« pestĂ« — atje nuk do tĂ« jetĂ« aq mirĂ« pĂ«r partitimin.

Sortezimi zgjidhet një herë në fazën e krijimit të Clustering Key. Nëse nevojitet ta ndryshojmë atë, do të duhet të derdhim tabelën tonë me një çelës tjetër.

Dhe më e rëndësishmja: nëse na nevojiten 100 mënyra të ndryshme për të marrë të njëjtat të dhëna, do të kemi 100 tabela të ndryshme.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster