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

Sljedeća HighLoad++ konferencija održat će se 6. i 7. travnja 2020. u St.
Detalji i ulaznice по ссылке. HighLoad++ Siberia 2019. Dvorana "Krasnojarsk". 25. lipnja, 12:00. Teze i prezentacija.

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

Događa se da su praktični zahtjevi u sukobu s teorijom, pri čemu se ne uzimaju u obzir aspekti važni za komercijalni proizvod. Ovaj govor predstavlja proces odabira i kombiniranja različitih pristupa stvaranju komponenti uzročne dosljednosti na temelju akademskog istraživanja temeljenog na zahtjevima komercijalnog proizvoda. Slušatelji će naučiti o postojećim teorijskim pristupima logičkim satovima, praćenju ovisnosti, sigurnosti sustava, sinkronizaciji sata i zašto se MongoDB odlučio za određena rješenja.

Mikhail Tyulenev (u daljnjem tekstu MT): – Govorit ću o uzročnoj dosljednosti – to je značajka na kojoj smo radili u MongoDB-u. Radim u grupi distribuiranih sustava, napravili smo to prije otprilike dvije godine.

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

U procesu sam se morao upoznati s brojnim akademskim istraživanjima, jer je ova značajka prilično dobro proučena. Pokazalo se da niti jedan članak ne odgovara onome što je potrebno u produkcijskoj bazi podataka zbog vrlo specifičnih zahtjeva koji su vjerojatno prisutni u svakoj produkcijskoj aplikaciji.

Govorit ću o tome kako mi, kao konzumenti akademskog istraživanja, od toga pripremimo nešto što potom možemo prezentirati našim korisnicima kao gotovo jelo koje je praktično i sigurno za upotrebu.

Uzročna dosljednost. Definirajmo pojmove

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

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

Recimo da je Penny u Europi i Leonard joj želi prirediti zabavu iznenađenja. I ne može smisliti ništa bolje nego izbaciti je sa svoje liste prijatelja, poslati svim svojim prijateljima ažuriranje na feedu: "Učinimo Penny sretnom!" (ona je u Europi, dok spava, sve to ne vidi i ne može vidjeti, jer je nema). Na kraju, ona briše ovu objavu, briše je iz Feeda i vraća pristup tako da ništa ne primijeti i da ne bude skandala.
Sve je to lijepo i dobro, ali pretpostavimo da je sustav distribuiran i da su stvari krenule malo krivo. Može se, primjerice, dogoditi da je do Pennyne restrikcije pristupa došlo nakon što se ova objava pojavila, ako događaji nisu uzročno-posljedično povezani. Zapravo, ovo je primjer kada je uzročna dosljednost potrebna za obavljanje poslovne funkcije (u ovom slučaju).

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

Modeli dosljednosti

Što je točno model dosljednosti u bazama podataka? Ovo su neka od jamstava koja distribuirani sustav daje o tome koje podatke klijent može primiti i kojim redoslijedom.

U principu, svi modeli konzistentnosti svode se na to koliko je distribuirani sustav sličan sustavu koji radi, na primjer, na jednom čvoru na prijenosnom računalu. I to je koliko je sustav koji radi na tisućama geo-distribuiranih "čvorova" sličan laptopu, u kojem se sva ova svojstva u principu izvršavaju automatski.

Stoga se modeli dosljednosti primjenjuju samo na distribuirane sustave. Svi sustavi koji su prethodno postojali i radili na istom vertikalnom skaliranju nisu imali takvih problema. Postojao je jedan međuspremnik i sve se uvijek čitalo iz njega.

Model Strong

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

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

Postoji još jedno, jače svojstvo koje je podržano u Spanneru - zove se vanjska dosljednost. O tome ćemo malo kasnije.

kauzalni

Sljedeći je Causal, upravo ono o čemu sam govorio. Postoji još nekoliko podrazina između Strong i Causal o kojima neću govoriti, ali sve se svode na Causal. Ovo je važan model jer je najjači od svih modela, najjača postojanost u prisutnosti mreže ili particija.

Kauzale su zapravo situacije u kojima su događaji povezani uzročno-posljedičnom vezom. Vrlo često ih se s klijentove točke gledišta doživljava kao Pročitajte svoja prava. Ako je klijent promatrao neke vrijednosti, ne može vidjeti vrijednosti koje su bile u prošlosti. Već počinje vidjeti očitavanje prefiksa. Sve se svodi na isto.
Kauzali kao model konzistentnosti djelomično su sređivanje događaja na poslužitelju, u kojem se događaji od svih klijenata promatraju u istom nizu. U ovom slučaju, Leonard i Penny.

