HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Sljedeća HighLoad++ konferencija održat će se 6. i 7. aprila 2020. godine u Sankt Peterburgu.
Detalji i ulaznice link. HighLoad++ Sibir 2019. Dvorana "Krasnojarsk". 25. jun, 12:00. Teze i prezentacija.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Dešava se da su praktični zahtjevi u sukobu sa teorijom, pri čemu se ne uzimaju u obzir aspekti važni za komercijalni proizvod. Ovaj govor predstavlja proces odabira i kombinovanja različitih pristupa stvaranju komponenti uzročne konzistentnosti zasnovanih na akademskom istraživanju zasnovanom na zahtevima komercijalnog proizvoda. Slušaoci će naučiti o postojećim teorijskim pristupima logičkim satovima, praćenju zavisnosti, sigurnosti sistema, sinhronizaciji sata i zašto se MongoDB odlučio na određena rješenja.

Mikhail Tyulenev (u daljem tekstu MT): – Govoriću o kauzalnoj konzistentnosti – ovo je karakteristika na kojoj smo radili u MongoDB-u. Radim u grupi distribuiranih sistema, radili smo to prije otprilike dvije godine.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

U tom procesu morao sam da se upoznam sa dosta akademskih istraživanja, jer je ova karakteristika prilično dobro proučavana. Pokazalo se da se niti jedan članak ne uklapa u ono što je potrebno u produkcijskoj bazi podataka zbog vrlo specifičnih zahtjeva koji su vjerovatno prisutni u bilo kojoj proizvodnoj aplikaciji.

Govorit ću o tome kako mi, kao potrošači akademskih istraživanja, pripremamo nešto od toga što možemo onda našim korisnicima predstaviti kao gotovo jelo koje je zgodno i sigurno za upotrebu.

Uzročna konzistentnost. Hajde da definišemo pojmove

Za početak, želim općenito reći šta je uzročna konzistentnost. Postoje dva lika - Leonard i Peni (TV serija "Teorija velikog praska"):

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Recimo da je Penny u Evropi i Leonard joj želi prirediti zabavu iznenađenja. I ne može smisliti ništa bolje od toga da je izbaci sa svoje liste prijatelja, a svim svojim prijateljima pošalje ažuriranje na feed: „Učinimo Penny srećnom!“ (ona je u Evropi, dok spava, ona sve ovo ne vidi i ne vidi, jer je nema). Na kraju, ona obriše ovu objavu, briše je iz Feed-a i vraća pristup tako da ništa ne primijeti i da ne bude skandala.
Sve je to dobro, ali pretpostavimo da je sistem distribuiran i da su stvari krenule malo po zlu. Može se, na primjer, dogoditi da je Pennyno ograničenje pristupa došlo nakon što se ovaj post pojavio, ako događaji nisu povezani uzročno-posledično. Zapravo, ovo je primjer kada je uzročna konzistentnost potrebna za obavljanje poslovne funkcije (u ovom slučaju).

Zapravo, ovo su prilično netrivijalna svojstva baze podataka - vrlo ih malo ljudi podržava. Pređimo na modele.

Modeli konzistentnosti

Šta je zapravo model konzistentnosti u bazama podataka? Ovo su neke od garancija koje distribuirani sistem daje o tome koje podatke klijent može primiti i kojim redoslijedom.

U principu, svi modeli konzistentnosti se svode na to koliko je distribuirani sistem sličan sistemu koji radi, na primjer, na jednom čvoru na laptopu. I ovako je sistem koji radi na hiljadama geo-distribuiranih „čvorova“ sličan laptopu, u kojem se sva ova svojstva u principu izvode automatski.

Stoga se modeli konzistentnosti primjenjuju samo na distribuirane sisteme. Svi sistemi koji su ranije postojali i radili na istom vertikalnom skaliranju nisu imali takve probleme. Postojao je jedan Buffer Cache i iz njega se uvijek sve čitalo.

Model Strong

Zapravo, prvi model je Strong (ili linija sposobnosti uspona, kako se često naziva). Ovo je model konzistentnosti koji osigurava da je svaka promjena, nakon što se potvrdi da se dogodila, vidljiva svim korisnicima sistema.

Ovo stvara globalni poredak svih događaja u bazi podataka. Ovo je vrlo jaka svojstva konzistencije i općenito je vrlo skupa. Međutim, veoma je dobro podržan. Samo je vrlo skup i spor - samo se rijetko koristi. To se zove sposobnost uspona.

Postoji još jedno, jače svojstvo koje je podržano u Spanner-u - nazvano Eksterna konzistentnost. Pričaćemo o tome malo kasnije.

Kauzalni

Sljedeća je uzročna, o čemu sam upravo govorio. Postoji još nekoliko podnivoa između Jakog i Uzročnog o kojima neću govoriti, ali svi se svode na Uzročno. Ovo je važan model jer je najjači od svih modela, najjača konzistentnost u prisustvu mreže ili particija.

Uzroci su zapravo situacija u kojoj su događaji povezani uzročno-posljedičnom vezom. Vrlo često se doživljavaju kao Read your on rights sa stanovišta klijenta. Ako je klijent uočio neke vrijednosti, ne može vidjeti vrijednosti koje su bile u prošlosti. Već počinje da vidi očitavanja prefiksa. Sve se svodi na isto.
Uzroci kao model konzistentnosti su djelomični poredak događaja na serveru, u kojem se događaji od svih klijenata promatraju u istom nizu. U ovom slučaju, Leonard i Peni.

