Cassandra. Hvordan ikke dø hvis du bare kjenner Oracle

Hei Habr.

Jeg heter Misha Butrimov, jeg vil gjerne fortelle deg litt om Cassandra. Historien min vil være nyttig for de som aldri har støtt på NoSQL-databaser – den har mange implementeringsfunksjoner og fallgruver du trenger å vite om. Og hvis du ikke har sett noe annet enn Oracle eller en annen relasjonsdatabase, vil disse tingene redde livet ditt.

Hva er så bra med Cassandra? Det er en NoSQL-database designet uten et eneste feilpunkt som skaleres godt. Hvis du trenger å legge til et par terabyte for en database, legger du ganske enkelt til noder i ringen. Vil du utvide det til et annet datasenter? Legg til noder i klyngen. Øke behandlet RPS? Legg til noder i klyngen. Det fungerer også i motsatt retning.

Cassandra. Hvordan ikke dø hvis du bare kjenner Oracle

Hva annet er hun god på? Det handler om å håndtere mange forespørsler. Men hvor mye er mye? 10, 20, 30, 40 tusen forespørsler per sekund er ikke mye. 100 tusen forespørsler per sekund for opptak - også. Det er selskaper som sa at de beholder 2 millioner forespørsler per sekund. De må nok tro det.

Og i prinsippet har Cassandra én stor forskjell fra relasjonsdata – den ligner ikke på dem i det hele tatt. Og dette er veldig viktig å huske.

Ikke alt som ser likt ut fungerer likt

En gang kom en kollega til meg og spurte: "Her er et CQL Cassandra-spørringsspråk, og det har en select-setning, det har hvor, det har og. Jeg skriver brev og det går ikke. Hvorfor?". Å behandle Cassandra som en relasjonsdatabase er den perfekte måten å begå voldelig selvmord på. Og jeg promoterer det ikke, det er forbudt i Russland. Du vil bare designe noe feil.

For eksempel kommer en kunde til oss og sier: «La oss bygge en database for TV-serier, eller en database for en oppskriftskatalog. Vi vil ha matretter der eller en liste over TV-serier og skuespillere i den.» Vi sier glad: "La oss gå!" Bare send to byte, et par tegn og du er ferdig, alt vil fungere veldig raskt og pålitelig. Og alt er bra helt til kundene kommer og sier at husmødre også løser det motsatte problemet: de har en liste over produkter, og de vil vite hvilken rett de vil lage. Du er død.

Dette er fordi Cassandra er en hybrid database: den gir samtidig en nøkkelverdi og lagrer data i brede kolonner. I Java eller Kotlin kan det beskrives slik:

Map<RowKey, SortedMap<ColumnKey, ColumnValue>>

Det vil si et kart som også inneholder et sortert kart. Den første nøkkelen til dette kartet er radtasten eller partisjonsnøkkelen - partisjoneringsnøkkelen. Den andre nøkkelen, som er nøkkelen til et allerede sortert kart, er Clustering-nøkkelen.

For å illustrere distribusjonen av databasen, la oss tegne tre noder. Nå må du forstå hvordan du dekomponerer dataene til noder. For hvis vi stapper alt i ett (det kan forresten bli tusen, to tusen, fem – så mange du vil), så handler ikke dette egentlig om distribusjon. Derfor trenger vi en matematisk funksjon som vil returnere et tall. Bare et tall, en lang int som vil falle innenfor et eller annet område. Og vi vil ha en node ansvarlig for ett område, den andre for den andre, den n-te for den n-te.

Cassandra. Hvordan ikke dø hvis du bare kjenner Oracle

Dette nummeret er tatt ved hjelp av en hash-funksjon, som brukes på det vi kaller partisjonsnøkkelen. Dette er kolonnen som er spesifisert i Primærnøkkeldirektivet, og dette er kolonnen som vil være den første og mest grunnleggende nøkkelen på kartet. Den bestemmer hvilken node som skal motta hvilke data. En tabell lages i Cassandra med nesten samme syntaks som i SQL:

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

)

Primærnøkkelen i dette tilfellet består av én kolonne, og det er også partisjoneringsnøkkelen.

Hvordan vil brukerne våre prestere? Noen vil gå til en node, noen til en annen, og noen til en tredje. Resultatet er en vanlig hashtabell, også kjent som et kart, også kjent som en ordbok i Python, eller en enkel nøkkelverdistruktur som vi kan lese alle verdiene fra, lese og skrive for nøkkel.

Cassandra. Hvordan ikke dø hvis du bare kjenner Oracle

Velg: når tillat filtrering blir til full skanning, eller hva du ikke skal gjøre

La oss skrive et utvalgt utsagn: select * from users where, userid = . Det viser seg som i Oracle: vi skriver select, spesifiserer betingelsene og alt fungerer, brukerne får det. Men hvis du velger for eksempel en bruker med et visst fødselsår, klager Cassandra over at den ikke kan oppfylle forespørselen. Fordi hun ikke vet noe i det hele tatt om hvordan vi fordeler data om fødselsåret - hun har bare én kolonne angitt som nøkkel. Så sier hun: «Ok, jeg kan fortsatt oppfylle denne forespørselen. Legg til tillat filtrering." Vi legger til direktivet, alt fungerer. Og i dette øyeblikket skjer noe forferdelig.

Når vi kjører på testdata er alt i orden. Og når du utfører en spørring i produksjon, hvor vi for eksempel har 4 millioner poster, så er ikke alt veldig bra for oss. Fordi tillat filtrering er et direktiv som lar Cassandra samle alle data fra denne tabellen fra alle noder, alle datasentre (hvis det er mange av dem i denne klyngen), og først deretter filtrere den. Dette er en analog av Full Scan, og knapt noen er fornøyd med den.