konačan

Treći model je Eventualna dosljednost. To je ono što podržavaju apsolutno svi distribuirani sustavi, minimalni model koji uopće ima smisla. To znači sljedeće: kada imamo neke promjene u podacima, u jednom trenutku oni postaju konzistentni.

U tom trenutku ona ne govori ništa, inače bi se pretvorila u Vanjsku Dosljednost – bila bi to sasvim druga priča. Ipak, ovo je vrlo popularan model, najčešći. Prema zadanim postavkama, svi korisnici distribuiranih sustava koriste Eventual Consistency.

Želim dati neke usporedne primjere:

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

Što znače ove strelice?

  • Latencija. Kako se snaga dosljednosti povećava, ona postaje veća iz očitih razloga: trebate napraviti više zapisa, dobiti potvrdu od svih hostova i čvorova koji sudjeluju u klasteru da su podaci već tamo. Sukladno tome, Eventualna dosljednost ima najbrži odgovor, jer ga tamo u pravilu možete čak i memorirati i to će u principu biti dovoljno.
  • Raspoloživost. Ako ovo shvatimo kao sposobnost sustava da odgovori u slučaju prekida mreže, particija ili neke vrste kvara, tolerancija na pogreške raste kako se smanjuje model konzistentnosti, jer nam je dovoljno da živi jedan host, a istovremeno vrijeme proizvodi neke podatke. Eventualna dosljednost uopće ne jamči ništa o podacima - može biti bilo što.
  • Anomalije. Istovremeno se, naravno, povećava broj anomalija. U Strong Consistency oni gotovo uopće ne bi trebali postojati, ali u Eventual Consistency mogu biti bilo što. Postavlja se pitanje: zašto ljudi odabiru Eventual Consistency ako sadrži anomalije? Odgovor je da su modeli eventualne dosljednosti primjenjivi i da anomalije postoje, na primjer, u kratkom vremenskom razdoblju; moguće je koristiti čarobnjaka 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 teorem

Kada vidite riječi dosljednost, dostupnost – što vam pada na pamet? Tako je - CAP teorem! Sada želim raspršiti mit... To nisam ja - to je Martin Kleppmann, koji je napisao prekrasan članak, prekrasnu knjigu.

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

CAP teorem je princip formuliran 2000-ih da dosljednost, dostupnost, particije: uzmite bilo koja dva, a ne možete odabrati tri. Bio je to određeni princip. Gilbert i Lynch su to nekoliko godina kasnije dokazali kao teorem. Onda se to počelo koristiti kao mantra - sustavi su se počeli dijeliti na CA, CP, AP i tako dalje.

Ovaj je teorem zapravo dokazan za sljedeće slučajeve... Prvo, Dostupnost se nije smatrala kontinuiranom vrijednošću od nula do stotina (0 - sustav je "mrtav", 100 - brzo reagira; navikli smo to tako smatrati) , ali kao svojstvo algoritma, koje jamči da za sva njegova izvršenja vraća podatke.

O vremenu odziva uopće nema riječi! Postoji algoritam koji vraća podatke nakon 100 godina - apsolutno prekrasan dostupni algoritam, koji je dio CAP teorema.
Drugo: teorem je dokazan za promjene u vrijednostima istog ključa, unatoč činjenici da se te promjene mogu promijeniti. To znači da se u stvarnosti praktički ne koriste, jer su modeli različiti Eventualna dosljednost, Jaka dosljednost (možda).

Čemu sve ovo? Štoviše, CAP teorem upravo u onom obliku u kojem je dokazan praktički nije primjenjiv i rijetko se koristi. U teoretskom obliku sve nekako ograničava. Ispada određeno načelo koje je intuitivno točno, ali općenito nije dokazano.

Uzročna dosljednost je najjači model

Ono što se sada događa je da možete dobiti sve tri stvari: dosljednost, dostupnost korištenjem particija. Konkretno, uzročna dosljednost je najjači model dosljednosti, koji još uvijek funkcionira u prisutnosti particija (prekida u mreži). Zato je toliki interes i zato smo se toga uhvatili.

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

Prvo, pojednostavljuje rad programera aplikacija. Konkretno, prisutnost velike podrške od strane poslužitelja: kada svi zapisi koji se pojavljuju unutar jednog klijenta zajamčeno stižu u istom nizu na drugom klijentu. Drugo, podnosi pregrade.

MongoDB interna kuhinja

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

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

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