Eventualno

Treći model je Eventualna konzistentnost. To je ono što podržavaju apsolutno svi distribuirani sistemi, minimalni model koji uopće ima smisla. To znači sljedeće: kada imamo neke promjene u podacima, one u nekom trenutku postaju konzistentne.

U takvom trenutku ona ništa ne govori, inače bi se pretvorila u vanjsku dosljednost - to bi bila sasvim druga priča. Ipak, ovo je vrlo popularan model, najčešći. Po defaultu, svi korisnici distribuiranih sistema koriste Eventual Consistency.

Želim dati nekoliko komparativnih primjera:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Šta znače ove strelice?

  • Latencija. Kako se snaga konzistentnosti povećava, ona postaje veća iz očiglednih razloga: morate napraviti više zapisa, dobiti potvrdu od svih hostova i čvorova koji učestvuju u klasteru da su podaci već tamo. U skladu s tim, Eventual Consistency ima najbrži odgovor, jer ga tamo, po pravilu, možete čak i zapamtiti i to će u principu biti dovoljno.
  • Dostupnost. Ako ovo shvatimo kao sposobnost sistema da reaguje u prisustvu prekida mreže, particija ili neke vrste kvara, tolerancija grešaka se povećava kako se model konzistentnosti smanjuje, jer nam je dovoljno da jedan host živi i istovremeno vrijeme proizvodi neke podatke. Eventualna konzistentnost uopšte ne garantuje ništa u vezi sa podacima - može biti bilo šta.
  • Anomalije. Istovremeno se, naravno, povećava i broj anomalija. U jakoj konzistentnosti gotovo da uopće ne bi trebali postojati, ali u Eventual Consistentu mogu biti bilo što. Postavlja se pitanje: zašto ljudi biraju Eventual Consistent ako sadrži anomalije? Odgovor je da su modeli Eventualne konzistentnosti primjenjivi i da anomalije postoje, na primjer, u kratkom vremenskom periodu; moguće je koristiti čarobnjak za čitanje i više ili manje čitanje konzistentnih podataka; Često je moguće koristiti modele jake konzistencije. U praksi to funkcionira, a često je broj anomalija vremenski ograničen.

CAP teorema

Kada vidite riječi dosljednost, dostupnost – šta vam pada na pamet? Tako je - CAP teorema! Sada želim da razbijem mit... Nisam ja – to je Martin Kleppmann, koji je napisao divan članak, divnu knjigu.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

CAP teorema je princip formulisan 2000-ih da konzistentnost, dostupnost, particije: uzmite bilo koja dva, a ne možete izabrati tri. To je bio određeni princip. Nekoliko godina kasnije su ga kao teoremu dokazali Gilbert i Lynch. Tada se ovo počelo koristiti kao mantra - sistemi su se počeli dijeliti na CA, CP, AP i tako dalje.

Ova teorema je zapravo dokazana za sljedeće slučajeve... Prvo, dostupnost se ne smatra kontinuiranom vrijednošću od nule do stotine (0 - sistem je "mrtav", 100 - brzo reaguje; navikli smo to tako smatrati) , ali kao svojstvo algoritma , koje garantuje da za sva svoja izvođenja vraća podatke.

O vremenu odgovora uopće nema ni riječi! Postoji algoritam koji vraća podatke nakon 100 godina - apsolutno divan dostupan algoritam, koji je dio CAP teoreme.
Drugo: teorema je dokazana za promjene vrijednosti istog ključa, uprkos činjenici da se ove promjene mogu promijeniti. To znači da se u stvarnosti praktično ne koriste, jer su modeli različiti Eventualna konzistencija, Strong Consistency (možda).

čemu sve ovo? Štaviše, CAP teorema u upravo onom obliku u kojem je dokazana praktično nije primjenjiva i rijetko se koristi. U teorijskoj formi, to nekako sve ograničava. Ispada određeni princip koji je intuitivno ispravan, ali općenito nije dokazan.

Uzročna konzistentnost je najjači model

Ono što se sada dešava je da možete dobiti sve tri stvari: konzistentnost, dostupnost koristeći particije. Konkretno, uzročna konzistentnost je najjači model konzistentnosti, koji i dalje radi u prisustvu particija (prekid u mreži). Zbog toga je to tako veliko interesovanje i zato smo ga i preuzeli.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Prvo, pojednostavljuje rad programera aplikacija. Konkretno, prisustvo velike podrške sa servera: kada svi zapisi koji se javljaju unutar jednog klijenta garantovano stižu u istom redosledu na drugom klijentu. Drugo, podnosi particije.

MongoDB interna kuhinja

Sjetivši se da je ručak, krećemo u kuhinju. Reći ću vam o modelu sistema, odnosno šta je MongoDB za one koji prvi put čuju za takvu bazu podataka.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

MongoDB (u daljem tekstu “MongoDB”) je distribuirani sistem koji podržava horizontalno skaliranje, odnosno dijeljenje; a unutar svakog šarda podržava i redundantnost podataka, odnosno replikaciju.

Sharding u MongoDB-u (a ne relacionoj bazi podataka) vrši automatsko balansiranje, to jest, svaka zbirka dokumenata (ili “tabela” u smislu relacijskih podataka) je podijeljena na dijelove, a server ih automatski premješta između dijelova.

