HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Den næste HighLoad++ konference afholdes den 6. og 7. april 2020 i St. Petersborg.
Detaljer og billetter по ссылке. HighLoad++ Sibirien 2019. Hal "Krasnoyarsk". 25. juni klokken 12. Specialer og præsentation.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Det sker, at praktiske krav er i konflikt med teori, hvor aspekter vigtige for et kommercielt produkt ikke tages i betragtning. Dette foredrag præsenterer en proces til at udvælge og kombinere forskellige tilgange til at skabe kausal sammenhængskomponenter baseret på akademisk forskning baseret på kravene til et kommercielt produkt. Lytterne vil lære om eksisterende teoretiske tilgange til logiske ure, afhængighedssporing, systemsikkerhed, klokkesynkronisering og hvorfor MongoDB slog sig ned på bestemte løsninger.

Mikhail Tyulenev (i det følgende benævnt MT): – Jeg vil tale om årsagssammenhæng - det er en funktion, vi har arbejdet på i MongoDB. Jeg arbejder i en gruppe af distribuerede systemer, vi gjorde det for omkring to år siden.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

I processen var jeg nødt til at sætte mig ind i en masse akademisk forskning, fordi denne funktion er blevet studeret ret godt. Det viste sig, at ikke en eneste artikel passer ind i, hvad der kræves i en produktionsdatabase på grund af meget specifikke krav, som sandsynligvis er til stede i enhver produktionsapplikation.

Jeg vil fortælle om, hvordan vi som forbrugere af akademisk forskning tilbereder noget ud fra det, som vi så kan præsentere for vores brugere som en færdigret, der er praktisk og sikker at bruge.

Årsagskonsistens. Lad os definere begreberne

Til at begynde med vil jeg sige i generelle vendinger, hvad kausal konsistens er. Der er to karakterer - Leonard og Penny (tv-serien "The Big Bang Theory"):

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Lad os sige, at Penny er i Europa, og Leonard vil holde hende til en overraskelsesfest. Og han kan ikke komme i tanke om noget bedre end at smide hende fra sin venneliste og sende alle sine venner en opdatering på feedet: "Lad os gøre Penny glad!" (hun er i Europa, mens hun sover, hun ser ikke alt dette og kan ikke se det, fordi hun ikke er der). I sidste ende sletter hun dette indlæg, sletter det fra feedet og gendanner adgangen, så hun ikke bemærker noget, og der er ingen skandale.
Det er alt sammen godt og vel, men lad os antage, at systemet er distribueret og det gik lidt galt. Det kan for eksempel ske, at Pennys adgangsbegrænsning opstod, efter at dette indlæg dukkede op, hvis begivenhederne ikke er relateret til årsag og virkning. Faktisk er dette et eksempel på, hvornår kausal sammenhæng er påkrævet for at udføre en forretningsfunktion (i dette tilfælde).

Faktisk er disse ganske ikke-trivielle egenskaber ved databasen - meget få mennesker støtter dem. Lad os gå videre til modellerne.

Konsistensmodeller

Hvad er egentlig en konsistensmodel i databaser? Det er nogle af de garantier, som et distribueret system giver om, hvilke data klienten kan modtage og i hvilken rækkefølge.

I princippet kommer alle konsistensmodeller ned på, hvor ens et distribueret system er et system, der for eksempel kører på én node på en bærbar computer. Og sådan ligner et system, der kører på tusindvis af geo-distribuerede "Noder", til en bærbar computer, hvor alle disse egenskaber i princippet udføres automatisk.

Derfor anvendes konsistensmodeller kun på distribuerede systemer. Alle systemer, der tidligere eksisterede og fungerede i samme vertikale skala, oplevede ikke sådanne problemer. Der var én Buffer Cache, og alt blev altid læst fra den.

Model Stærk

Faktisk er den allerførste model Strong (eller rise ability line, som det ofte kaldes). Dette er en konsistensmodel, der sikrer, at hver ændring, når den er bekræftet, at den er sket, er synlig for alle brugere af systemet.

Dette skaber en global rækkefølge af alle hændelser i databasen. Dette er en meget stærk konsistensegenskab, og den er generelt meget dyr. Det er dog meget godt understøttet. Den er bare meget dyr og langsom – den bliver bare sjældent brugt. Dette kaldes stigeevne.

Der er en anden, stærkere egenskab, der understøttes i Spanner - kaldet Ekstern Konsistens. Vi taler om det lidt senere.

Causal

Den næste er Causal, hvilket er præcis, hvad jeg talte om. Der er flere underniveauer mellem Strong og Causal, som jeg ikke vil tale om, men de koger alle ned til Causal. Dette er en vigtig model, fordi den er den stærkeste af alle modeller, den stærkeste sammenhæng i tilstedeværelsen af ​​et netværk eller partitioner.

Årsagssammenhænge er faktisk en situation, hvor hændelser er forbundet med en årsag-virkning-sammenhæng. Meget ofte opfattes de som Læs dine rettigheder fra kundens synspunkt. Hvis klienten har observeret nogle værdier, kan han ikke se værdier, der var i fortiden. Han er allerede begyndt at se præfiksaflæsninger. Det hele kommer ned til det samme.
Causals som konsistensmodel er en delvis rækkefølge af hændelser på serveren, hvor hændelser fra alle klienter observeres i samme rækkefølge. I dette tilfælde Leonard og Penny.