MongoDB (u daljnjem tekstu "MongoDB") je distribuirani sustav koji podržava horizontalno skaliranje, odnosno dijeljenje; a unutar svakog sharda podržava i redundantnost podataka, odnosno replikaciju.

Sharding u MongoDB-u (nije relacijska baza podataka) izvodi automatsko balansiranje, odnosno svaka kolekcija dokumenata (ili “tablica” u smislu relacijskih podataka) podijeljena je na dijelove, a poslužitelj ih automatski premješta između shardova.

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

Još jedna važna točka: 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 - search - odnosno izvršnu java izravno u Mongo, i tamo je postalo moguće vršiti pretraživanja kroz Lucene, isto kao u Elastici.

I napravili su novi proizvod - Charts, dostupan je i na Atlasu (Mongov vlastiti Cloud). Imaju besplatnu razinu - možete se igrati s njom. Jako mi se svidio Charts - vizualizacija podataka, vrlo intuitivna.

Sastojci Uzročna dosljednost

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

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

Sve je počelo s člankom Leslie Lampert, koji je napisan 1970-ih. Kao što vidite, neka istraživanja na ovu temu još su u tijeku. Sada Kauzalna dosljednost doživljava interes u vezi s razvojem distribuiranih sustava.

Ograničenja

Koja ograničenja postoje? Ovo je zapravo jedna od glavnih točaka, jer su ograničenja koja proizvodni sustav nameće vrlo različita od ograničenja koja postoje u akademskim člancima. Često su prilično umjetni.

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

  • Prvo, "MongoDB" je jedan master, kao što sam već rekao (ovo uvelike pojednostavljuje).
  • Vjerujemo da bi sustav trebao podržavati oko 10 tisuća shardova. Ne možemo donositi nikakve arhitektonske odluke koje bi eksplicitno ograničile ovu vrijednost.
  • Imamo cloud, ali pretpostavljamo da bi čovjek ipak trebao imati priliku kada skine binarni, pusti ga na laptopu i sve radi super.
  • Pretpostavljamo nešto što istraživanje rijetko pretpostavlja: vanjski klijenti mogu raditi što god žele. MongoDB je open source. Sukladno tome, klijenti mogu biti tako pametni i ljuti - mogu poželjeti sve polomiti. Nagađamo da bizantski feilori mogu potjecati.
  • Za vanjske klijente koji su izvan perimetra, postoji važno ograničenje: ako je ova značajka onemogućena, tada se ne bi trebalo primijetiti smanjenje performansi.
  • Još jedna točka općenito je antiakademska: kompatibilnost prethodnih verzija i budućih. Stari upravljački programi moraju podržavati nova ažuriranja, a baza podataka mora podržavati stare upravljačke programe.

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

Komponente uzročne konzistencije

Sada ću govoriti o nekim komponentama. Ako razmatramo uzročnu dosljednost općenito, možemo odabrati blokove. Odabrali smo radove koji pripadaju određenom bloku: Praćenje ovisnosti, odabir satova, kako se ti satovi mogu međusobno sinkronizirati i kako osiguravamo sigurnost - ovo je okvirni pregled onoga o čemu ću govoriti:

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

Potpuno praćenje ovisnosti

Zašto je to potrebno? Tako da kada se podaci repliciraju, svaki zapis, svaka promjena podataka sadrži informacije o tome o kojim promjenama 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 dosljednost: od teorije do prakse

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

Zašto smo odlučili ne koristiti ovaj pristup (potpuno praćenje)? Očito, jer je ovaj pristup nepraktičan: svaka promjena na društvenoj mreži ovisi o svim prethodnim promjenama na toj društvenoj mreži, prijenosu, recimo, Facebooka ili VKontaktea pri svakom ažuriranju. Unatoč tome, postoji mnogo istraživanja o praćenju pune ovisnosti – to su prije društvenih mreža; u nekim situacijama to stvarno funkcionira.

Eksplicitno praćenje ovisnosti

Sljedeći je ograničeniji. Ovdje se također razmatra prijenos informacija, ali samo onaj koji je jasno ovisan. Što ovisi o čemu, u pravilu se utvrđuje Prijavom. Kada se podaci repliciraju, upit vraća odgovore samo kada su prethodne ovisnosti zadovoljene, odnosno prikazane. Ovo je bit načina na koji funkcionira uzročna dosljednost.

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

Ona vidi da zapis 5 ovisi o zapisima 1, 2, 3, 4 - prema tome, čeka prije nego što klijent dobije pristup promjenama napravljenim Pennynom odlukom o pristupu, kada su sve prethodne promjene već prošle kroz bazu podataka.

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