Query Router, koji distribuira zahtjeve, za klijenta je neki klijent preko kojeg radi. On već zna gdje i koji podaci se nalaze i usmjerava sve zahtjeve na ispravan dio.

Još jedna važna stvar: MongoDB je jedan master. Postoji jedan primarni - može uzeti zapise koji podržavaju ključeve koje sadrži. Ne možete raditi Multi-master pisanje.

Napravili smo izdanje 4.2 - tamo su se pojavile nove zanimljive stvari. Konkretno, ubacili su Lucene – pretragu – odnosno izvršnu java direktno u Mongo, i tamo je postalo moguće obavljati pretrage kroz Lucene, isto kao i u Elastici.

I napravili su novi proizvod - Charts, dostupan je i na Atlasu (Mongov vlastiti oblak). Imaju besplatni nivo - možete se igrati s njim. Zaista su mi se svidjeli grafikoni - vizualizacija podataka, vrlo intuitivna.

Sastojci Uzročna konzistencija

Izbrojao sam oko 230 članaka objavljenih na ovu temu - od Leslie Lampert. Sada ću vam po svom sjećanju prenijeti neke dijelove ovih materijala.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Sve je počelo sa člankom Leslie Lampert, koji je napisan 1970-ih. Kao što vidite, neka istraživanja na ovu temu su još uvijek u toku. Sada kauzalna konzistentnost doživljava interesovanje u vezi sa razvojem distribuiranih sistema.

Ograničenja

Koja ograničenja postoje? Ovo je zapravo jedna od glavnih tačaka, jer se ograničenja koja proizvodni sistem nameće veoma razlikuju od ograničenja koja postoje u akademskim člancima. Često su prilično umjetni.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

  • Prvo, “MongoDB” je jedan master, kao što sam već rekao (ovo uvelike pojednostavljuje).
  • Smatramo da bi sistem trebao podržavati oko 10 hiljada šarda. Ne možemo donositi nikakve arhitektonske odluke koje će eksplicitno ograničiti ovu vrijednost.
  • Imamo oblak, ali pretpostavljamo da bi čovjek ipak trebao imati priliku kada preuzme binarni program, pokrene ga na svom laptopu i sve radi odlično.
  • Pretpostavljamo nešto što Research retko pretpostavlja: spoljni klijenti mogu da rade šta god žele. MongoDB je open source. U skladu s tim, klijenti mogu biti toliko pametni i ljuti - mogu htjeti sve razbiti. Nagađamo da bi vizantijski Feilori mogli biti porijeklom.
  • Za eksterne klijente koji su izvan perimetra postoji važno ograničenje: ako je ova funkcija onemogućena, onda ne bi trebalo primijetiti degradaciju performansi.
  • Još jedna stvar je općenito antiakademska: kompatibilnost prethodnih i budućih verzija. Stari upravljački programi moraju podržavati nova ažuriranja, a baza podataka mora podržavati stare upravljačke programe.

Općenito, sve ovo nameće ograničenja.

Komponente uzročne konzistencije

Sada ću govoriti o nekim komponentama. Ako uzmemo u obzir uzročnu konzistentnost općenito, možemo odabrati blokove. Birali smo između radova koji pripadaju određenom bloku: Praćenje zavisnosti, odabir satova, kako se ovi satovi međusobno sinhronizuju i kako obezbeđujemo sigurnost - ovo je grubi prikaz onoga o čemu ću govoriti:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Potpuno praćenje zavisnosti

Zašto je to potrebno? Tako da kada se podaci repliciraju, svaki zapis, svaka promjena podataka sadrži informacije o tome od kojih promjena ovisi. Prva i naivna promjena je kada svaka poruka koja sadrži zapis sadrži informacije o prethodnim porukama:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

U ovom primjeru, broj u vitičastim zagradama je broj zapisa. Ponekad se ti zapisi sa vrijednostima čak prenose u cijelosti, ponekad se prenose neke verzije. Suština je da svaka promjena sadrži informacije o prethodnoj (očigledno nosi sve ovo u sebi).

Zašto smo odlučili da ne koristimo ovaj pristup (potpuno praćenje)? Očigledno, zato što je ovaj pristup nepraktičan: svaka promjena društvene mreže ovisi o svim prethodnim promjenama na toj društvenoj mreži, prenoseći, recimo, Facebook ili VKontakte u svakom ažuriranju. Ipak, postoji mnogo istraživanja o potpunom praćenju zavisnosti – to su preddruštvene mreže; u nekim situacijama to zaista radi.

Eksplicitno praćenje zavisnosti

Sljedeći je ograničeniji. Ovdje se također razmatra prijenos informacija, ali samo one koje su jasno zavisne. Šta zavisi od čega se, po pravilu, utvrđuje Aplikacija. Kada se podaci repliciraju, upit vraća odgovore samo kada su prethodne zavisnosti zadovoljene, odnosno prikazane. Ovo je suština kako uzročna konzistentnost funkcionira.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Ona vidi da zapis 5 zavisi od zapisa 1, 2, 3, 4 - shodno tome, ona čeka pre nego što klijent dobije pristup promenama napravljenim Peninom odlukom o pristupu, kada su sve prethodne promene već prošle kroz bazu podataka.

Ni ovo nam ne odgovara, jer je još uvijek previše informacija i to će usporiti stvari. Postoji još jedan pristup...

Lamport Clock