eventuel

Den tredje model er Eventuel Konsistens. Dette er, hvad absolut alle distribuerede systemer understøtter, den minimale model, der overhovedet giver mening. Det betyder følgende: Når vi har nogle ændringer i dataene, bliver de på et tidspunkt konsistente.

I sådan et øjeblik siger hun ikke noget, ellers ville hun blive til Ekstern Konsistens - det ville være en helt anden historie. Ikke desto mindre er dette en meget populær model, den mest almindelige. Som standard bruger alle brugere af distribuerede systemer Eventuel Konsistens.

Jeg vil gerne give nogle komparative eksempler:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Hvad betyder disse pile?

  • Reaktionstid. Efterhånden som konsistensstyrken øges, bliver den større af indlysende årsager: du skal lave flere poster, få bekræftelse fra alle værter og noder, der deltager i klyngen, at dataene allerede er der. Følgelig har Eventual Consistency det hurtigste svar, for der kan du som regel endda forpligte det til hukommelsen, og det vil i princippet være nok.
  • Tilgængelighed. Hvis vi forstår dette som systemets evne til at reagere i nærvær af netværksbrud, partitioner eller en eller anden form for fejl, øges fejltolerancen, efterhånden som konsistensmodellen falder, da det er nok for os, at én vært lever og samtidig tiden producerer nogle data. Eventual Consistency garanterer overhovedet ikke noget om dataene – det kan være hvad som helst.
  • Anomalier. Samtidig stiger antallet af anomalier naturligvis. I Strong Consistency burde de næsten slet ikke eksistere, men i Eventual Consistency kan de være hvad som helst. Spørgsmålet opstår: hvorfor vælger folk eventuel konsistens, hvis det indeholder anomalier? Svaret er, at Eventual Consistency-modeller er anvendelige, og der findes anomalier, f.eks. i løbet af kort tid; det er muligt at bruge guiden til at læse og mere eller mindre læse konsistente data; Det er ofte muligt at bruge stærke konsistensmodeller. I praksis virker dette, og ofte er antallet af anomalier begrænset i tid.

CAP-sætning

Når du ser ordene konsistens, tilgængelighed – hvad tænker du på? Det er rigtigt - CAP-sætning! Nu vil jeg aflive myten... Det er ikke mig - det er Martin Kleppmann, der har skrevet en vidunderlig artikel, en vidunderlig bog.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

CAP-sætningen er et princip formuleret i 2000'erne om, at Konsistens, Tilgængelighed, Partitioner: tag to, og du kan ikke vælge tre. Det var et vist princip. Det blev bevist som et teorem et par år senere af Gilbert og Lynch. Så begyndte dette at blive brugt som et mantra - systemer begyndte at blive opdelt i CA, CP, AP og så videre.

Denne teorem blev faktisk bevist for følgende tilfælde... For det første blev tilgængelighed ikke betragtet som en kontinuerlig værdi fra nul til hundreder (0 - systemet er "dødt", 100 - reagerer hurtigt; vi er vant til at betragte det på den måde) , men som en egenskab ved algoritmen , som garanterer, at den for alle dens udførelser returnerer data.

Der er slet ikke et ord om responstid! Der findes en algoritme, der returnerer data efter 100 år – en helt vidunderlig tilgængelig algoritme, som er en del af CAP-sætningen.
For det andet: teoremet blev bevist for ændringer i værdierne af den samme nøgle, på trods af at disse ændringer kan ændres. Det betyder, at de i virkeligheden praktisk talt ikke bruges, fordi modellerne er forskellige Eventuel Konsistens, Stærk Konsistens (måske).

Hvad er alt dette til for? Desuden er CAP-sætningen i nøjagtig den form, som den blev bevist, praktisk talt ikke anvendelig og bruges sjældent. I teoretisk form begrænser det på en eller anden måde alt. Det viser sig et vist princip, der er intuitivt korrekt, men som generelt ikke er blevet bevist.

Kausal konsistens er den stærkeste model

Det, der sker nu, er, at du kan få alle tre ting: Konsistens, Tilgængelighed ved hjælp af partitioner. Især Causal konsistens er den stærkeste konsistensmodel, som stadig fungerer i nærvær af partitioner (brud i netværket). Derfor har det så stor interesse, og derfor tog vi det op.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

For det første forenkler det arbejdet for applikationsudviklere. Især tilstedeværelsen af ​​stor support fra serveren: når alle poster, der forekommer inde i en klient, garanteres at ankomme i samme rækkefølge på en anden klient. For det andet tåler den skillevægge.

MongoDB indvendigt køkken

Idet vi husker, at det er frokost, går vi ud i køkkenet. Jeg vil fortælle dig om systemmodellen, nemlig hvad MongoDB er for dem, der hører om sådan en database for første gang.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

MongoDB (herefter benævnt "MongoDB") er et distribueret system, der understøtter horisontal skalering, det vil sige sharding; og inden for hvert shard understøtter det også dataredundans, det vil sige replikering.