Lamport sat

Jako su stari. Lamportov sat znači da su ove ovisnosti složene 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 drugačija vremena. Ipak, sustav takvim porukama nekako uravnotežuje sat. Što se događa u ovom slučaju?

Podijelio sam tu veliku krhotinu na dva dijela da bude jasno: Prijatelji mogu živjeti u jednom čvoru, koji sadrži dio zbirke, a Feed može živjeti u drugom čvoru, koji sadrži dio ove zbirke. Je li jasno kako mogu izaći iz reda? Prvi Feed će reći: "Replicirano", a zatim Prijatelji. Ako sustav ne pruži neku vrstu jamstva da Feed neće biti prikazan dok se ne isporuče i zavisnosti Prijatelja u zbirci Prijatelja, tada ćemo imati upravo situaciju koju sam spomenuo.

Vidite kako se vrijeme brojača na Feedu logično povećava:

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

Dakle, glavno svojstvo ovog Lamportovog sata i uzročne dosljednosti (objašnjeno kroz Lamportov sat) je sljedeće: ako imamo događaje A i B, a događaj B ovisi o događaju A*, onda slijedi da je logičko vrijeme događaja A manje od Logičko vrijeme od događaja B.

* Ponekad se također kaže da se A dogodilo prije B, odnosno da se A dogodilo prije B - to je određena relacija koja djelomično uređuje cijeli skup događaja koji su se dogodili općenito.

Suprotno je netočno. To je zapravo jedan od glavnih nedostataka Lamportovog sata - djelomični red. Postoji koncept simultanih događaja, odnosno događaja u kojima se niti (A dogodilo prije B) niti (A se dogodilo prije B). Primjer bi bio Leonardovo istovremeno dodavanje nekog drugog kao prijatelja (čak ni Leonarda, već Sheldona, na primjer).
Ovo je svojstvo koje se često koristi pri radu s Lamportovim satovima: oni posebno promatraju funkciju i iz toga zaključuju da su ti događaji možda ovisni. Jer jedan je način istinit: ako je LogicalTime A manje od LogicalTime B, tada se B ne može dogoditi prije A; a ako više, onda možda.

Vektorski sat

Logičan razvoj Lamport sata je Vector Clock. 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" povećava se prilikom pisanja - 1, 2, 3:

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

Zašto je Vector Clock bolji? Zato što vam omogućuju da shvatite koji su događaji istodobni i kada se događaju na različitim čvorovima. Ovo je vrlo važno za sustav dijeljenja kao što je MongoDB. No, ovo nismo mi odabrali, iako je divna stvar, i super radi, a vjerojatno bi nam i odgovarala...

Ako imamo 10 tisuća fragmenata, ne možemo prenijeti 10 tisuća komponenti, čak i ako to komprimiramo 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, odustali od ovog pristupa i prešli na drugi.

Spanner TrueTime. Atomski sat

Rekao sam da će biti priča o Spanneru. Ovo je super stvar, ravno iz XNUMX. stoljeća: atomski satovi, GPS sinkronizacija.

Koja je ideja? “Spanner” je Googleov sustav koji je nedavno postao čak i ljudima dostupan (dodali su mu SQL). Svaka transakcija tamo ima neku vremensku oznaku. Budući da je vrijeme sinkronizirano*, svakom događaju može se dodijeliti određeno vrijeme - atomski satovi imaju vrijeme čekanja, nakon kojeg se jamči da će se "dogoditi" drugo vrijeme.

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

Dakle, jednostavnim pisanjem u bazu podataka i čekanjem određenog vremenskog perioda, Serializabilnost događaja je automatski zajamčena. Oni imaju najjači model dosljednosti koji se u principu može zamisliti – to je vanjska dosljednost.

* Ovo je glavni problem s Lampart satovima - oni nikada nisu sinkroni na distribuiranim sustavima. Mogu se razlikovati; čak i s NTP-om, još uvijek ne rade dobro. "Spanner" ima atomski sat i sinkronizacija je, čini se, mikrosekundna.

Zašto nismo birali? Ne pretpostavljamo da naši korisnici imaju ugrađeni atomski sat. Kad se pojave, ugrađeni su u svaki laptop, bit će neka super cool GPS sinkronizacija - onda da... Ali za sada najbolje što je moguće je Amazon, Base Stations - za fanatike... Pa smo koristili druge satove .

Hibridni sat