Oni su veoma stari. Lamportov sat znači da su ove zavisnosti presavijene u skalarnu funkciju, koja se zove Lamportov sat.

Skalarna funkcija je neki apstraktni broj. Često se naziva logičnim vremenom. Sa svakim događajem, ovaj brojač se povećava. Brojač, koji je trenutno poznat procesu, šalje svaku poruku. Jasno je da procesi mogu biti neusklađeni, mogu imati potpuno različita vremena. Ipak, sistem nekako balansira sat sa takvim porukama. Šta se dešava u ovom slučaju?

Podijelio sam tu veliku krhotinu na dva da bi bilo jasno: Prijatelji mogu živjeti u jednom čvoru, koji sadrži dio kolekcije, a Feed može živjeti u drugom čvoru, koji sadrži dio ove kolekcije. Je li jasno kako mogu izaći iz reda? Prvi feed će reći: “Replicirano”, a zatim Prijatelji. Ako sistem ne pruži neku vrstu garancije da feed neće biti prikazan sve dok se ne isporuče i zavisnosti od prijatelja u kolekciji Friends, onda ćemo imati upravo situaciju koju sam spomenuo.

Vidite kako se vrijeme brojača na Feed-u logično povećava:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Dakle, glavno svojstvo ovog Lamportovog sata i uzročne konzistentnosti (objašnjeno kroz Lamportov sat) je ovo: ako imamo događaje A i B, a događaj B zavisi od događaja A*, onda slijedi da je logičko vrijeme događaja A manje od Logično vrijeme od događaja B.

* Ponekad se kaže i da se A dogodilo prije B, odnosno da se A dogodilo prije B - to je određena relacija koja djelimično naređuje čitav niz događaja koji su se uopšte desili.

Suprotno je netačno. Ovo je zapravo jedan od glavnih nedostataka Lamportovog sata - djelomični red. Postoji koncept o simultanim događajima, odnosno događajima u kojima se ni (A se dogodilo prije B) ni (A se dogodilo prije B) nije. Primjer bi bio Leonardovo paralelno dodavanje nekog drugog kao prijatelja (čak ne Leonarda, već Sheldona, na primjer).
Ovo je svojstvo koje se često koristi kada se radi sa Lamport satovima: oni posebno gledaju na funkciju i iz toga zaključuju da su ti događaji možda ovisni. Jer jedan način je tačan: ako je logičko vrijeme A manje od logičkog vremena B, onda se B ne može dogoditi prije A; a ako više, onda možda.

Vector Clock

Logičan razvoj Lamportovog sata je vektorski sat. Razlikuju se po tome što svaki čvor koji se nalazi ovdje sadrži svoj zasebni sat, a prenose se kao vektor.
U ovom slučaju, vidite da je nulti indeks vektora odgovoran za feed, a prvi indeks vektora je za prijatelje (svaki od ovih čvorova). A sada će se povećati: nulti indeks "Feed" se povećava prilikom pisanja - 1, 2, 3:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Zašto je Vector Clock bolji? Zato što vam omogućavaju da shvatite koji su događaji simultani i kada se dešavaju na različitim čvorovima. Ovo je veoma važno za sistem za šardiranje kao što je MongoDB. Međutim, mi nismo izabrali ovo, iako je to divna stvar, i odlično radi, i vjerovatno bi nam odgovaralo...

Ako imamo 10 hiljada fragmenata, ne možemo prenijeti 10 hiljada komponenti, čak i ako ih komprimujemo ili smislimo nešto drugo - nosivost će i dalje biti nekoliko puta manja od volumena cijelog ovog vektora. Stoga smo, stisnuvši srce i zube, napustili ovaj pristup i prešli na drugi.

Spanner TrueTime. Atomski sat

Rekao sam da će biti priča o Spanneru. Ovo je super stvar, pravo iz XNUMX. veka: atomski satovi, GPS sinhronizacija.

Koja je ideja? “Spanner” je Google sistem koji je nedavno čak postao dostupan ljudima (dodali su mu SQL). Svaka transakcija ima neku vremensku oznaku. Pošto je vrijeme sinhronizovano*, svakom događaju se može dodijeliti određeno vrijeme - atomski satovi imaju vrijeme čekanja, nakon čega se garantuje da će se „dogoditi“ drugo vrijeme.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Dakle, jednostavnim pisanjem u bazu podataka i čekanjem određenog vremenskog perioda, serijalizacija događaja je automatski zagarantovana. Oni imaju najjači model konzistentnosti koji se u principu može zamisliti – to je eksterna konzistentnost.

* Ovo je glavni problem sa Lampart satovima - oni nikada nisu sinhroni na distribuiranim sistemima. Mogu se razlikovati; čak i sa NTP-om, oni i dalje ne rade dobro. "Spanner" ima atomski sat i sinhronizacija je, čini se, mikrosekunde.

Zašto nismo izabrali? Ne pretpostavljamo da naši korisnici imaju ugrađen atomski sat. Kada se pojave, ugrađeni u svaki laptop, postojaće neka super cool GPS sinhronizacija - onda da... Ali za sada najbolje što je moguće je Amazon, bazne stanice - za fanatike... Tako da smo koristili druge satove .

Hibridni sat

To je zapravo ono što kuca u MongoDB-u kada se osigurava kauzalna konzistentnost. Kako su hibridni? Hibrid je skalarna vrijednost, ali ima dvije komponente:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

  • Prva je Unix epoha (koliko je sekundi prošlo od „početka kompjuterskog svijeta“).
  • Drugi je neki inkrement, također 32-bitni neoznačeni int.