Sharding i MongoDB (ikke en relationsdatabase) udfører automatisk balancering, det vil sige, at hver samling af dokumenter (eller "tabel" med hensyn til relationelle data) er opdelt i stykker, og serveren flytter dem automatisk mellem shards.

Forespørgselsrouteren, som distribuerer anmodninger til en klient, er en klient, som den fungerer igennem. Den ved allerede, hvor og hvilke data der er placeret og sender alle anmodninger til det korrekte shard.

Et andet vigtigt punkt: MongoDB er en enkelt master. Der er én primær - den kan tage poster, der understøtter de nøgler, den indeholder. Du kan ikke skrive Multi-master.

Vi lavede release 4.2 - nye interessante ting dukkede op der. Især indsatte de Lucene - søg - nemlig eksekverbar java direkte i Mongo, og der blev det muligt at udføre søgninger gennem Lucene, det samme som i Elastica.

Og de lavede et nyt produkt - Charts, det er også tilgængeligt på Atlas (Mongos egen Cloud). De har et gratis niveau - du kan lege med det. Jeg kunne virkelig godt lide diagrammer - datavisualisering, meget intuitiv.

Ingredienser Årsagskonsistens

Jeg talte omkring 230 artikler, der er blevet publiceret om dette emne - fra Leslie Lampert. Nu fra min hukommelse vil jeg formidle nogle dele af disse materialer til dig.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Det hele startede med en artikel af Leslie Lampert, som blev skrevet i 1970'erne. Som du kan se, er nogle undersøgelser af dette emne stadig i gang. Nu oplever Causal konsistens interesse i forbindelse med udvikling af distribuerede systemer.

Begrænsninger

Hvilke begrænsninger er der? Det er faktisk en af ​​hovedpointerne, for de begrænsninger, som et produktionssystem pålægger, er meget forskellige fra de begrænsninger, der findes i akademiske artikler. De er ofte ret kunstige.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

  • For det første er "MongoDB" en enkelt mester, som jeg allerede sagde (dette forenkler meget).
  • Vi mener, at systemet skal understøtte omkring 10 tusinde shards. Vi kan ikke træffe nogen arkitektoniske beslutninger, der eksplicit vil begrænse denne værdi.
  • Vi har en sky, men vi antager, at en person stadig skal have muligheden, når han downloader binær, kører den på sin bærbare computer, og alt fungerer fantastisk.
  • Vi antager noget, som Research sjældent antager: eksterne kunder kan gøre, hvad de vil. MongoDB er open source. Derfor kan klienter være så smarte og vrede - de kan ønske at bryde alt. Vi spekulerer i, at byzantinske feilors kan stamme fra.
  • For eksterne klienter, der er uden for perimeteren, er der en vigtig begrænsning: Hvis denne funktion er deaktiveret, bør der ikke observeres nogen ydeevneforringelse.
  • Et andet punkt er generelt anti-akademisk: kompatibiliteten af ​​tidligere versioner og fremtidige. Gamle drivere skal understøtte nye opdateringer, og databasen skal understøtte gamle drivere.

Generelt pålægger alt dette begrænsninger.

Årsagskonsistenskomponenter

Jeg vil nu tale om nogle af komponenterne. Hvis vi overvejer kausal konsistens generelt, kan vi vælge blokke. Vi valgte blandt værker, der hører til en bestemt blok: Afhængighedssporing, valg af ure, hvordan disse ure kan synkroniseres med hinanden, og hvordan vi sikrer sikkerhed - dette er en grov oversigt over, hvad jeg vil tale om:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Fuld afhængighedssporing

Hvorfor er det nødvendigt? Så når data replikeres, indeholder hver post, hver dataændring information om, hvilke ændringer den afhænger af. Den allerførste og naive ændring er, når hver besked, der indeholder en post, indeholder information om tidligere beskeder:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

I dette eksempel er tallet i krøllede parenteser rekordtallene. Nogle gange overføres disse poster med værdier endda i deres helhed, nogle gange overføres nogle versioner. Den nederste linje er, at hver ændring indeholder information om den foregående (selvfølgelig bærer alt dette i sig selv).

Hvorfor besluttede vi ikke at bruge denne tilgang (fuld sporing)? Det er klart, fordi denne tilgang er upraktisk: enhver ændring af et socialt netværk afhænger af alle tidligere ændringer af det sociale netværk, overførsel af f.eks. Facebook eller VKontakte i hver opdatering. Ikke desto mindre er der en masse forskning om fuld afhængighedssporing - disse er præ-sociale netværk; i nogle situationer virker det virkelig.

Eksplicit afhængighedssporing

Den næste er mere begrænset. Her tages der også hensyn til overførsel af information, men kun det, der er klart afhængigt. Hvad afhænger af hvad, er som udgangspunkt bestemt af Ansøgningen. Når data replikeres, returnerer forespørgslen kun svar, når tidligere afhængigheder er blevet opfyldt, dvs. vist. Dette er essensen af, hvordan kausal konsistens virker.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Hun ser, at post 5 afhænger af post 1, 2, 3, 4 - derfor venter hun, før klienten har adgang til de ændringer, der er foretaget af Pennys adgangsbeslutning, når alle tidligere ændringer allerede er passeret gennem databasen.