To je zapravo ono što je važno u MongoDB-u kada se osigurava uzročna dosljednost. Kako su hibridni? Hibrid je skalarna vrijednost, ali ima dvije komponente:

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

  • Prva je Unix epoha (koliko je sekundi prošlo od “početka svijeta računala”).
  • Drugi je neki inkrement, također 32-bitni unsigned int.

To je zapravo sve. Postoji ovaj pristup: dio koji je odgovoran za vrijeme je cijelo vrijeme sinkroniziran sa satom; svaki put kada dođe do ažuriranja, ovaj dio se sinkronizira sa satom i ispada da je vrijeme uvijek manje-više točno, a inkrement vam omogućuje razlikovanje događaja koji su se dogodili u istom trenutku.

Zašto je ovo važno za MongoDB? Zato što vam omogućuje da napravite neku vrstu rezervnih restorana u određenom trenutku u vremenu, odnosno događaj je vremenski indeksiran. 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 ti reći samo tebi (molim te, nemoj nikome reći)! To smo učinili jer ovako izgledaju organizirani, indeksirani podaci u MongoDB OpLog-u. OpLog je podatkovna struktura koja sadrži apsolutno sve promjene u bazi: prvo idu u OpLog, a zatim se primjenjuju na sam Storage u slučaju kada se radi o repliciranom datumu ili shardu.

To je bio glavni razlog. Ipak, postoje i praktični zahtjevi za razvoj baze podataka, što znači da ona treba biti jednostavna - malo koda, što manje pokvarenih stvari koje treba prepisivati ​​i testirati. Činjenica da su naši oplozi bili indeksirani hibridnim satovima puno je pomogla i omogućila nam da napravimo pravi izbor. Stvarno se isplatilo i nekako je magično djelovalo na prvom prototipu. Bilo je jako cool!

Sinkronizacija sata

U znanstvenoj literaturi opisano je nekoliko metoda sinkronizacije. Govorim o sinkronizaciji kada imamo dva različita sharda. Ako postoji jedan skup replika, nema potrebe za nikakvom sinkronizacijom: ovo je "jedan 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 sharda, vremenska sinkronizacija je ovdje važna. Ovdje je vektorski sat više pomogao! Ali mi ih nemamo.

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

Drugi je prikladan - ovo je "Otkucaji srca". Moguće je razmjenjivati ​​neke signale koji se javljaju svake jedinice vremena. Ali otkucaji srca su prespori, ne možemo pružiti latenciju našem klijentu.

Istinsko vrijeme je, naravno, divna stvar. Ali, opet, to je vjerojatno budućnost... Iako se već može u Atlasu, već postoje brzi “Amazonovi” sinkronizatori vremena. Ali neće biti dostupan svima.

Ogovaranje je kada sve poruke uključuju vrijeme. To je otprilike ono što mi koristimo. Svaka poruka između čvorova, upravljački program, usmjerivač podatkovnog čvora, apsolutno sve za MongoDB je neka vrsta elementa, komponente baze podataka koja sadrži sat koji radi. Svugdje imaju značenje hibridnog vremena, ono se prenosi. 64 bita? Ovo dopušta, ovo je moguće.

Kako to sve skupa funkcionira?

Evo gledam jedan set replika da malo olakšam. Postoje primarni i sekundarni. Sekundarni obavlja replikaciju i nije uvijek potpuno sinkroniziran s primarnim.

Događa se umetanje u "Primery" s određenom vremenskom vrijednošću. Ovaj umetak povećava interni broj za 11, ako je to maksimum. Ili će provjeriti vrijednosti sata i sinkronizirati se sa satom ako su vrijednosti sata veće. To vam omogućuje organizaciju prema vremenu.

Nakon što napravi snimku, događa se važan trenutak. Sat je u "MongoDB" i povećava se samo u slučaju pisanja u "Oplog". To je događaj koji mijenja stanje sustava. U apsolutno svim klasičnim člancima događajem se smatra kada poruka pogodi čvor: poruka je stigla, što znači da je sustav promijenio stanje.

To je zbog činjenice da tijekom istraživanja nije sasvim jasno kako će se ova poruka protumačiti. Znamo sigurno da ako se to ne odražava u „Oplogu“, onda se neće tumačiti ni na koji način, a promjena stanja sustava samo je unos u „Oplog“. To nam sve pojednostavljuje: model ga pojednostavljuje i omogućuje 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 tu vrijednost, a njegovo vrijeme je 12. Sada, recimo, čitanje počinje s drugog čvora (Sekundarni), i prenosi afterClusterTime u poruka. Kaže: “Trebam sve što se dogodilo barem nakon 12 ili tijekom dvanaest” (vidi sliku gore).