To je sve, zapravo. Postoji ovakav pristup: dio koji je odgovoran za vrijeme je cijelo vrijeme sinhronizovan sa satom; svaki put kada dođe do ažuriranja, ovaj dio se sinkronizira sa satom i ispostavi se da je vrijeme uvijek manje-više tačno, a inkrement vam omogućava da razlikujete događaje koji su se dogodili u istom trenutku.

Zašto je ovo važno za MongoDB? Zato što vam omogućava da napravite neku vrstu rezervnih restorana u određenom trenutku, odnosno događaj se indeksira po vremenu. Ovo je važno kada su potrebni određeni događaji; Za bazu podataka, događaji su promjene u bazi podataka koje su se dogodile u određenim vremenskim intervalima.

Najvažniji razlog ću vam reći samo vama (molim vas, nemojte nikome reći)! Ovo smo uradili jer ovako izgledaju organizovani, indeksirani podaci u MongoDB OpLog-u. OpLog je struktura podataka koja sadrži apsolutno sve promjene u bazi podataka: one prvo idu u OpLog, a zatim se primjenjuju na sam Storage u slučaju kada se radi o repliciranom datumu ili šardu.

To je bio glavni razlog. Ipak, postoje i praktični zahtjevi za razvoj baze podataka, što znači da ona treba da bude jednostavna - malo koda, što manje pokvarenih stvari koje treba prepisati i testirati. Činjenica da su naši oplogovi bili indeksirani hibridnim satovima je mnogo pomogla i omogućila nam da napravimo pravi izbor. Zaista se isplatilo i nekako magično funkcioniralo na prvom prototipu. Bilo je super!

Sinhronizacija sata

U naučnoj literaturi je opisano nekoliko metoda sinhronizacije. Govorim o sinhronizaciji kada imamo dva različita dijela. Ako postoji jedan skup replika, nema potrebe za bilo kakvom sinhronizacijom: ovo je “single master”; imamo OpLog, u koji padaju sve promjene - u ovom slučaju, sve je već sekvencijalno poredano u samom "Oplogu". Ali ako imamo dva različita dijela, ovdje je važna vremenska sinhronizacija. Tu je vektorski sat više pomogao! Ali mi ih nemamo.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Drugi je prikladan - ovo je "Otkucaji srca". Moguća je razmjena nekih signala koji se javljaju u svakoj jedinici vremena. Ali otkucaji srca su presporo, ne možemo osigurati kašnjenje našem klijentu.

Istinsko vrijeme je, naravno, divna stvar. Ali, opet, ovo je vjerovatno budućnost... Iako se to već može uraditi u Atlasu, već postoje brzi „amazonski“ sinhronizatori vremena. Ali neće biti dostupan svima.

Ogovaranje je kada sve poruke uključuju vrijeme. To je otprilike ono što koristimo. Svaka poruka između čvorova, drajver, ruter čvora podataka, apsolutno sve za MongoDB je neka vrsta elementa, komponente baze podataka koja sadrži sat koji radi. Oni svuda imaju značenje hibridnog vremena, ono se prenosi. 64 bita? Ovo dozvoljava, to je moguće.

Kako sve to funkcionira zajedno?

Ovdje gledam jednu repliku da bi bilo malo lakše. Postoje primarni i sekundarni. Sekundarni vrši replikaciju i nije uvijek potpuno sinkroniziran s primarnim.

Dolazi do umetanja u "Primery" sa određenom vremenskom vrijednošću. Ovaj umetak povećava interni broj za 11, ako je to maksimum. Ili će provjeriti vrijednosti sata i sinhronizirati se sa satom ako su vrijednosti sata veće. Ovo vam omogućava da se organizujete po vremenu.

Nakon što on napravi snimak, dešava se važan trenutak. Sat je u "MongoDB" i povećava se samo u slučaju pisanja u "Oplog". Ovo je događaj koji mijenja stanje sistema. U apsolutno svim klasičnim člancima, događajem se smatra kada poruka udari u čvor: poruka je stigla, što znači da je sistem promijenio svoje stanje.

To je zbog činjenice da tokom istraživanja nije sasvim jasno kako će se ova poruka tumačiti. Pouzdano znamo da ako se to ne odrazi u “Oplog”, onda to neće biti interpretirano ni na koji način, a promjena stanja sistema je samo unos u “Oplog”. Ovo nam sve pojednostavljuje: model ga pojednostavljuje i omogućava nam da ga organiziramo unutar jednog skupa replika i mnoge druge korisne stvari.

Vraća se vrijednost koja je već zapisana u “Oplog” - znamo da “Oplog” već sadrži ovu vrijednost, a njeno vrijeme je 12. Sada, recimo, čitanje počinje od drugog čvora (Secondary), a prenosi afterClusterTime u poruka. Kaže: „Treba mi sve što se desilo najmanje posle 12 ili tokom dvanaest“ (vidi sliku iznad).

To je ono što se naziva Uzročno dosljedno (CAT). U teoriji postoji takav koncept da je to neki odsječak vremena, koji je sam po sebi dosljedan. U ovom slučaju možemo reći da je ovo stanje sistema koje je uočeno u trenutku 12.