Det passer os heller ikke, for der er stadig for meget information, og det vil bremse tingene. Der er en anden tilgang...

Lamport ur

De er meget gamle. Lamport Clock betyder, at disse afhængigheder er foldet til en skalar funktion, som kaldes Lamport Clock.

En skalarfunktion er et abstrakt tal. Det kaldes ofte logisk tid. Med hver begivenhed øges denne tæller. Tælleren, som i øjeblikket er kendt af processen, sender hver besked. Det er klart, at processer kan være ude af sync, de kan have helt andre tidspunkter. Ikke desto mindre balancerer systemet på en eller anden måde uret med sådanne beskeder. Hvad sker der i dette tilfælde?

Jeg delte det store skår i to for at gøre det klart: Venner kan bo i én node, som indeholder en del af samlingen, og Feed kan bo i en anden node, som indeholder en del af denne samling. Er det klart, hvordan de kan komme ud af køen? First Feed vil sige: "Replikeret", og derefter Friends. Hvis systemet ikke giver en eller anden form for garanti for, at feedet ikke bliver vist, før Friends-afhængighederne i Friends-samlingen også er leveret, så vil vi have præcis den situation, som jeg nævnte.

Du ser, hvordan tællertiden på Feed logisk stiger:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Så hovedegenskaben ved dette Lamport-ur og årsagssammenhæng (forklaret gennem Lamport-uret) er dette: hvis vi har hændelser A og B, og hændelse B afhænger af hændelse A*, så følger det, at den logiske tid for hændelse A er mindre end end LogicalTime fra Event B.

* Nogle gange siger de også, at A skete før B, det vil sige, at A skete før B - dette er en bestemt relation, der delvist ordner hele det sæt af hændelser, der skete generelt.

Det modsatte er forkert. Dette er faktisk en af ​​de største ulemper ved Lamport Clock - delvis rækkefølge. Der er et begreb om samtidige hændelser, det vil sige hændelser, hvor hverken (A skete før B) eller (A skete før B). Et eksempel ville være Leonards parallelle tilføjelse af en anden som ven (ikke engang Leonard, men Sheldon, for eksempel).
Dette er den egenskab, der ofte bruges, når man arbejder med Lamport-ure: de ser specifikt på funktionen, og ud fra dette konkluderer de, at disse begivenheder måske er afhængige. Fordi én måde er sand: hvis LogicalTime A er mindre end LogicalTime B, så kan B ikke ske før A; og hvis mere, så måske.

Vektor ur

Den logiske udvikling af Lamport-uret er Vector Clock. De adskiller sig ved, at hver knude, der er her, indeholder sit eget separate ur, og de transmitteres som en vektor.
I dette tilfælde kan du se, at vektorens nulte indeks er ansvarlig for Feed, og det første indeks af vektoren er for Friends (hver af disse noder). Og nu vil de stige: nulindekset for "Feed" stiger, når du skriver - 1, 2, 3:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Hvorfor er Vector Clock bedre? Fordi de giver dig mulighed for at finde ud af, hvilke begivenheder der er samtidige, og hvornår de opstår på forskellige noder. Dette er meget vigtigt for et sharding-system som MongoDB. Det valgte vi dog ikke, selvom det er en skøn ting, og den fungerer fantastisk, og den ville nok passe os...

Hvis vi har 10 tusinde shards, kan vi ikke overføre 10 tusinde komponenter, selvom vi komprimerer det eller finder på noget andet - nyttelasten vil stadig være flere gange mindre end volumen af ​​hele denne vektor. Derfor, mens vi bider vores hjerter og tænder, opgav vi denne tilgang og gik videre til en anden.

Skruenøgle TrueTime. Atomur

Jeg sagde, at der ville være en historie om Spanner. Dette er en cool ting, lige ud af det XNUMX. århundrede: atomure, GPS-synkronisering.

Hvad er ideen? "Spanner" er et Google-system, der for nylig endda blev tilgængeligt for folk (de tilføjede SQL til det). Hver transaktion der har et tidsstempel. Da tiden er synkroniseret*, kan hver hændelse tildeles en bestemt tid - atomure har en ventetid, hvorefter en anden tid garanteres at "ske".

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Således, ved blot at skrive til databasen og vente i et stykke tid, garanteres begivenhedens serialiseringsevne automatisk. De har den stærkeste Konsistens-model, man i princippet kan forestille sig – det er Ekstern Konsistens.

* Dette er hovedproblemet med Lampart ure - de er aldrig synkrone på distribuerede systemer. De kan afvige; selv med NTP fungerer de stadig ikke særlig godt. "Spanner" har et atomur og synkronisering, ser det ud til, er mikrosekunder.

Hvorfor valgte vi ikke? Vi antager ikke, at vores brugere har et indbygget atomur. Når de dukker op, og er indbygget i hver bærbar, vil der være en slags superfed GPS-synkronisering - så ja... Men indtil videre er det bedste, der er muligt, Amazon, Base Stations - for fanatikere... Så vi brugte andre ure .

Hybrid ur

Det er faktisk det, der tikker i MongoDB, når man sikrer kausal konsistens. Hvordan er de hybrider? Hybrid er en skalarværdi, men den har to komponenter:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

  • Den første er Unix-epoken (hvor mange sekunder er der gået siden "begyndelsen af ​​computerverdenen").
  • Den anden er en stigning, også en 32-bit usigneret int.