To je ono što se naziva uzročno dosljedno (CAT). Postoji takav koncept u teoriji da je to neki isječak vremena, koji je konzistentan sam po sebi. U ovom slučaju možemo reći da je to stanje sustava koje je promatrano u trenutku 12.

Sada ovdje još nema ničega jer se na ovaj način simulira situacija kada trebate sekundarnu da replicira podatke iz primarne. On čeka... I sada su stigli podaci - vraća te vrijednosti natrag.

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

Otprilike tako sve funkcionira. Skoro.

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

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

Jasno je da nakon ovoga sustav postaje apsolutno nedostupan za bilo što. Može se samo istovariti i očistiti – puno ručnog rada. Puna dostupnost:

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

Štoviše, ako se to replicira negdje drugdje, tada cijeli klaster jednostavno padne. Apsolutno nedopustiva situacija koju svatko može vrlo brzo i lako 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 također smo počeli generirati potpis (plavi tekst):

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

Potpis se generira pomoću ključa koji je pohranjen unutar baze podataka, unutar sigurnog perimetra; sam se generira i ažurira (korisnici ne vide ništa o tome). Generira se hash, a svaka poruka se potpisuje kada se kreira i provjerava valjanost kada se primi.
Vjerojatno se u glavama ljudi postavlja pitanje: "Koliko ovo usporava stvari?" Rekao sam vam da bi trebao raditi brzo, pogotovo u nedostatku ove značajke.

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

Ako napustimo stalno generiranje potpisa, to će usporiti sustav čak i u nedostatku značajke, koja ne zadovoljava naše pristupe i zahtjeve. Pa što smo učinili?

Učini to brzo!

To je prilično jednostavna stvar, ali trik je zanimljiv - podijelit ću ga, možda će nekoga zanimati.
Imamo hash koji pohranjuje potpisane podatke. Svi podaci prolaze kroz predmemoriju. Predmemorija ne označava određeno vrijeme, već raspon. Kada stigne neka vrijednost, generiramo raspon, maskiramo zadnjih 16 bitova i potpisujemo ovu vrijednost:

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

Dobivanjem takvog potpisa sustav ubrzavamo (relativno) 65 tisuća puta. Radi odlično: kada smo provodili eksperimente, vrijeme se zapravo smanjilo za 10 tisuća puta kada smo imali sekvencijalno ažuriranje. Jasno je da kad su posvađani, to ne ide. Ali u većini praktičnih slučajeva radi. Kombinacija Range potpisa i potpisa riješila je sigurnosni problem.

Što 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 značajci (posebno sada, kada smo radili transakcije itd.), moramo čitati i razumjeti. Potrebno je vrijeme, ali je zapravo vrlo korisno jer jasno pokazuje gdje smo. Čini 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. Što je novo u našem algoritmu? Nema tu neke posebne novosti. Novost prije leži u načinu na koji smo spojili postojeće pristupe. Stoga je prva stvar č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ć s normalnim, stvarnim stvarima koje imaju problema s dostupnošću, latencijom i tolerancijom na greške.
  • Posljednja stvar je da smo morali sagledati različite ideje i kombinirati nekoliko potpuno različitih članaka u jedan pristup, zajedno. Ideja o potpisivanju, na primjer, općenito je došla iz članka koji je razmatrao Paxos protokol, koji je za ne-Byzantine Failors unutar autorizacijskog protokola, za Byzantine - izvan autorizacijskog protokola... Općenito, to je upravo ono što mi završio radeći.

    Ovdje nema apsolutno ništa novo! Ali čim smo sve to pomiješali... To je isto kao da je recept za salatu Olivier glupost, jer su jaja, majoneza i krastavci već izmišljeni... Ista je priča.

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

Završit ću s ovim. Hvala vam!

pitanja

Pitanje iz publike (u daljnjem tekstu B): – Hvala, Mikhail, na izvješću! Zanimljiva je tema o vremenu. Vi koristite Ogovaranje. Rekli su da svatko ima svoje vrijeme, svatko zna svoje lokalno vrijeme. Koliko sam shvatio, imamo vozača - može biti mnogo klijenata s pokretačima, planeri upita također, shardovi također... A na što se sustav svodi ako iznenada imamo nedosljednost: netko odluči da je to za minutu ispred, netko minutu iza? Gdje ćemo završiti?