Sada ovdje još nema ničega, jer ova vrsta simulira situaciju kada vam je potrebno da sekundar replicira podatke iz primarnog. Čeka... I sada su stigli podaci - vraća ove vrijednosti nazad.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Tako otprilike sve funkcionira. Skoro.

Šta znači "skoro"? Pretpostavimo da postoji neka osoba koja je pročitala i razumjela kako sve ovo funkcionira. Shvatio sam da svaki put kada se ClusterTime pojavi, ažurira interni logički sat, a zatim se sljedeći unos povećava za jedan. Ova funkcija zauzima 20 redova. Recimo da ova osoba prenosi najveći 64-bitni broj, minus jedan.

Zašto "minus jedan"? Budući da će interni sat biti zamijenjen ovom vrijednošću (očigledno, ovo je najveća moguća i veća od trenutnog vremena), tada će se pojaviti unos u "Oplog", a sat će se povećati za drugu jedinicu - i već će biti maksimalna vrijednost (jednostavno postoje sve jedinice, nema gdje drugdje) , nesvete ints).

Jasno je da nakon toga sistem postaje apsolutno nedostupan za bilo šta. Može se samo istovariti i očistiti - puno ručnog rada. Potpuna dostupnost:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Štaviše, ako se ovo ponovi negdje drugdje, onda cijeli klaster jednostavno pada. Apsolutno neprihvatljiva situacija koju svako može vrlo brzo i jednostavno organizirati! Stoga smo ovaj trenutak smatrali jednim od najvažnijih. Kako to spriječiti?

Naš način je da potpišemo clusterTime

Ovako se prenosi u poruci (ispred plavog teksta). Ali smo također počeli generirati potpis (plavi tekst):

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Potpis se generiše pomoću ključa koji je pohranjen unutar baze podataka, unutar sigurnog perimetra; sama se generira i ažurira (korisnici ne vide ništa o tome). Generiše se hash, a svaka poruka se potpisuje kada se kreira i potvrđuje kada je primljena.
Vjerovatno se u glavama ljudi postavlja pitanje: „Koliko ovo usporava stvari?“ Rekao sam vam da bi trebalo da radi brzo, posebno u nedostatku ove funkcije.

Šta znači koristiti uzročnu konzistentnost u ovom slučaju? Ovo je za prikaz parametra afterClusterTime. Bez toga će ionako jednostavno proslijediti vrijednosti. Ogovaranje, počevši od verzije 3.6, uvijek radi.

Ako ostavimo konstantno generisanje potpisa, to će usporiti sistem čak i u nedostatku neke funkcije, koja ne zadovoljava naše pristupe i zahtjeve. Pa šta smo uradili?

Učini to brzo!

To je prilično jednostavna stvar, ali trik je zanimljiv - podijeliću ga, možda će nekoga zanimati.
Imamo hash koji pohranjuje potpisane podatke. Svi podaci prolaze kroz keš memoriju. Keš memorija ne potpisuje određeno vrijeme, već opseg. Kada neka vrijednost stigne, generiramo raspon, maskiramo posljednjih 16 bitova i potpisujemo ovu vrijednost:

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Primanjem takvog potpisa ubrzavamo sistem (relativno) 65 hiljada puta. Radi odlično: kada smo izvodili eksperimente, vrijeme se zapravo smanjilo za 10 hiljada puta kada smo imali sekvencijalno ažuriranje. Jasno je da kada su u sukobu, to ne funkcionira. Ali u većini praktičnih slučajeva funkcionira. Kombinacija potpisa Range zajedno sa potpisom rešila je bezbednosni problem.

Šta smo naučili?

Lekcije koje smo naučili iz ovoga:

  • Moramo čitati materijale, priče, članke, jer imamo puno zanimljivih stvari. Kada radimo na nekoj funkciji (naročito sada, kada smo radili transakcije, itd.), moramo čitati i razumjeti. Za to je potrebno vrijeme, ali je zapravo vrlo korisno jer nam jasno pokazuje gdje smo. Činilo se da nismo smislili ništa novo – samo smo uzeli sastojke.

    Općenito, postoji određena razlika u razmišljanju kada je akademska konferencija (Sigmon, na primjer) - svi se fokusiraju na nove ideje. Šta je novo u našem algoritmu? Nema tu ništa posebno novo. Novost prije leži u načinu na koji smo spojili postojeće pristupe. Stoga je prva stvar pročitati klasike, počevši od Lamparta.

  • U proizvodnji su zahtjevi potpuno drugačiji. Siguran sam da se mnogi od vas ne suočavaju sa „sferičnim“ bazama podataka u apstraktnom vakuumu, već sa normalnim, stvarnim stvarima koje imaju problema sa dostupnošću, kašnjenjem i tolerancijom grešaka.
  • Posljednja stvar je da smo morali razmotriti različite ideje i spojiti nekoliko potpuno različitih članaka u jedan pristup, zajedno. Ideja o potpisivanju, na primjer, generalno je proizašla iz članka koji je razmatrao Paxos protokol, koji je za nevizantijske promašaje unutar autorizacionog protokola, za vizantijske - izvan autorizacionog protokola... Generalno, to je upravo ono što mi na kraju uradio.

    Ovdje nema apsolutno ništa novo! Ali čim smo sve pomešali... To je isto kao da kažete da je recept za salatu Olivier glupost, jer su jaja, majonez i krastavci već izmišljeni... O istoj priči.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Završiću sa ovim. Hvala ti!