Det er alt, faktisk. Der er denne tilgang: den del, der er ansvarlig for tiden, er synkroniseret med uret hele tiden; hver gang der sker en opdatering, synkroniseres denne del med uret, og det viser sig, at klokkeslættet altid er mere eller mindre korrekt, og inkrement giver dig mulighed for at skelne mellem hændelser, der fandt sted på samme tidspunkt.

Hvorfor er dette vigtigt for MongoDB? Fordi det giver dig mulighed for at lave en slags backup-restauranter på et bestemt tidspunkt, det vil sige, at begivenheden indekseres efter tid. Dette er vigtigt, når der er behov for visse begivenheder; For en database er hændelser ændringer i databasen, der skete med bestemte tidsintervaller.

Jeg vil kun fortælle dig den vigtigste grund til dig (vær venlig, fortæl det ikke til nogen)! Vi gjorde dette, fordi det er sådan organiserede, indekserede data ser ud i MongoDB OpLog. OpLog er en datastruktur, der indeholder absolut alle ændringer i databasen: de går først til OpLog, og derefter anvendes de på selve Storage i tilfælde af, at det er en replikeret dato eller shard.

Dette var hovedårsagen. Alligevel er der også praktiske krav til at udvikle en database, hvilket betyder, at det skal være enkelt – lidt kode, så få ødelagte ting som muligt, der skal omskrives og testes. Det faktum, at vores oplogs blev indekseret af hybridure, hjalp meget og gjorde det muligt for os at træffe det rigtige valg. Det gav virkelig pote og virkede på en magisk måde på den allerførste prototype. Det var meget fedt!

Ursynkronisering

Der er flere synkroniseringsmetoder beskrevet i den videnskabelige litteratur. Jeg taler om synkronisering, når vi har to forskellige skår. Hvis der er ét replikasæt, er der ikke behov for nogen synkronisering: dette er en "single master"; vi har en OpLog, som alle ændringer falder ind i - i dette tilfælde er alt allerede sekventielt bestilt i selve "Oplog". Men hvis vi har to forskellige skår, er tidssynkronisering vigtig her. Det var her vektoruret hjalp mere! Men vi har dem ikke.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Den anden er velegnet - dette er "Heartbeats". Det er muligt at udveksle nogle signaler, der opstår hver tidsenhed. Men hjerteslag er for langsomme, vi kan ikke give latens til vores klient.

Sand tid er selvfølgelig en vidunderlig ting. Men igen, dette er sandsynligvis fremtiden... Selvom det allerede kan gøres i Atlas, er der allerede hurtige "Amazon"-tidssynkronisatorer. Men det vil ikke være tilgængeligt for alle.

Sladder er, når alle beskeder inkluderer tid. Det er omtrent det, vi bruger. Hver besked mellem noder, en driver, en datanode-router, absolut alt for MongoDB er en slags element, en databasekomponent, der indeholder et ur, der kører. De har betydningen af ​​hybridtid overalt, det transmitteres. 64 bit? Dette tillader, dette er muligt.

Hvordan hænger det hele sammen?

Her ser jeg på et replikasæt for at gøre det lidt nemmere. Der er primær og sekundær. Secondary replikerer og er ikke altid fuldstændig synkroniseret med Primary.

En indsættelse sker i "Primery" med en bestemt tidsværdi. Denne indsats øger det interne antal med 11, hvis dette er maksimum. Eller det vil tjekke urværdierne og synkronisere med uret, hvis urværdierne er større. Dette giver dig mulighed for at organisere efter tid.

Efter at han har lavet optagelsen, indtræffer et vigtigt øjeblik. Uret er i "MongoDB" og øges kun i tilfælde af skrivning til "Oplog". Dette er den begivenhed, der ændrer systemets tilstand. I absolut alle klassiske artikler anses en hændelse for at være, når en besked rammer en node: beskeden er ankommet, hvilket betyder, at systemet har ændret sin tilstand.

Dette skyldes, at det under forskning ikke er helt klart, hvordan dette budskab vil blive fortolket. Vi ved med sikkerhed, at hvis det ikke afspejles i "Oplog", så vil det ikke blive fortolket på nogen måde, og en ændring i systemets tilstand er kun en indtastning i "Oplog". Dette forenkler alt for os: Modellen forenkler det og giver os mulighed for at organisere det i ét replikasæt og mange andre nyttige ting.

Den værdi, der allerede er skrevet til "Oplog" returneres - vi ved, at "Oplog" allerede indeholder denne værdi, og dens tid er 12. Lad os sige, at læsning begynder fra en anden node (Sekundær), og den transmitterer afterClusterTime i beskeden. Han siger: "Jeg har brug for alt, der skete i det mindste efter 12 eller i løbet af tolv" (se billedet ovenfor).

Dette er det, der kaldes Causal a consistent (CAT). Der er sådan et koncept i teorien, at dette er et stykke tid, hvilket er konsistent i sig selv. I dette tilfælde kan vi sige, at dette er tilstanden af ​​systemet, der blev observeret på tidspunktet 12.