MT: – Zaista odlično pitanje! Samo sam htio razgovarati o krhotinama. Ako sam dobro shvatio pitanje, imamo sljedeću situaciju: postoji shard 1 i shard 2, očitavanje se događa iz ta dva sharda - oni imaju nepodudarnost, nemaju međusobnu interakciju, jer je vrijeme koje oni znaju različito, osobito vrijeme koje postoje u oplozima.
Recimo da je shard 1 napravio milijun zapisa, shard 2 nije napravio ništa, a zahtjev je stigao na dva sharda. A prvi ima afterClusterTime od preko milijun. U takvoj situaciji, kao što sam objasnio, shard 2 uopće neće odgovoriti.

NA: – Htio sam znati kako se sinkroniziraju i biraju jedno logično vrijeme?

MT: - Vrlo jednostavno za sinkronizaciju. Shard, kada afterClusterTime dođe do njega, a on ne nađe vremena u “Oplog”, pokreće ne odobreno. To jest, on svojim rukama podiže svoje vrijeme na ovu vrijednost. To znači da nema događaja koji odgovaraju ovom zahtjevu. On umjetno stvara ovaj događaj i tako postaje Kauzalno dosljedan.

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

MT: – Shard je zamišljen tako da više neće dolaziti, jer je to jedan majstor. Ako se već prijavio, onda neće doći, nego će doći kasnije. Ne može se dogoditi da negdje nešto zapne, pa ne piše, a onda stignu ti događaji - i uzročna konzistentnost se pokvari. Kad ne piše, neka svi dođu na red (on će ih čekati).

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

NA: – Imam nekoliko pitanja u vezi s redovima. Uzročna dosljednost pretpostavlja da postoji određeni red radnji koje je potrebno izvršiti. Što se događa ako jedan od naših paketa nestane? Dolazi 10., 11.... 12. je nestao, a svi ostali čekaju da se ostvari. I odjednom nam je crkao auto, ne možemo ništa. Postoji li najveća duljina reda čekanja koja se nakuplja prije izvršenja? Koji se fatalni kvar događa kada se bilo koje stanje izgubi? Štoviše, ako zapišemo da postoji neko prethodno stanje, onda od njega nekako treba krenuti? Ali nisu ga odgurnuli!

MT: – Također odlično pitanje! Što radimo? MongoDB ima koncept kvoruma piše, kvorum čita. U kojim slučajevima se poruka može izgubiti? Kad pisanje nije kvorum ili kad čitanje nije kvorum (može se zalijepiti i nekakvo smeće).
Što se tiče Kauzalne konzistentnosti, proveden je veliki eksperimentalni test, čiji je rezultat bio da u slučaju kada su pisanja i čitanja nekvorumski, dolazi do kršenja Kauzalne konzistentnosti. Točno ono što kažete!

Naš savjet: upotrijebite barem čitanje kvoruma kada koristite uzročnu dosljednost. U ovom slučaju ništa se neće izgubiti, čak i ako se izgubi zapis o kvorumu... Ovo je ortogonalna situacija: ako korisnik ne želi gubitak podataka, mora koristiti zapis o kvorumu. Uzročna dosljednost ne jamči trajnost. Trajnost je zajamčena replikacijom i strojevima povezanim s replikacijom.

NA: – Kada kreiramo instancu koja umjesto nas izvodi sharding (ne master, već slave), ona se oslanja na Unix vrijeme vlastitog stroja ili na vrijeme "mastera"; Sinkronizira li se prvi put ili povremeno?

MT: — Sad ću razjasniti. Krhotina (tj. vodoravna particija) – tu uvijek postoji primarni. I shard može imati "mastera" i mogu postojati replike. Ali shard uvijek podržava snimanje, jer mora podržavati neku domenu (shard ima Primary).

NA: – Znači sve ovisi isključivo o “majstoru”? Koristi li se uvijek glavno vrijeme?

MT: - da Možete slikovito reći: sat otkucava kada se dogodi ulazak u “master”, u “Oplog”.

NA: – Imamo klijenta koji se povezuje i ne mora znati ništa o vremenu?

MT: – Ne morate uopće ništa znati! Ako govorimo o tome kako to funkcionira na klijentu: kada klijent želi koristiti Kauzalnu dosljednost, treba otvoriti sesiju. Sada je sve tu: transakcije u sesiji i preuzimanje prava... Sesija je redoslijed logičkih događaja koji se događaju s klijentom.

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

Klijent ne mora znati apsolutno ništa! Ovo mu je potpuno neprozirno. Ako ljudi koriste ove značajke, što mogu učiniti? Prvo, možete sigurno čitati sekundare: možete pisati u primarni i čitati iz geografski repliciranih sekundara i biti sigurni da radi. U isto vrijeme, sesije koje su snimljene na Primarnoj mogu se čak prenijeti na Sekundarnu, tj. možete koristiti ne jednu sesiju, već nekoliko.