Vaša pitanja

Pitanje iz publike (u daljem tekstu B): – Hvala, Mihaile, na izveštaju! Zanimljiva je tema o vremenu. Koristite Gossiping. Rekli su da svako ima svoje vrijeme, svako zna svoje lokalno vrijeme. Koliko sam ja shvatio, imamo drajver - može biti mnogo klijenata sa drajverima, planerima upita, takođe i šardovima... I na šta se sistem svodi ako odjednom imamo neslaganje: neko odluči da je za minut ispred, neko minut iza? Gdje ćemo završiti?

MT: – Zaista odlično pitanje! Hteo sam samo da pričamo o krhotinama. Ako sam dobro razumio pitanje, imamo sljedeću situaciju: postoji dio 1 i dio 2, očitavanje se dešava iz ova dva dijela - oni imaju neslaganje, ne komuniciraju jedno s drugim, jer je vrijeme koje znaju je različito, posebno vrijeme kada postoje u oplogovima.
Recimo da je dio 1 napravio milion zapisa, dio 2 nije uradio baš ništa, a zahtjev je došao do dva dijela. A prvi ima afterClusterTime od preko milion. U takvoj situaciji, kao što sam objasnio, krhotina 2 uopće neće reagirati.

AT: – Želeo sam da znam kako se sinhronizuju i biraju jedno logično vreme?

MT: - Vrlo lako se sinhronizuje. Shard, kada afterClusterTime dođe do njega i on ne nađe vremena u “Oplogu”, inicira no odobreno. Odnosno, on svojim rukama podiže svoje vrijeme na ovu vrijednost. To znači da nema događaja koji odgovaraju ovom zahtjevu. On stvara ovaj događaj umjetno i tako postaje kauzalno dosljedan.

AT: – Šta ako mu nakon ovoga dođu neki drugi događaji koji su izgubljeni negdje u mreži?

MT: – Shard je dizajniran tako da više neće doći, jer se radi o jednom majstoru. Ako se već prijavio, onda neće doći, već će doći kasnije. Ne može se desiti da se nešto negdje zaglavi, onda on ne piše, a onda stignu ovi događaji - i naruši se uzročna konzistentnost. Kad on ne piše, svi bi trebali doći sljedeći (on će ih čekati).

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

AT: – Imam nekoliko pitanja u vezi sa redovima. Uzročna konzistentnost pretpostavlja da postoji određeni red radnji koje treba izvršiti. Šta se dešava ako jedan od naših paketa nestane? Evo dolazi 10., 11.... 12. je nestao, a svi ostali čekaju da se ostvari. I odjednom nam je auto umro, ne možemo ništa. Postoji li maksimalna dužina reda koji se akumulira prije nego što se izvrši? Koji fatalni neuspjeh nastaje kada se izgubi bilo koje stanje? Štaviše, ako zapišemo da postoji neko prethodno stanje, onda bi nekako trebalo krenuti od njega? Ali ga nisu odgurnuli!

MT: – Takođe odlično pitanje! Šta mi radimo? MongoDB ima koncept kvoruma piše, kvoruma čita. U kojim slučajevima poruka može biti izgubljena? Kada pisanje nije kvorum ili kada čitanje nije kvorum (neka vrsta smeća također može ostati).
Što se tiče uzročne konzistentnosti, sproveden je veliki eksperimentalni test čiji je rezultat bio da u slučaju kada upisivanje i čitanje nije kvorum, dolazi do kršenja kauzalne konzistentnosti. Tačno ono što kažete!

Naš savjet: koristite barem čitanje kvoruma kada koristite uzročnu konzistentnost. U ovom slučaju ništa neće biti izgubljeno, čak i ako se izgubi kvorum zapis... Ovo je ortogonalna situacija: ako korisnik ne želi da se podaci izgube, treba koristiti zapis kvoruma. Uzročna konzistentnost ne garantuje trajnost. Trajnost je zagarantovana replikacijom i mašinama koje su povezane s replikacijom.

AT: – Kada kreiramo instancu koja za nas vrši sharding (ne master, već slave, respektivno), ona se oslanja na Unix vrijeme svoje vlastite mašine ili na vrijeme „mastera“; Da li se sinhronizuje prvi put ili periodično?

MT: – Sad ću pojasniti. Shard (tj. horizontalna particija) – tu uvijek postoji Primary. A krhotina može imati "majstora" i mogu postojati replike. Ali dio uvijek podržava snimanje, jer mora podržavati neku domenu (sard ima Primary).

AT: – Dakle, sve zavisi isključivo od „majstora“? Da li se uvijek koristi glavno vrijeme?

MT: - Da. Možete figurativno reći: sat otkucava kada dođe do ulaska u "master", u "Oplog".

AT: – Imamo klijenta koji se povezuje i ne treba da zna ništa o vremenu?

MT: – Ne morate ništa da znate! Ako govorimo o tome kako to funkcionira na klijenta: kada klijent želi koristiti uzročnu konzistentnost, mora otvoriti sesiju. Sada je sve tu: transakcije u sesiji i preuzimanje prava... Sesija je redosled logičkih događaja koji se dešavaju kod klijenta.

Ako otvori ovu sesiju i tamo kaže da želi uzročnu konzistentnost (ako sesija podrazumevano podržava uzročnu konzistentnost), sve radi automatski. Vozač pamti ovo vrijeme i povećava ga kada primi novu poruku. Pamti koji je odgovor prethodni vratio sa servera koji je vratio podatke. Sljedeći zahtjev će sadržavati afterCluster("vrijeme veće od ovog").