Hvis vi bare trengte brukere etter ID, ville vi klare dette. Men noen ganger må vi skrive andre spørsmål og legge andre begrensninger på utvalget. Derfor husker vi: alt dette er et kart som har en partisjoneringsnøkkel, men inni det er et sortert kart.

Og hun har også en nøkkel, som vi kaller Clustering Key. Denne nøkkelen, som igjen består av kolonnene vi velger, ved hjelp av hvilken Cassandra forstår hvordan dataene er fysisk sortert og vil bli plassert på hver node. Det vil si at for en partisjonsnøkkel vil Clustering-nøkkelen fortelle deg nøyaktig hvordan du skyver dataene inn i dette treet, hvilken plass de vil ta der.

Dette er egentlig et tre, en komparator kalles ganske enkelt der, som vi sender et bestemt sett med kolonner til i form av et objekt, og det er også spesifisert som en liste over kolonner.

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

Vær oppmerksom på primærnøkkeldirektivet; dets første argument (i vårt tilfelle, året) er alltid partisjonsnøkkel. Den kan bestå av en eller flere kolonner, det spiller ingen rolle. Hvis det er flere kolonner, må det fjernes i parentes igjen slik at språkforbehandleren forstår at dette er primærnøkkelen, og bak den er alle de andre kolonnene Clustering-nøkkelen. I dette tilfellet vil de bli overført i komparatoren i den rekkefølgen de vises. Det vil si at den første kolonnen er mer signifikant, den andre er mindre betydningsfull, og så videre. Hvordan vi skriver, er for eksempel lik felt for dataklasser: vi lister opp feltene, og for dem skriver vi hvilke som er større og hvilke som er mindre. I Cassandra er dette relativt sett feltene til dataklassen, som likeverdighetene som er skrevet for den vil bli brukt på.

Vi setter sortering og legger begrensninger

Du må huske at sorteringsrekkefølgen (synkende, stigende, hva som helst) settes i samme øyeblikk som nøkkelen opprettes, og den kan ikke endres senere. Det bestemmer fysisk hvordan dataene skal sorteres og hvordan de skal lagres. Hvis du trenger å endre grupperingsnøkkelen eller sorteringsrekkefølgen, må du opprette en ny tabell og overføre data til den. Dette vil ikke fungere med en eksisterende.

Cassandra. Hvordan ikke dø hvis du bare kjenner Oracle

Vi fylte bordet vårt med brukere og så at de falt i en ring, først etter fødselsår, og deretter inne på hver node etter lønn og bruker-ID. Nå kan vi velge ved å pålegge restriksjoner.

Vår arbeidende dukker opp igjen where, and, og vi får brukere, og alt er bra igjen. Men hvis vi prøver å bruke bare en del av Clustering-nøkkelen, og en mindre signifikant, så vil Cassandra umiddelbart klage over at den ikke kan finne stedet på kartet vårt hvor dette objektet, som har disse feltene for null-komparatoren, og denne det var bare satt , - hvor han ligger. Jeg må hente opp alle dataene fra denne noden igjen og filtrere den. Og dette er en analog av Full Scan i en node, dette er dårlig.

I enhver uklar situasjon, opprett en ny tabell

Hvis vi ønsker å kunne målrette brukere etter ID, eller etter alder, eller etter lønn, hva skal vi gjøre? Ingenting. Bare bruk to bord. Hvis du trenger å nå brukere på tre forskjellige måter, vil det være tre tabeller. Borte er dagene da vi sparte plass på skruen. Dette er den billigste ressursen. Det koster mye mindre enn responstid, noe som kan være skadelig for brukeren. Det er mye mer behagelig for brukeren å motta noe på et sekund enn på 10 minutter.

Vi bytter unødvendig plass og denormaliserte data for evnen til å skalere godt og operere pålitelig. Tross alt, faktisk, en klynge som består av tre datasentre, som hver har fem noder, med et akseptabelt nivå av databevaring (når ingenting går tapt), er i stand til å overleve døden til ett datasenter fullstendig. Og ytterligere to noder i hver av de resterende to. Og først etter dette begynner problemene. Dette er en ganske god redundans, den er verdt et par ekstra SSD-stasjoner og prosessorer. Derfor, for å bruke Cassandra, som aldri er SQL, der det ikke er noen relasjoner, fremmednøkler, må du kjenne til enkle regler.

Vi designer alt etter din forespørsel. Det viktigste er ikke dataene, men hvordan applikasjonen skal fungere med dem. Hvis den trenger å motta forskjellige data på forskjellige måter eller samme data på forskjellige måter, må vi sette dem på en måte som er praktisk for applikasjonen. Ellers vil vi mislykkes i Full Scan og Cassandra vil ikke gi oss noen fordel.

Denormalisering av data er normen. Vi glemmer normale former, vi har ikke lenger relasjonsdatabaser. Legger vi ned noe 100 ganger, vil det legge seg 100 ganger. Det er fortsatt billigere enn å stoppe.

Vi velger nøklene for partisjonering slik at de distribueres normalt. Vi vil ikke at hashen til nøklene våre skal falle i ett smalt område. Det vil si at fødselsåret i eksemplet ovenfor er et dårlig eksempel. Mer presist er det bra om brukerne våre er normalfordelt etter fødselsår, og dårlig om vi snakker om 5. klasseelever – partisjonen der blir ikke særlig god.

Sortering velges én gang ved opprettelse av klyngenøkkel. Hvis det må endres, må vi oppdatere tabellen med en annen nøkkel.

Og det viktigste: Hvis vi trenger å hente de samme dataene på 100 forskjellige måter, vil vi ha 100 forskjellige tabeller.

Kilde: www.habr.com

Legg til en kommentar