Nu er der intet her endnu, fordi denne slags simulerer situationen, når du har brug for den sekundære til at replikere data fra den primære. Han venter... Og nu er dataene ankommet - han returnerer disse værdier tilbage.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Det er stort set sådan det hele fungerer. Næsten.

Hvad betyder "næsten"? Lad os antage, at der er en person, der har læst og forstået, hvordan det hele fungerer. Jeg indså, at hver gang ClusterTime opstår, opdaterer den det interne logiske ur, og så øges den næste post med én. Denne funktion tager 20 linjer. Lad os sige, at denne person transmitterer det største 64-bit nummer, minus en.

Hvorfor "minus en"? Fordi det interne ur vil blive erstattet med denne værdi (det er naturligvis den størst mulige og større end det aktuelle klokkeslæt), så vil der ske en indtastning i "Oplog", og uret vil blive forøget med en anden enhed - og der vil allerede være en maksimal værdi (der er simpelthen alle enheder, der er ingen andre steder at tage hen), unsaint ints).

Det er klart, at systemet efter dette bliver absolut utilgængeligt for noget som helst. Den kan kun aflæsses og rengøres - meget manuelt arbejde. Fuld tilgængelighed:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Desuden, hvis dette replikeres et andet sted, så falder hele klyngen simpelthen ned. En absolut uacceptabel situation, som alle kan organisere meget hurtigt og nemt! Derfor betragtede vi dette øjeblik som et af de vigtigste. Hvordan forebygger man det?

Vores måde er at underskrive clusterTime

Sådan sendes det i beskeden (før den blå tekst). Men vi begyndte også at generere en signatur (blå tekst):

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Signaturen genereres af en nøgle, der er gemt inde i databasen, inden for en sikker perimeter; selv genereres og opdateres (brugerne kan ikke se noget om det). Der genereres en hash, og hver besked signeres, når den oprettes og valideres, når den modtages.
Spørgsmålet opstår sandsynligvis i folks sind: "Hvor meget bremser dette tingene?" Jeg fortalte dig, at det skulle fungere hurtigt, især i mangel af denne funktion.

Hvad vil det sige at bruge kausal konsistens i dette tilfælde? Dette er for at vise afterClusterTime-parameteren. Uden dette vil det simpelthen passere værdier alligevel. Sladder, fra version 3.6, virker altid.

Hvis vi forlader den konstante generering af signaturer, vil det bremse systemet selv i mangel af en funktion, som ikke opfylder vores tilgange og krav. Så hvad gjorde vi?

Gør det hurtigt!

Det er en ret simpel ting, men tricket er interessant - jeg deler det, måske vil nogen være interesseret.
Vi har en hash, der gemmer de signerede data. Alle data går gennem cachen. Cachen underskriver ikke den specifikke tid, men rækkevidden. Når en værdi ankommer, genererer vi et område, maskerer de sidste 16 bit, og vi signerer denne værdi:

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Ved at modtage en sådan signatur fremskynder vi systemet (relativt) 65 tusinde gange. Det fungerer fantastisk: da vi udførte eksperimenter, faldt tiden faktisk med 10 tusinde gange, når vi havde en sekventiel opdatering. Det er klart, at når de er uenige, så virker det ikke. Men i de fleste praktiske tilfælde virker det. Kombinationen af ​​Range-signaturen sammen med signaturen løste sikkerhedsproblemet.

Hvad har vi lært?

Erfaringer, vi har lært af dette:

  • Vi skal læse materialer, historier, artikler, for vi har mange interessante ting. Når vi arbejder på en eller anden funktion (især nu, hvor vi foretog transaktioner osv.), skal vi læse og forstå. Det tager tid, men det er faktisk meget nyttigt, fordi det gør det klart, hvor vi er. Vi så ikke ud til at finde på noget nyt - vi tog bare ingredienserne.

    Generelt er der en vis forskel på at tænke, når der er en akademisk konference (f.eks. Sigmon) – alle fokuserer på nye ideer. Hvad er nyt ved vores algoritme? Der er ikke noget særligt nyt her. Det nye ligger snarere i den måde, vi blandede eksisterende tilgange sammen. Derfor er den første ting at læse klassikerne, begyndende med Lampart.

  • I produktionen er kravene helt anderledes. Jeg er sikker på, at mange af jer ikke står over for "sfæriske" databaser i et abstrakt vakuum, men med normale, rigtige ting, der har problemer med tilgængelighed, latens og fejltolerance.
  • Den sidste ting er, at vi skulle se på forskellige ideer og kombinere flere helt forskellige artikler i én tilgang, sammen. Ideen om at underskrive, for eksempel, kom generelt fra en artikel, der betragtede Paxos-protokollen, som for ikke-byzantinske fejl er inde i autorisationsprotokollen, for byzantinske - uden for autorisationsprotokollen... Generelt er det præcis, hvad vi endte med at gøre.

    Der er absolut intet nyt her! Men så snart vi blandede det hele sammen... Det er det samme som at sige, at Olivier-salatopskriften er noget pjat, for æg, mayonnaise og agurker er allerede opfundet... Det handler om den samme historie.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Jeg slutter med det her. Tak skal du have!

R'RѕRїSЂRѕSЃS <