Klijent ne mora znati apsolutno ništa! Ovo je za njega potpuno neprozirno. Ako ljudi koriste ove funkcije, šta mogu učiniti? Prvo, možete bezbedno čitati sekundarne sadržaje: možete pisati u Primary i čitati iz geografski repliciranih sekundarnih sadržaja i biti sigurni da radi. U isto vrijeme, sesije koje su snimljene na Primary mogu se čak prenijeti na Sekundarni, odnosno možete koristiti ne jednu sesiju, već nekoliko.

AT: – Novi sloj računarstva – CRDT (Conflict-free Replicated Data Types) tipovi podataka – usko je povezan sa temom Eventualne konzistentnosti. Da li ste razmišljali o integraciji ovih vrsta podataka u bazu podataka i šta možete reći o tome?

MT: - Dobro pitanje! CRDT ima smisla za sukobe pisanja: u MongoDB, jedan master.

AT: – Imam pitanje od devopsa. U stvarnom svijetu postoje takve jezuitske situacije kada se dogodi vizantijski neuspjeh, a zli ljudi unutar zaštićenog perimetra počnu da guraju u protokol, šalju zanatske pakete na poseban način?

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

MT: – Zli ljudi unutar perimetra su kao trojanski konj! Zli ljudi unutar perimetra mogu učiniti mnogo loših stvari.

AT: – Jasno je da ostavite, grubo rečeno, rupu na serveru kroz koju možete ubaciti zoološki vrt slonova i zauvek srušiti ceo klaster... Trebaće vremena za ručni oporavak... Ovo je, najblaže rečeno, pogrešno. S druge strane, ovo je zanimljivo: u stvarnom životu, u praksi, postoje situacije kada se dešavaju prirodno slični unutrašnji napadi?

MT: – Pošto se u stvarnom životu retko susrećem sa kršenjem bezbednosti, ne mogu da kažem da li se dešavaju. Ali ako govorimo o filozofiji razvoja, mislimo ovako: imamo perimetar koji obezbjeđuje momke koji obezbjeđuju – ovo je zamak, zid; a unutar perimetra možete raditi šta god želite. Jasno je da postoje korisnici koji imaju mogućnost samo pregleda, a postoje korisnici koji imaju mogućnost brisanja direktorija.

Ovisno o pravima, šteta koju korisnici mogu napraviti može biti miš, a može biti i slon. Jasno je da korisnik sa punim pravima može sve. Korisnik s ograničenim pravima može uzrokovati znatno manje štete. Konkretno, ne može razbiti sistem.

AT: – U zaštićenom perimetru neko je pokušao da napravi neočekivane protokole za server kako bi u potpunosti uništio server, a ako imate sreće i ceo klaster... Da li ikada bude toliko „dobro“?

MT: “Nikad nisam čuo za takve stvari.” Činjenica da možete srušiti server na ovaj način nije nikakva tajna. Fail unutra, biti iz protokola, biti ovlašteni korisnik koji može ovako nešto napisati u poruci... Zapravo, nemoguće je, jer će ipak biti provjereno. Moguće je onemogućiti ovu autentifikaciju za korisnike koji to ne žele - onda je to njihov problem; oni su, grubo receno, sami razorili zidove i tu mozes ugurati slona koji ce gaziti... Ali generalno mozes da se obuces kao majstor, dodji i izvuci ga!

AT: – Hvala na izveštaju. Sergej (Yandex). Postoji konstanta u Mongu koja ograničava broj članova sa pravom glasa u skupu replika, a ova konstanta je 7 (sedam). Zašto je to konstanta? Zašto ovo nije neka vrsta parametra?

MT: – Imamo skupove replika sa 40 čvorova. Uvek postoji većina. Ne znam koja verzija...

AT: – U skupu replika možete pokrenuti članove koji nemaju pravo glasa, ali ima najviše 7 članova s ​​pravom glasa Kako možemo preživjeti gašenje u ovom slučaju ako je naš skup replika raspoređen u 3 data centra? Jedan data centar se lako može isključiti, a druga mašina može ispasti.

MT: – Ovo je već malo van okvira izvještaja. Ovo je opšte pitanje. Možda ti mogu reći o tome kasnije.

HighLoad++, Mikhail Tyulenev (MongoDB): Uzročna konzistentnost: od teorije do prakse

Neke reklame 🙂

Hvala vam što ste ostali s nama. Da li vam se sviđaju naši članci? Želite li vidjeti još zanimljivih sadržaja? Podržite nas naručivanjem ili preporukom prijateljima, cloud VPS za programere od 4.99 USD, jedinstveni analog servera početnog nivoa, koji smo mi izmislili za vas: Cijela istina o VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps od 19$ ili kako dijeliti server? (dostupno sa RAID1 i RAID10, do 24 jezgra i do 40GB DDR4).

Dell R730xd 2 puta jeftiniji u Equinix Tier IV data centru u Amsterdamu? Samo ovdje 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV od 199 USD u Holandiji! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - od 99 USD! Pročitajte o Kako izgraditi infrastrukturnu kompaniju. klase uz korišćenje Dell R730xd E5-2650 v4 servera u vrednosti od 9000 evra za peni?

izvor: www.habr.com

Dodajte komentar