NA: – Novi sloj računalne znanosti – tipovi podataka CRDT (Replicirani tipovi podataka bez sukoba) – snažno je povezan s temom Eventualne dosljednosti. Jeste li razmišljali o integraciji ove vrste podataka u bazu podataka i što o tome možete reći?

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

NA: – Imam pitanje od devopsa. U stvarnom svijetu postoje takve jezuitske situacije kada se dogodi Bizantski neuspjeh, a zli ljudi unutar zaštićenog perimetra počnu zabadati u protokol, slati craft pakete na poseban način?

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

MT: – Zli ljudi unutar perimetra su poput trojanskog konja! Zli ljudi unutar perimetra mogu učiniti puno loših stvari.

NA: – Jasno je da ostaviti, grubo rečeno, rupu u serveru kroz koju možete progurati zoološki vrt slonova i zauvijek urušiti cijeli klaster... Trebat će vremena za ručni oporavak... Ovo je, blago rečeno, pogrešno. S druge strane, ovo je zanimljivo: u stvarnom životu, u praksi, postoje situacije kada se prirodno događaju slični unutarnji napadi?

MT: – Budući da se u stvarnom životu rijetko susrećem s upadima sigurnosti, ne mogu reći hoće li se dogoditi. Ali ako govorimo o filozofiji razvoja, razmišljamo ovako: imamo perimetar koji osigurava momke koji rade sigurnost - ovo je dvorac, zid; a unutar perimetra možete raditi što god želite. Jasno je da postoje korisnici s mogućnošću samo pregledavanja, a postoje i korisnici s mogućnošću brisanja imenika.

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

NA: – U zaštićenom perimetru netko je pokušao kreirati neočekivane protokole za poslužitelj kako bi u potpunosti uništio poslužitelj, a ako imate sreće i cijeli klaster... Postane li ikada tako “dobro”?

MT: “Nikad nisam čuo za takve stvari.” Činjenica da na ovaj način možete srušiti poslužitelj nije tajna. Zatajiti unutra, biti iz protokola, biti ovlašteni korisnik koji može ovako nešto napisati u poruci... Zapravo, to je nemoguće, jer će se još provjeriti. Moguće je onemogućiti ovu autentifikaciju korisnicima koji je ne žele - to je onda njihov problem; oni su, grubo govoreći, sami uništili zidove i tamo možete ugurati slona koji će gaziti... Ali općenito, možete se maskirati u majstora, dođite i izvucite ga!

NA: – Hvala na izvješću. Sergej (Yandex). U Mongu postoji konstanta koja ograničava broj članova s ​​pravom glasa u skupu replika, a ta je konstanta 7 (sedam). Zašto je to konstanta? Zašto ovo nije nekakav parametar?

MT: – Imamo setove replika s 40 čvorova. Uvijek postoji većina. Ne znam koja verzija...

NA: – U Replica Setu možete pokrenuti članove bez prava glasa, ali postoji najviše 7 članova s ​​pravom glasa. Kako možemo preživjeti gašenje u ovom slučaju ako je naš Replica Set raspoređen u 3 podatkovna centra? Jedan podatkovni centar može se lako isključiti, a drugi stroj može ispasti.

MT: – Ovo već malo izlazi iz okvira izvješća. Ovo je općenito pitanje. Možda ti o tome mogu pričati kasnije.

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

Neki oglasi 🙂

Hvala što ste ostali s nama. Sviđaju li vam se naši članci? Želite li vidjeti više zanimljivog sadržaja? Podržite nas narudžbom ili preporukom prijateljima, cloud VPS za programere od 4.99 USD, jedinstveni analog poslužitelja početne razine, koji smo izmislili za vas: Cijela istina o VPS (KVM) E5-2697 v3 (6 jezgri) 10GB DDR4 480GB SSD 1Gbps od 19 USD ili kako podijeliti poslužitelj? (dostupno s RAID1 i RAID10, do 24 jezgre i do 40 GB DDR4).

Dell R730xd 2 puta jeftiniji u Equinix Tier IV podatkovnom 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 Nizozemskoj! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128 GB DDR3 2x960 GB SSD 1 Gbps 100 TB - od 99 USD! Pročitaj o Kako izgraditi infrastrukturu corp. klase uz korištenje Dell R730xd E5-2650 v4 servera vrijednih 9000 eura za lipu?

Izvor: www.habr.com

Dodajte komentar