Spørgsmål fra salen (i det følgende benævnt B): – Tak, Mikhail, for rapporten! Emnet om tid er interessant. Du bruger Gossiping. De sagde, at alle har deres egen tid, alle kender deres lokale tid. Som jeg forstår det, har vi en driver - der kan være mange klienter med drivere, forespørgselsplanlæggere også, shards også... Og hvad kommer systemet til, hvis vi pludselig har en uoverensstemmelse: nogen beslutter, at det er til en minut foran, nogen et minut bagud? Hvor ender vi?

MT: – Virkelig godt spørgsmål! Jeg ville bare tale om skår. Hvis jeg forstår spørgsmålet rigtigt, har vi følgende situation: der er skår 1 og skår 2, læsning sker fra disse to skår - de har en uoverensstemmelse, de interagerer ikke med hinanden, fordi den tid, de kender, er forskellig, især den tid, de eksisterer i oplogs.
Lad os sige, at shard 1 lavede en million poster, shard 2 gjorde slet ikke noget, og anmodningen kom til to shards. Og den første har en afterClusterTime på over en million. I sådan en situation, som jeg forklarede, vil shard 2 aldrig reagere overhovedet.

I: – Jeg ville gerne vide, hvordan de synkroniserer og vælger et logisk tidspunkt?

MT: - Meget let at synkronisere. Shard, når afterClusterTime kommer til ham, og han ikke finder tid i "Oplog", indleder ingen godkendt. Det vil sige, at han hæver sin tid med hænderne til denne værdi. Det betyder, at den ikke har nogen begivenheder, der matcher denne anmodning. Han skaber denne begivenhed kunstigt og bliver dermed kausalkonsistent.

I: – Hvad hvis der efter dette kommer nogle andre begivenheder til ham, som er gået tabt et sted i netværket?

MT: – Shard er designet sådan, at de ikke kommer igen, da det er en enkelt mester. Hvis han allerede har tilmeldt sig, så kommer de ikke, men kommer senere. Det kan ikke ske, at noget sætter sig fast et sted, så skriver han ikke, og så kommer disse begivenheder - og den kausale konsistens er brudt. Når han ikke skriver, skulle de alle komme næste gang (han vil vente på dem).

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

I: – Jeg har flere spørgsmål angående køerne. Årsagskonsistens forudsætter, at der er en specifik kø af handlinger, der skal udføres. Hvad sker der, hvis en af ​​vores pakker forsvinder? Her kommer den 10., 11.... den 12. er forsvundet, og alle andre venter på, at den bliver til virkelighed. Og pludselig døde vores bil, vi kan ikke gøre noget. Er der en maksimal længde på køen, der akkumuleres, før den udføres? Hvilken fatal fiasko sker, når en tilstand går tabt? Desuden, hvis vi skriver ned, at der er en tidligere tilstand, så skal vi på en eller anden måde tage udgangspunkt i det? Men de skubbede ham ikke væk!

MT: – Også et godt spørgsmål! Hvad laver vi? MongoDB har begrebet kvorum skriver, kvorum læser. I hvilke tilfælde kan en besked gå tabt? Når en skrivning ikke er beslutningsdygtig, eller når en læsning ikke er beslutningsdygtig (en slags affald kan også hænge fast).
Med hensyn til kausal konsistens blev der udført en stor eksperimentel test, hvis resultat var, at i det tilfælde, hvor skrivning og læsning er ikke-quorum, forekommer krænkelser af kausal konsistens. Præcis hvad du siger!

Vores råd: brug mindst kvorumslæsning, når du bruger kausal konsistens. I dette tilfælde vil intet gå tabt, selv hvis kvorumsposten er tabt... Dette er en ortogonal situation: hvis brugeren ikke ønsker, at data skal gå tabt, skal han bruge en kvorumspost. Årsagskonsistens garanterer ikke holdbarhed. Holdbarhed er garanteret af replikering og det maskineri, der er forbundet med replikering.

I: – Når vi opretter en instans, der udfører sharding for os (henholdsvis ikke mester, men slave), er den afhængig af Unix-tiden for sin egen maskine eller på tidspunktet for "mesteren"; Synkroniserer det for første gang eller periodisk?

MT: – Jeg vil afklare nu. Shard (dvs. vandret partition) - der er altid en Primary der. Og et skår kan have en "mester", og der kan være replikaer. Men shard'en understøtter altid optagelse, fordi den skal understøtte et eller andet domæne (shard'en har Primary).

I: – Så alt afhænger udelukkende af "mesteren"? Bruges mestertid altid?

MT: - Ja. Du kan i overført betydning sige: uret tikker, når der sker en adgang til "master", i "Oplog".

I: – Vi har en klient, der forbinder og ikke behøver at vide noget om tiden?

MT: - Du behøver ikke at vide noget som helst! Hvis vi taler om, hvordan det virker på klienten: når klienten vil bruge kausal konsistens, skal han åbne en session. Nu er alt der: transaktioner i sessionen, og hent en rettighed... En session er bestilling af logiske hændelser, der sker med klienten.

Hvis han åbner denne session og siger der, at han ønsker kausal konsistens (hvis sessionen understøtter kausal konsistens som standard), fungerer alt automatisk. Føreren husker denne tid og øger den, når den modtager en ny besked. Den husker, hvilket svar den forrige returnerede fra serveren, der returnerede dataene. Den næste anmodning vil indeholde afterCluster ("tid større end dette").

Kunden behøver ikke at vide noget som helst! Dette er fuldstændig uigennemskueligt for ham. Hvis folk bruger disse funktioner, hvad kan de så gøre? For det første kan du trygt læse sekundærer: du kan skrive til Primary og læse fra geografisk replikerede sekundære og være sikker på, at det virker. Samtidig kan sessioner, der blev optaget på Primary, endda overføres til Secondary, dvs. du kan ikke bruge én session, men flere.

I: – Et nyt lag af computervidenskab – CRDT (Conflict-free Replicated Data Types) datatyper – er stærkt relateret til emnet Eventuel konsistens. Har du overvejet at integrere disse typer data i databasen, og hvad kan du sige om det?

MT: - Godt spørgsmål! CRDT giver mening til skrivekonflikter: i MongoDB, single master.

I: – Jeg har et spørgsmål fra devops. I den virkelige verden er der sådanne jesuitiske situationer, når den byzantinske fiasko opstår, og onde mennesker inden for den beskyttede omkreds begynder at stikke ind i protokollen, sende håndværkspakker på en særlig måde?

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

MT: – Onde mennesker inde i omkredsen er som en trojansk hest! Onde mennesker inden for omkredsen kan gøre mange dårlige ting.

I: – Det er klart, at groft sagt efterlade et hul i serveren, hvorigennem man kan sætte en zoologisk have af elefanter og kollapse hele klyngen for altid... Det vil tage tid at genoprette manuel... Dette mildt sagt er forkert. På den anden side er dette interessant: i det virkelige liv er der i praksis situationer, hvor naturligt lignende interne angreb forekommer?

MT: - Da jeg sjældent støder på sikkerhedsbrud i det virkelige liv, kan jeg ikke sige, om de sker. Men hvis vi taler om udviklingsfilosofien, tænker vi sådan her: Vi har en perimeter, der giver de fyre, der laver sikkerhed - det her er et slot, en mur; og indenfor omkredsen kan du gøre hvad du vil. Det er klart, at der er brugere med mulighed for kun at se, og der er brugere med mulighed for at slette mappen.

Afhængigt af rettighederne kan den skade, som brugerne kan gøre, være en mus, eller det kan være en elefant. Det er klart, at en bruger med fulde rettigheder overhovedet kan gøre hvad som helst. En bruger med begrænsede rettigheder kan forårsage væsentlig mindre skade. Det kan især ikke bryde systemet.

I: – I den beskyttede perimeter forsøgte nogen at skabe uventede protokoller til serveren for fuldstændigt at ødelægge serveren, og hvis du er heldig, hele klyngen... Bliver det nogensinde så "godt"?

MT: "Jeg har aldrig hørt om sådanne ting." At du kan crashe en server på denne måde er ingen hemmelighed. Fail inde, være fra protokollen, være en autoriseret bruger, der kan skrive sådan noget i beskeden... Faktisk er det umuligt, fordi det stadig vil blive verificeret. Det er muligt at deaktivere denne autentificering for brugere, der ikke ønsker det - så er det deres problem; groft sagt ødelagde de selve væggene, og du kan skubbe en elefant derind, som vil trampe... Men generelt kan du klæde dig ud som reparatør, kom og hiv den ud!

I: – Tak for rapporten. Sergey (Yandex). Der er en konstant i Mong, der begrænser antallet af stemmeberettigede medlemmer i replikasættet, og denne konstant er 7 (syv). Hvorfor er dette en konstant? Hvorfor er dette ikke en slags parameter?

MT: – Vi har replikasæt med 40 noder. Der er altid flertal. Jeg ved ikke hvilken version...

I: – I Replica Set kan du køre medlemmer uden stemmeret, men der er maksimalt 7 stemmeberettigede medlemmer Hvordan kan vi overleve nedlukningen i dette tilfælde, hvis vores Replica Set er spredt på 3 datacentre? Et datacenter kan nemt slukke, og en anden maskine kan falde ud.

MT: – Dette er allerede lidt uden for betænkningens rammer. Dette er et generelt spørgsmål. Måske kan jeg fortælle dig om det senere.

HighLoad++, Mikhail Tyulenev (MongoDB): Årsagssammenhæng: fra teori til praksis

Nogle annoncer 🙂

Tak fordi du blev hos os. Kan du lide vores artikler? Vil du se mere interessant indhold? Støt os ved at afgive en ordre eller anbefale til venner, cloud VPS for udviklere fra $4.99, en unik analog af entry-level servere, som blev opfundet af os til dig: Hele sandheden om VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps fra $19 eller hvordan deler man en server? (tilgængelig med RAID1 og RAID10, op til 24 kerner og op til 40 GB DDR4).

Dell R730xd 2 gange billigere i Equinix Tier IV datacenter i Amsterdam? Kun her 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV fra $199 i Holland! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - fra $99! Læse om Hvordan man bygger infrastruktur corp. klasse med brug af Dell R730xd E5-2650 v4-servere til en værdi af 9000 euro for en krone?

Kilde: www.habr.com

Tilføj en kommentar