Konferenca e ardhshme HighLoad++ do të mbahet më 6 dhe 7 prill 2020 në Shën Petersburg.
Të dhënat dhe biletat . HighLoad++ Siberia 2019. Salla "Krasnojarsk". 25 qershor, 12:00. Tëzat dhe .

Ndonjëherë kërkesat praktike përplasen me teorinë, ku aspekte të rëndësishme për produktin komercial nuk merren parasysh. Në këtë prezantim paraqitet procesi i zgjedhjes dhe kombinimit të qasjeve të ndryshme për krijimin e komponentëve të Causal consistency, bazuar në studime akademike, duke u bazuar në kërkesat e produkteve komerciale. Dëgjuesit do të mësojnë për qasjet teorike ekzistuese ndaj logical clocks, tracking të varësive, sigurinë e sistemeve, sinkronizimin e orëve, dhe pse MongoDB zgjodhi disa nga këto zgjidhje.
Mikhail Tyulenyev (më pas – MT): – Do të flas për Causal consistency – kjo është një veçori mbi të cilën kemi punuar në MongoDB. Punoj në grupin e sistemeve të shpërndara, ne e zhvilluam atë rreth dy vjet më parë.

Në proces, duhej të familiarizohem me një numër të madh kërkimesh akademike, pasi kjo veçori është studiuar mjaft mirë. Doli që asnjë artikull nuk përputhet me atë që kërkohet në prodhim, duke pasur parasysh kërkesa shumë specifike që ka çdo aplikacion prodhimi.
Do të flas për atë se si ne, si konsumatorë të kërkimeve akademike, përgatisim diçka që më pas mund t'ia paraqesim përdoruesve tanë si një pjatë të gatshme, të lehtë dhe të sigurt për t'u përdorur.
Causal consistency. Le të sqarojmë disa koncepte
Për fillim, dua të them në terma të përgjithshëm se çfarë është Causal consistency. Janë dy personazhe – Leonard dhe Penny (seriali "Teoria e Big Bangut"):

Supozoni se Penny është në Evropë, dhe Leonard dëshiron t'i bëjë një surprizë, një festë. Dhe ai nuk di çfarë tjetër të bëjë, sesa ta heqë atë nga lista e miqve, dhe të dërgojë një azhurnim në feed-in e të gjithëve: "Le të gëzojmë Penny-n!" (ajo është në Evropë, për momentin fle, nuk e sheh këtë dhe nuk mund ta shohë, sepse nuk është aty). Në fund, ai e fshin këtë postim, e fshin nga "Feed-i" dhe rivendos aksesin, që ajo të mos e kuptojë dhe të mos ketë zënkë.
Kjo është e shkëlqyer, por le të supozojmë se sistemi është shpërndarë, dhe ngjarjet ndodhën ndryshe. Mund të ndodhë, për shembull, që kufizimi i aksesit për Penny ndodhi pasi ky postim u shfaq, nëse ngjarjet nuk janë të lidhura me njëra-tjetrën me lidhje përkatësie. Në thelb, kjo është një shembull se si nevojitet Causal consistency për të realizuar një funksion biznesi (në këtë rast).
Në të vërtetë, këto janë cilësi mjaft jo triviale të bazave të dhënash – shumë pak i mbështesin ato. Le të kalojmë në modelet.
Modelet e konsistencës
Çfarë është model konsistence në bazat e dhënash? Këto janë disa garantime që një sistem i shpërndarë jep lidhur me atë se cilat të dhëna dhe në cilën rend mundet klienti të marrë.
Në thelb, të gjitha modelet e konsistencës reduktohen në atë se sa i ngjan një sistem i shpërndarë një sistemi që punon, për shembull, në një nod të vetëm në një laptop. Dhe sa i ngjan një sistem që punon në mijëra nodë të shpërndara, laptopit, ku të gjitha këto veçori plotësohen automatikisht.
Prandaj, modelet e konsistencës aplikohen vetëm në sistemet e shpërndara. Të gjitha sistemet që më parë ekzistonin dhe punonin në një shkallë vertikale, nuk kishin këto probleme. Atje kishte një Buffer Cache, dhe gjithçka e lexonte nga ai gjithmonë.
Modeli Strong
Saktësisht, modeli i parë është Strong (ose linearity, siç quhet shpesh). Ky është një model konsistence që garanton që çdo ndryshim, sapo marrim konfirmimin që ka ndodhur, bëhet i dukshëm për të gjithë përdoruesit e sistemit.
Kjo krijon një rend global të ngjarjeve në Baze të Dhënash. Kjo është një cilësi shumë e fortë e konsistencës dhe është mjaft e kushtueshme. Megjithatë, ajo mbështetet shumë mirë. Thjesht është shumë e shtrenjtë dhe e ngadalshme – prandaj përdoret rrallë. Kjo quhet linearitet.
Ka një veçori tjetër, madje më të fortë, e cila mbahet në "Spanner" – e quajtur Konsistenca Eksterne. Do ta diskutojmë këtë më vonë.
Causal
Një tjetër është Causal, që është ajo për të cilën kam folur. Ndërmjet Strong dhe Causal ekzistojnë disa nivele të tjerë që nuk do të flas për to, por të gjitha ato reduktohen në Causal. Ky është një model i rëndësishëm, sepse është konsistenca më e fortë e të gjitha modele, konsistenca më e fortë në praninë e rrjeteve ose ndarjeve.
Causals – është situata ku ngjarjet janë të lidhura me njëra-tjetrën me një lidhje shkakësore. Shpesh herë, ato kuptohen si Read your on rights nga perspektiva e klientit. Nëse klienti ka vëzhguar disa vlera, ai nuk mund të shikojë vlerat që ishin në të kaluarën. Ai fillon të shohë leximet me prefiks. E gjitha kjo reduktohet në të njëjtën gjë.
Causals si model konsistence – një renditje e pjesshme e ngjarjeve në server, ku ngjarjet nga të gjithë klientët vëzhgohen në të njëjtën renditje. Në këtë rast – Leonard dhe Penny.
Eventual
Modeli i tretë – është Eventual Consistency. Ky është një model që mbështetet nga të gjitha sistemet e shpërndara, një model minimal që ka ndonjë kuptim. Ai do të thotë se: kur ndodhin disa ndryshime në të dhëna, ato në një moment bëhen konsistente.
Në atë moment, ai nuk thotë asgjë, përndryshe do të kthehej në External Consistency – do të ishte një histori krejt tjetër. Megjithatë, ky është një model shumë i popullarizuar, më i përhapuri. Si parazgjedhje, të gjithë përdoruesit e sistemeve të shpërndara përdorin saktësisht Eventual Consistency.
Dua të jap disa shembuj krahasues:

Çfarë do të thonë këto shigjeta?
- Latency. Me rritjen e forcës së konsistencës, ajo bëhet më e madhe për arsye të qarta: duhen bërë më shumë regjistrime, të merret një konfirmim nga të gjitha host-të dhe nodet që janë pjesë e klasterit, se të dhënat janë aty. Përkatësisht, në Eventual Consistency, përgjigjja më e shpejtë është, sepse aty, zakonisht, mund të angazhoheni madje edhe në memory dhe kjo do të ishte mjaft e mjaftueshme.
- Availability. Nëse e kuptojmë si mundësi të sistemit për të përgjigjur në prani të çarjeve të rrjetit, partitions, ose ndonjë dështimi – qëndrueshmëria rritet me uljen e modelit të konsistencës, sepse mjafton që një host të jetë në funksion dhe të ofrojë disa të dhëna. Eventual Consistency nuk garanton asgjë për të dhënat – ato mund të jenë çfarëdo.
- Anomalies. Megjithatë, natyrisht, rritet numri i anomali-ve. Në Strong Consistency, ato pothuajse nuk duhet të ekzistojnë, ndërsa në Eventual Consistency ato mund të jenë çfarëdo. Lind pyetja: pse e zgjedhin njerëzit Eventual Consistency, kur ajo përmban anomali? Përgjigja është se modelet e Eventual Consistency janë të aplikueshme, dhe anomalitë ekzistojnë, për shembull, për një periudhë të shkurtër; ka mundësinë për të përdorur master për të lexuar dhe në mënyrë më ose më pak për të lexuar të dhëna konsistente; shpesh ka mundësi për të përdorur modele të forta konsistence. Praktikisht, kjo funksionon, dhe shpesh numri i anomali-ve është i kufizuar në kohë.
Teorema CAP
Kur shihni fjalët konsistencë, disponueshmëri – çfarë ju vjen në mend? E saktë – teorema CAP! Dua të heq një mit… Nuk jam unë – ka Martin Kleppmann, i cili ka shkruar një artikull të shkëlqyer, një libër të shkëlqyer.

Teorema CAP – është një parim i formuluar në vitet 2000, që thotë se Konsistenca, Disponueshmëria, Particionet: merrni çdo dy, dhe nuk mund të zgjidhni tre. Ky ishte një parim. Ai u provua si teorem disa vjet më vonë, për të cilën u kujdesën Gilbert dhe Lynch. Pastaj kjo filloi të përdorej, si një mantra – sistemet filluan të ndahen në CA, CP, AP dhe kështu me radhë.
Kjo teoremë u provua në të vërtetë për këto raste… Së pari, Disponueshmëria u shqyrtua jo si një vlerë e vazhdueshme nga zero në njëqind (0 - sistemi "i vdekur", 100 - përgjigje të shpejtë; ne e kemi zakonisht të analizojmë kështu), por si një pronë e algoritmit që garanton se në të gjitha ekzekutimet e tij, ai kthen të dhëna.
Nuk ka asnjë fjalë për kohën e përgjigjes! Ekziston një algoritëm që kthen të dhëna pas 100 vjetësh – një algoritëm mjaft i disponueshëm, i cili është pjesë e teoremës CAP.
E dyta: teorema u provua për ndryshimet në vlerat e njëjti çelësi, ndonëse këto ndryshime janë një linjë e resizeable. Kjo do të thotë se ato në të vërtetë nuk përdoren shumë, sepse modelet e tjera janë Eventual Consistency, Strong Consistency (ndoshta).
Për çfarë po flasim? Për atë se teorema CAP në formën e saj, ashtu si është provuar, në të vërtetë nuk është shumë e aplikueshme, përdoret rrallë. Në formën teorike, ajo në një farë mënyre kufizon gjithçka. Kemi një parim, i cili është intuitivisht i vërtetë, por në përgjithësi nuk është provuar.
Konsistenca shkakësore – modeli më i fortë
Ajo që po ndodh tani – është e mundur të keni të gjitha tri gjërat: Konsistencën, Disponueshmërinë duke përdorur Particionet. Në veçanti, konsistenca shkakësore – modeli më i fortë i konsistencës, i cili në prani të Particioneve (çarjeve në rrjet) vazhdon të funksionojë. Prandaj, ajo përfaqëson një interes të madh, prandaj ne u angazhuam me të.

Së pari, ajo thjeshton punën e zhvilluesve të aplikacioneve. Në veçanti, ka mbështetje të madhe nga serveri: kur të gjitha shënimet që ndodhin brenda një klienti sigurohet që të vijnë në atë renditje te klienti tjetër. Së dyti, ajo përballon ndarjet.
Kuzhina brendshme e MongoDB
Duke pasur parasysh drekën, ne kalojmë në kuzhinë. Do të flas për modelin e sistemit, konkretisht – çfarë është MongoDB për ata që dëgjojnë për këtë bazë të dhënash për herë të parë.


MongoDB (më tej – «MongoDB») është një sistem i shpërndarë që mbështet shkallëzimin horizontal, dmth. sharding; dhe brenda çdo shard gjithashtu mbështet tepricën e të dhënave, dmth. replikimin.
Sharding në «MongoDB» (një DB jo-relacional) kryen balancimin automatike, dmth. çdo koleksion dokumentesh (ose «tabelë» në terminologjinë e të dhënave relacional) në pjesë, dhe tashmë serveri e lëviz ato automatikisht midis shards.
Query Router, i cili shpërndan kërkesat, për klientin është një klient i caktuar, përmes të cilit ai punon. Ai tashmë di se ku dhe cilat të dhëna ndodhen, drejton të gjitha kërkesat në shardin e duhur.
Një tjetër moment i rëndësishëm: MongoDB është një master i vetëm. Ka një Primar – ai mund të marrë shënime, mbështetur në ato çelësa që ai përmban. Nuk është e mundur të bësh shkruarje multi-master.
Ne kemi bërë lançimin 4.2 – aty janë shfaqur gjëra të reja interesante. Në veçanti, kemi futur Lucene – kërkimin – konkretisht executable java direkt në «Mongo», dhe tani është e mundur të bësh kërkime përmes Lucene, ashtu si në «Elasticsearch».
Dhe kemi krijuar një produkt të ri – Charts, i cili gjithashtu është i disponueshëm në «Atlas» (në vetë Cloud «Mongo»). Ata kanë Free Tier – mund të luash me këtë. Charts më ka pëlqyer shumë – vizualizimi i të dhënave, shumë intuitiv.
Përbërësit e konsistencës kauzale
Kam numëruar rreth 230 artikuj, të cilët janë publikuar mbi këtë temë – nga Leslie Lamport. Tani, nga kujtesa, do t'ju transmetoj disa pjesë të këtyre materialeve.

Çdo gjë filloi me një artikull nga Leslie Lamport, i cili u shkrua në vitet 1970. Siç e shihni, kërkimet mbi këtë temë vazhdojnë akoma. Aktualisht, konsistenca kauzale po përjeton një interes për shkak të zhvillimit të sistemeve të shpërndara.
Kufizimet
Çfarë kufizimesh ka? Kjo në të vërtetë është një nga piketat kryesore, sepse kufizimet që sistemet e prodhimit i vendosin janë shumë të ndryshme nga ato që ekzistojnë në artikujt akademikë. Shpesh ato janë mjaft artificiale.

- Së pari, «MongoDB» është një master i vetëm, siç e kam thënë më parë (kjo e bën gjithçka më të thjeshtë).
- Ne mendojmë se sistemi duhet të mbështesë rreth 10,000 shards. Nuk mund të marrim ndonjë vendim arkitekturor që do të kufizonte qartë këtë vlerë.
- Kemi një cloud, por supozojmë se personi duhet të ketë mundësinë, kur shkarkon binary, ta nisë atë në laptopin e tij dhe gjithçka të punojë përsosur.
- Ne supozojmë se në kërkime përdoret rrallë: klientët e jashtëm mund të bëjnë çfarëdo. «MongoDB» është open-source. Si rezultat, klientët mund të jenë kaq të zgjuar, të keq, mund të duan të prishin gjithçka. Ne supozojmë se mund të ndodhin Byzantine Failures.
- Për klientët e jashtëm, të cilët janë përtej perimetrave – një kufizim i rëndësishëm: nëse kjo veçori është e çaktivizuar, nuk duhet të ketë ndonjë degradim të performancës.
- Një tjetër moment – në përgjithësi antinë akademik: përputhshmëria e versioneve të mëparshme dhe atyre të ardhshme. Driverat e vjetër duhet të mbështesin përditësimet e reja, dhe DB duhet të mbështesë driverat e vjetër.
Në përgjithësi, gjithë kjo vendos kufizime.
Komponentët e konsistencës kauzale
Tani do të flas për disa komponentë. Nëse e shqyrtojmë në përgjithësi konsistencën kauzale, mund të identifikojmë blloqe. Ne zgjodhëm nga punimet që i përkasin një blloku të caktuar: Ndjekja e Varësive, zgjedhja e orëve, si mund të sinkronizohen këto orë me njëra-tjetrën, dhe si sigurojmë sigurinë – kjo është një përmbledhje e thjeshtë e asaj që do të flas:

Ndjekja e plotë e varësive (Full Dependency Tracking)
Pse është e nevojshme? Për të siguruar që, kur të dhënat replikohen – çdo shënim, çdo ndryshim të dhënash të përmbajë informacion rreth ndrrimeve nga të cilat varet. Ndryshimi më i parë dhe më i naiv është kur çdo mesazh që përmban një shënim, përmban informacion mbi mesazhet e mëparshme:

Në këtë shembull, numri në kllapa është numri i shënimeve. N sometimes këto shënime me vlera kalohen madje krejtësisht, ndonjëherë kalohen disa versione. Thelbi qëndron se çdo ndryshim përmban informacionin mbi të kaluarën (e sjell këtë gjithmonë me vete).
Pse vendosëm të mos përdorim këtë qasje (ndjekje e plotë)? Është e qartë, sepse kjo qasje është jopraktike: çdo ndryshim në një rrjet social varet nga të gjithë ndryshimet e mëparshme në këtë rrjet social, duke i kaluar, le të themi, "Facebook" ose "Vkontakte" në çdo përditësim. Megjithatë, ka shumë kërkime pikërisht mbi Ndjekjen e Plotë të Varësive – këto janë para rrjeteve sociale, për disa situata kjo vërtet funksionon.
Ndjekja e qartë e varësive (Explicit Dependency Tracking)
E ardhshmja – më e kufizuar. Këtu gjithashtu shqyrtohet transmetimi i informacionit, por vetëm atij që është qartë i varur. Çfarë varet nga çfarë, zakonisht e përcakton tashmë Aplikacioni. Kur të dhënat riprodhohen, në kërkesë jepen vetëm përgjigjet, kur varësitë e mëparshme janë përmbushur, pra janë treguar. Kjo është thelbi i funksionit të Causal consistency.

Ajo sheh se shënimi 5 varet nga shënimet 1, 2, 3, 4 – përkatësisht, ajo pret, përpara se klienti të ketë qasje në ndryshimet e kryera nga procedura e aksesit të Penny, kur të gjitha ndryshimet e mëparshme tashmë kanë kaluar në bazën e të dhënave.
Kjo gjithashtu nuk na kënaq, sepse megjithatë informacioni është shumë i madh, dhe do ta ngadalësonte. Ka një qasje tjetër...
Orët Lamport (Lamport Clock)
Ato janë shumë të vjetra. Orari Lamport nënkupton se këto varësi përmbledhin në një funksion skalar, i cili quhet Orari Lamport.
Një funksion skalar është një numër abstrakt. Shpesh quhet kohë logjike. Me çdo ngjarje ky numër rritet. Numri, i cili aktualisht është i njohur për procesin, dërgon çdo mesazh. Është e qartë se proceset mund të jenë jashtë sinkronizimi, ato mund të kenë kohë krejtësisht të ndryshme. Megjithatë, me këtë shkëmbim mesazhesh, sistemi balancoj orët. Çfarë ndodh në këtë rast?
E kam ndarë atë shard të madh në dy pjesë, që të jetë e qartë: Friends mund të jetojnë në një nod, i cili përmban një copë koleksioni, dhe Feed – në një nod tjetër, ku përmban një copë të kësaj koleksioni. Është e qartë se si ata mund të mos jenë në radhë? Në fillim Feed do të thotë: 'U riprodhua', dhe pastaj – Friends. Nëse sistemi nuk siguron ndonjë garanci që Feed nuk do të shfaqet derisa varësitë e Friends në koleksionin e Friends gjithashtu të jenë dorëzuar, atëherë na ndodh situata për të cilën po flas.
Shihni si rritet logjike koha e numrit në Feed:

Prandaj, pronësia kryesore e Orarit Lamport dhe Causal consistency (që shpjegohet përmes Orarit Lamport) është e tillë: nëse kemi ngjarje A dhe B, dhe ngjarja B varet nga ngjarja A *, atëherë nga kjo ndjekim se LogicalTime e Ngjarjes A është më e vogël se LogicalTime e Ngjarjes B.
* Ndonjëherë thuhet gjithashtu se A ndodhi para B, dmth A ndodhi përpara B – kjo është një marrëdhënie që rendit pjesërisht gjithsej ngjarjeve që ndodhin.
Në drejtimin e kundërt, kjo nuk është e vërtetë. Kjo është në të vërtetë një nga disavantazhet kryesore të Orarit Lamport – rendi pjesor. Atje ka një koncept për ngjarje të sinkronizuara, dmth ngjarje në të cilat as (A ndodhi para B) dhe as (A ndodhi para B). Një shembull mund të jetë shtimi paralel nga Leonard në miqtë e dikujt tjetër (madje jo nga Leonard, por nga Sheldon, për shembull).
Ky është një veçori që shpesh përdoret kur punoni me orët Lamport: shikoni pikërisht funksionin dhe nga këtu të nxirrni përfundimin – ndoshta këto ngjarje janë të varura. Sepse në një drejtim kjo është e vërtetë: nëse LogicalTime A është më e vogël se LogicalTime B, atëherë B nuk mund të ndodhi para A; dhe nëse është më e madhe, atëherë ndoshta.
Orët vektoriale (Vector Clock)
Zhvillimi logjik i Orëve Lamport është Orët Vektoriale. Ato dallohen nga fakti se çdo nod këtu përmban orët e tij të ndara dhe ato dërgohen si një vektor.
Në këtë rast, shihni se indeksi zero i vektorit përputhet me Feed, ndërsa indeksi i parë i vektorit me Friends (secili nga këto nod). Tani ata do të rriten: indeksi zero i 'Feed' rritet me shënimin – 1, 2, 3:

Çfarë është më e mira te Orët Vektoriale? Që lejojnë të kuptoni se cilat ngjarje janë sinkronizuar dhe kur ndodhin në nodet e ndryshme. Kjo është shumë e rëndësishme për sistemin e shardimit, si 'MongoDB'. Megjithatë, ne nuk zgjedhim këtë, ndonëse është një gjë e shkëlqyer, funksionon mirë dhe ndoshta do na përkiste...
Nëse kemi 10 mijë sharde, nuk mund të dërgojmë 10 mijë komponentë, edhe nëse i kompresojmë, duke menduar diçka tjetër – megjithatë ngarkesa është shumë më e vogël se vëllimi total i këtij vektori. Prandaj, me dhimbje në zemër dhe dhëmbë, ne u tërhoqëm nga kjo qasje dhe kaluam në një tjetër.
Spanner TrueTime. Orët atomike
Kam thënë se do të flas për 'Spanner'. Kjo është një gjë e mrekullueshme, me të vërtetë në shekullin XXI: orët atomike, sinkronizimi GPS.
Cila është ideja? «Spanner» është një sistem i Google që së fundmi ka filluar të jetë i aksesueshëm për njerëzit (ata i shtuan SQL atij). Çdo transaksion atje ka një fiksim të caktuar të kohës. Duke qenë se koha është e sinkronizuar*, çdo ngjarje mund t'i caktohet një fiksim i caktuar i kohës - orët atomike kanë një periudhë pritje, pas së cilës garanton që «ndodh» një kohë tjetër.

Kështu, thjesht duke regjistruar në DB dhe duke pritur një periudhë të caktuar kohe, automatikisht garantohet Serializability e ngjarjes. Ata kanë modelin më të fortë të Konsistencës, që mund të imagjinohet – ajo është Konsistenca Eksterne.
* Kjo është problemi kryesor i orëve të Lamportit – ato kurrë nuk janë në sinkronizim në sistemet e shpërndara. Ato mund të shkojnë në mënyrë të pasinkronizuar, edhe me NTP, megjithatë nuk funksionojnë shumë mirë. «Spanner» ka orë atomike dhe sinkronizim të tillë, duket se në mikrosekonda.
Pse nuk e zgjodhëm? Ne nuk presim që përdoruesit tanë të kenë orë atomike të integruara. Kur të bëhen të integruara në çdo laptop, do të ketë një sinkronizim super të shkëlqyer GPS – atëherë po... Ndërsa aktualisht, gjëja më e mirë që është e mundur – është «Amazon», Base Stations – për fanaticët... Prandaj ne përdorëm orë të tjera.
Orë Hibride (Hybrid Clock)
Kjo është në thelb ajo që tregon në «MongoDB» kur siguron Konsistencë Kausale. Ato janë hibride në çfarë? Hibridi është një vlerë skalarike, por ajo përbëhet nga dy komponente:

- E para – është epoka unix (sa sekonda kanë kaluar nga «fillimi i botës kompjuterike»).
- E dyta – një inkrementim, gjithashtu një int unsigned 32-bit.
Kjo është, në thelb, e gjitha. Ka një qasje të tillë: pjesa që merret me kohën, gjithmonë sinkronizohet me orët; sa herë që ndodh një përditësim, kjo pjesë sinkronizohet me orët dhe rezulton që koha është gjithmonë më shumë-më pak e saktë, ndërsa inkrementimi lejon të dallohet ngjarjet që ndodhin në të njëjtën kohë.
Pse është e rëndësishme kjo për «MongoDB»? Sepse lejon të bëhen disa rikthime rezervash në një moment të caktuar të kohës, dmth ngjarja indikohet me kohën. Kjo është thelbësore kur disa ngjarje kërkohen; për DB, ngjarjet janë ndryshimet në DB që ndodhin në intervale të caktuara të kohës.
Arsyeja kryesore do t'ju them vetëm juve (të lutem, mos e thuaj askujt tjetër)! Ne e bëmë këtë sepse kështu duken të dhënat e renditura dhe të indekstuara në MongoDB OpLog. OpLog është një strukturë të dhënash që përmban të gjitha ndryshimet në bazë: ato fillimisht shkojnë në OpLog dhe pastaj aplikohen në Storage, në rast se janë të dhëna të replikueshme ose të ndara.
Kjo ishte arsyeja kryesore. Megjithatë, ka edhe kërkesa praktike për zhvillimin e bazës, që do të thotë se duhet të jetë e thjeshtë – sa më pak kod, sa më pak gjëra të prishura që duhen rishkruar dhe testuar. Fakti që oplogët tanë ishin të indeksuar me orë hibride, ndihmoi shumë dhe mundësoi një zgjedhje të saktë. Kjo me të vërtetë e justifikoi veten dhe si për një magji, funksionoi që në prototipin e parë. Ishte shumë e bukur!
Sinkronizimi i orëve
Ka disa metoda sinkronizimi, të përshkruara në literaturën shkencore. Unë po flas për sinkronizimin kur kemi dy sharda të ndryshme. Nëse një grup replikash – nuk ka nevojë për asnjë sinkronizim: ky është një «master të vetëm»; kemi një OpLog, ku gjithe ndryshimet barten – në këtë rast gjithçka është renditur sekuencialisht në «OpLog». Por nëse kemi dy sharda të ndryshëm, këtu sinkronizimi i kohës është i rëndësishëm. Këtu orët vektoriale ndihmuan më shumë! Por ne nuk i kemi ato.

Një qëndrim tjetër është «Heartbeats». Mund të shkëmbejnë disa sinjale, që ndodhin çdo njësi kohe. Por «Heartbeats» janë shumë të ngadalta, ne nuk mund të sigurojmë latencën për klientin tonë.
Koha e vërtetë – natyrisht, është një gjë e mrekullueshme. Por, përsëri, ndoshta kjo është e ardhmja... Megjithëse në «Atlas» tashmë mund të bë shpërndarë; ka sinkronizues të kohës të shpejtë të «Amazon», por kjo nuk do të jetë e aksesueshme për të gjithë.
Gossiping – është kur të gjitha mesazhet përfshijnë kohën. Kjo është aty ku e përdorim. Çdo mesazh midis node-ve, drejtuesi, routeri i nënave të të dhënave, çdo gjë për «MongoDB» – janë disa elemente, komponentë të bazës së të dhënave, që përmbajnë orë që kalojnë. Ka gjithandej një vlerë të kohës hibride, ajo përcillet. 64 bite? Kjo është e mundur.
Si funksionon gjithçka së bashku?
Këtu po shqyrtoj një grup replikash, për të qenë pak më e thjeshtë. Ka Primary dhe Secondary. Sekondari bën replikimin dhe nuk është gjithmonë plotësisht i sinkronizuar me Primary.
Një insert po ndodh në "Primer" me një vlerë të caktuar kohe. Ky insert rrit numëruesin e brendshëm me 11, nëse ky është maksimal. Ose do të kontrollojë vlerat e orëve dhe do të sinkronizohet sipas orëve, nëse vlerat e orëve janë më të mëdha. Kjo lejon që të rendisim sipas kohës.
Pas regjistrimit, ndodh një moment i rëndësishëm. Orët në "MongoDB" rriten vetëm në rast të regjistrimit në "Oplog". Kjo është ngjarja që ndryshon gjendjen e sistemit. Në të gjitha artikujt klasikë, ngjarja konsiderohet si koha kur një mesazh arrin në nod: mesazhi arriti – do të thotë, sistemi ndryshoi gjendjen e tij.
Kjo ndodh sepse gjatë hetimit nuk mund të kuptohet si do të interpretohet ky mesazh. Ne e dimë me siguri se nëse nuk pasqyrohet në "Oplog", atëherë nuk do të interpretohet kurrë, dhe ndryshimi i gjendjes së sistemit është vetëm regjistrimi në "Oplog". Kjo e thjeshton: modelin e thjeshton dhe lejon renditjen brenda një grupi replikues, dhe shumë gjëra të tjera të dobishme.
Kthehet një vlerë që është regjistruar tashmë në "Oplog" – ne e dimë se kjo vlerë është dukur atje, dhe koha e saj është 12. Tani, le të themi, fillon leximi nga një nod tjetër (Sekondar), dhe ai transmeton tashmë afterClusterTime në vetë mesazhin. Ai thotë: "Më duhen të gjitha ato që ndodhën të paktën pas 12 ose gjatë dymbëdhjetës" (shih figurën më lart).
Kjo quhet Causal a consistent (CAT). Ekziston një koncept në teori, që është një prerje e kohës, e cila është vetë konsistente. Në këtë rast, mund të thuhet se kjo është gjendja e sistemit, e cila është vëzhguar në momentin 12.
Tani këtu nuk ka asgjë, sepse kjo simulohet si situatë ku Sekondari duhet të replikojë të dhënat nga Primari. Ai prit... Dhe ja, të dhënat erdhën – kthen këto vlera prapa.

Kështu funksionon gjithçka. Afërsisht.
Çfarë do të thotë "afërsisht"? Le të supozojmë se ka një person që ka lexuar dhe kuptuar se si funksionon gjithçka. E kuptoi se çdo herë ndodh ClusterTime, ai përditëson orët logjike të brendshme, dhe pastaj regjistrimi i ardhshëm rrit atë me një. Kjo funksion merr 20 rreshta. Le të themi se ky person transmeton numrin më të madh 64-bit, minus një.
Pse "minus një"? Sepse orët e brendshme do të vendosen në këtë vlerë (sigurisht, kjo është vlera maksimale e mundshme dhe më shumë se koha aktuale), pastaj do të ndodhë regjistrimi në "Oplog", dhe orët do të rriten akoma me një – dhe do të ketë tashmë vlerën maksimale (aty janë thjesht të gjitha një, nuk ka më shumë, unsaint int’ët).
E qartë se pas kësaj sistemi bëhet krejtësisht i pavlefshëm për gjithçka. Ai mund të shkarkohet vetëm, të pastrohet – shumë punë manuale. Disponueshmëria totale:

Nëse kjo replikon diku tjetër, atëherë thjesht e gjithë grupa do të shkojë nën. Një situatë krejtësisht e papranueshme, të cilën çdo person mund ta organizojë shumë shpejt dhe lehtë! Prandaj ne e trajtuam këtë moment si një nga më të rëndësishmit. Si ta parandalojmë atë?
Ruga jonë – të nënshkruajmë clusterTime
Ajo transmetohet në mesazh (para tekstit blu). Por ne filluam gjithashtu të gjenerojmë një nënshkrim (teksti blu):

Nënshkrimi gjenerohet me një çelës, i cili ruhet brenda bazës së të dhënave, brenda një perimetrin të sigurt; vetë gjenerohet, përditësohet (përdoruesit nuk shohin asgjë nga kjo). Një hash gjenerohet, dhe çdo mesazh gjatë krijimit nënshkruhet, ndërsa gjatë pranim – validizohet.
Me siguri lind një pyetje tek njerëzit: "Sa shumë ngadalëson kjo?" Kisha thënë se duhet të punojë shpejt, veçanërisht në mungesë të kësaj veçorie.
Çfarë do të thotë të përdorësh Causal consistency në këtë rast? Të tregohet parametri afterClusterTime. Ndryshe, ai do të transmetojë vlera në çdo rast. Gossiping, duke filluar nga versioni 3.6, punon gjithmonë.
Nëse ne mbajmë gjenerimin e vazhdueshëm të nënshkrimeve, atëherë kjo do ta ngadalësojë sistemin edhe në mungesë të veçorisë, që nuk përputhet me qasjet dhe kërkesat tona. Dhe çfarë bëmë ne?
Bëje këtë shpejt!
Një gjë mjaft e thjeshtë, por truku interesant – do të ndaj, ndoshta do të jetë interesante për disa.
Kemi një hash, ku ruhet të dhënat e nënshkruara. Të gjitha të dhënat kalojnë përmes një cache. Cache nënshkruan jo saktësisht kohën, por Range. Kur vjen një vlerë e caktuar, ne gjenerojmë Range, maskojmë 16 bitat e fundit, dhe këtë vlerë nënshkruajmë:

Duke këtë nënshkrim, ne përshpejtojmë sistemin (në mënyrë të kushtëzuar) 65,000 herë. Funksionon mrekullisht: kur bëmë eksperimentet – në të vërtetë koha u reduktua me 10,000 herë, kur kishim një përditësim të njëpasnjëshëm. Është e qartë se kur ato janë të çorganizuara, kjo nuk ndodh. Por në shumicën e rasteve praktike, kjo funksionon. Kombinimi i nënshkrimit Range së bashku me nënshkrimin e lejuan të zgjidhet problemi i sigurisë.
Çfarë mësuam?
Mësimet që nxorrëm nga kjo:
- Duhet të lexojmë materiale, histori, artikuj, sepse kemi shumë gjëra interesante. Kur punojmë në ndonjë funksionalitet (sidomos tani, kur po bëjmë transaksione etj.), duhet të lexojmë, të kuptojmë. Kjo merr kohë, por është shumë e dobishme, sepse kuptohet se ku jemi. Nuk kemi shpikur asgjë të re – thjesht morëm përbërësit.
Në të vërtetë, vërehet një ndryshim i caktuar në mënyrën e mendimit kur ka një konferencë akademike (p.sh. "Sigmon") – atje të gjithë përqendrohen në ide të reja. Cila është noviteti i algoritmit tonë? Këtu nuk ka ndonjë novitet të jashtëzakonshëm. Noviteti qëndron më shumë në atë si i kemi kombinuar qasjet ekzistuese. Prandaj e para – duhet të lexojmë klasiket, duke filluar nga Lamport.
- Në prodhim kërkesat janë krejt ndryshe. Unë jam i sigurt se shumë prej jush përballen jo me bazat e dhënash "sferike" në një boshllëk abstrakt, por me gjëra normale, reale, të cilat kanë probleme me disponibilitetin, vonesat dhe qëndrueshmërinë.
- E fundit – është se na duhet të shqyrtojmë ide të ndryshme dhe të kombinojmë disa artikuj krejt ndryshe në një qasje, së bashku. Ideja e nënshkrimit erdhi, për shembull, nga një artikull që shqyrtonte protokollin Paxos, për ndonjë fail orm që nuk është vizantian brenda protokollit të autorizimit, për ato vizantine – jashtë protokollit të autorizimit... Në thelb, kjo është ajo që ne përfundimisht bëmë.
Këtu nuk ka asgjë të re! Por sa herë që i kombinomim të gjitha... Është si të thuash se receta e sallatës Olivier është dështim, sepse vezët, majonezi dhe kastravecat tashmë janë shpikur... Është pak a shumë e njëjta histori.

Këtu e mbyll. Faleminderit!
Pyetje
Pyetje nga auditoriumi (më pas – P): – Faleminderit, Mikhail për prezantimin! Çështja për kohën është interesante. Ju përdorni Gossiping. Keni thënë se të gjithë kanë kohën e tyre, të gjithë e dinë kohën e tyre lokale. E kuptova se kemi një driver – klientët me driverë mund të kenë shumë, gjithashtu query-planner të shumtë, dhe shumë shards gjithashtu… Çfarë ndodh me sistemin, nëse papritmas ndodh një ndarje: dikush vendos që është një minutë përpara, dikush - një minutë mbrapa? Ku do të përfundojmë?
MT: – Pyetje shumë e mirë në të vërtetë! Pikërisht për shards doja të flisja. Nëse e kuptoj saktë pyetjen, kemi një situatë të tillë: ka shard 1 dhe shard 2, leximi ndodh nga këto dy shards – ata kanë ndarjen, ata nuk komunikohet me njëri-tjetrin, sepse koha që ata e dinë është e ndryshme, sidomos koha që ekziston në oplog.
Supozoni se shard 1 ka bërë një milion regjistrime, shard 2 asgjë, dhe kërkesa ka ardhur në dy shards. Dhe i pari ka afterClusterTime më shumë se një milion. Në një situatë të tillë, siç e shpjegova, shard 2 kurrë nuk do të përgjigjet.
M: – Doja të dija se si ata sinkronizohen dhe zgjedhin një kohë logjike?
MT: – Shumë thjesht sinkronizohen. Shardi, kur merr afterClusterTime, dhe nuk gjen kohën në "Oplog" – inicion no approved. Domethënë, ai e rrit me dorë kohën e tij në këtë vlerë. Kjo do të thotë se nuk ka ngjarje që i përgjigjen kësaj kërkese. Ai krijon këtë ngjarje në mënyrë artificiale dhe bëhet kështu Causal Consistent.
M: – Dhe nëse pas kësaj vijnë ndonjë ngjarje të tjera, që janë humbur diku në rrjet?
MT: – Shardi është ndërtuar në mënyrë që ato nuk do të vijnë më, sepse është single master. Nëse ai e ka regjistruar atë, ato nuk do të vijnë më, por do të jenë më pas. Nuk mund të ndodhë që diku diçka të ngecë, pastaj ai bën no write, dhe pastaj këto ngjarje erdhën – dhe u prish Causal consistency. Kur ai bën no write, ato të gjitha duhet të vijnë më tej (ai do t'i presë).

M: – Kam kam disa disa pyetje në lidhje me radhët. Kështu, konsistenca shkakësore sugjeron se ekziston një renditje e caktuar veprimesh që duhen kryer. Çfarë do të ndodhte nëse na humbet një paketë? Dola në të dhjetën, në të njëmbëdhjetën… paketa e dymbëdhjetë humbi, ndërsa të gjitha të tjerat po presin që ajo të ekzekutohet. Dhe papritmas, makina jonë vdes, nuk mund të bëjmë asgjë. A ka një gjatësi maksimale të radhës që mbledhët para se të ekzekutohet? Cila është dështimi fatal që ndodh nëse humbim ndonjë nga gjendjet? Akoma më tepër, nëse regjistrojmë se ka një gjendje të mëparshme, atëherë duhet të nisim nga ajo? Megjithatë, nuk u nisëm nga ajo!
MT: – Po, një tjetër pyetje e shkëlqyer! Çfarë bëjmë? Në MongoDB ka konceptin e shënimeve kuorum dhe leximin kuorum. Në cilat raste mund të humbasë një mesazh? Kur shënimi nuk është kuorum ose kur leximi nuk është kuorum (edhe kjo mund të sjellë ndonjë trashëgimi të padëshiruar).
Në lidhje me konsistencën shkakësore, ne kemi realizuar një kontroll të madh eksperimental, rezultat i të cilit është se kur shënimet dhe leximet janë të pa-kuorum, ndodhin shkelje të konsistencës shkakësore. Pikërisht ajo që thoni!
Këshilla jonë: përdorni të paktën leximin kuorum kur përdorni konsistencën shkakësore. Në këtë rast, asgjë nuk do të humbasë, madje nëse shënimi kuorum humbet... Kjo është një situatë ortogonale: nëse një përdorues nuk dëshiron që të dhënat të humbin, duhet të përdorë shënime kuorum. Konsistenca shkakësore nuk ofron garanci për qëndrushmërinë. Garancitë për qëndrushmërinë ofrojnë replikimi dhe mekanizmat e lidhura me replikimin.
M: – Kur krijojmë një instancë, e cila kryen shpërndarjen (jo master, por slave përkatësisht), a mbështetet në kohën unix të makinës së saj apo në kohën e "masterit"; a sinkronizohet për herë të parë apo periodikisht?
MT: – Tani do të sqarohem. Shard (dmth. ndarja horizontale) – atje gjithmonë ka një Primar. Dhe në shard mund të ketë "master" dhe mund të ketë replika. Por shard gjithmonë mbështet shënimin, sepse duhet të mbajë një domen të caktuar (në shard ndodhet Primari).
M: – Pra, gjithçka varet vetëm nga "masteri"? A përdoret gjithmonë koha e "masterit"?
MT: – Po. Mund ta themi figurativisht: orët bien, kur ndodh shënimi në "master", në "OpLog".
M: – Kemi një klient që lidhet dhe nuk ka nevojë të dijë asgjë për kohën?
MT: – Aspak nuk ka nevojë të dijë asgjë! Nëse flasim për mënyrën se si funksionon në klient: klienti, kur dëshiron të përdorë konsistencën shkakësore, duhet të hapë një sesion. Atje është gjithçka: dhe transaksionet në sesion, dhe marrja e të drejtave... Sesioni është një renditje e ngjarjeve logjike që ndodhin me klientin.
Nëse ai hap këtë sesion dhe thotë se dëshiron konsistencën shkakësore (nëse si parazgjedhje sesioni mbështet konsistencën shkakësore), gjithçka funksionon automatikisht. Drejtori memorizon këtë kohë dhe e rrit kur merr një mesazh të ri. Ai memorizon se çfarë përgjigjeje ktheu serveri i mëparshëm që kthente të dhënat. Kërkesa e ardhshme do të përmbajë afterCluster ("koha më e madhe se kjo").
Klienti nuk ka nevojë të dijë fare asgjë! Është absolutisht e padukshme për të. Nëse njerëzit përdorin këto veçori, çfarë lejon të bëhet? Në radhë të parë, mund të lexoni në mënyrë të sigurt nga secondaries: mund të shkruani në Primar, dhe të lexoni nga secondaries të riprodhuara gjeografikisht dhe të jeni të sigurt se kjo funksionon. Në këtë rast, sesionet që janë regjistruar në Primar mund të përcillen edhe në Secondary, dmth. mund të përdoren jo një sesion, por disa.
M: – Temat lidhur me konsistencën eventuale janë shumë të lidhura me një shtresë të re të shkencës kompjuterike – llojet e të dhënave CRDT (Tipet e të Dhënave të Replikuara pa Konflikta). A keni shqyrtuar integrimin e këtyre llojeve të të dhënave në bazë dhe çfarë mund të thoni për këtë?
MT: – Pyetje e mirë! CRDT ka kuptim për konflikte gjatë shënimit: në MongoDB – një master i vetëm.
M: – Kam një pyetje nga devops. Në botën reale hasen situata të tilla ishuetike, kur ndodhin dështime bizantine, dhe njerëz të këqij brenda perimetrin e sigurisë fillojnë të ndërhyjnë në protokoll, duke dërguar paketa të craftuara në mënyrë të veçantë?

MT: – Njerëzit e këqij brenda perimetrin – është e njëjtë si një kalë Troje! Njerëzit e këqij brenda perimetrin mund të bëjnë shumë gjëra të këqija.
M: – Natyrisht, lënia në server, në terma të thjeshtë, e një vrimë, përmes së cilës mund të kaloni një çerdhe elefantesh dhe të shembni të gjithë clusterin përgjithmonë... Do të kërkohet kohë për rikuperim manual... Kjo, lehtësisht, është e gabuar. Nga ana tjetër, është interesante të dini: në jetën reale, në praktikë, ndodhin situata të tilla kur sulme të brendshme ndodhin natyrshëm?
MT: – Pavarësisht se nuk kam hasur shpesh në shkelje të sigurisë në jetën reale, nuk mund të them - ndoshta ato ndodhin. Por nëse flasim për filozofinë e zhvilluesve, mendojmë kështu: kemi një perimetër që siguron ata që merakosen për sigurinë - ky është një çelës, një mur; dhe brenda perimetrin mund të bësh gjithçka. Është e qartë se ka përdorues me mundësi vetëm për të parë, dhe ka përdorues me mundësi për të fshirë një katalog.
Në varësi të të drejtave, dëmimi që përdoruesit mund të shkaktojnë mund të jetë si me një mi, ashtu edhe me një elefant. Është e qartë se përdoruesi me të drejta të plota mund të bëjë gjithçka. Përdoruesi me të drejta të ngushta mund të shkaktojë ndjeshëm më pak dëm. Në veçanti, ai nuk mund ta prishë sistemin.
M: – Në një perimetrin e mbrojtur, dikush mund të provojë të formojë protokolle të papritura për serverin, për ta vënë serverin në një pozitë të vështirë, dhe nëse ka fat, ndoshta edhe tërë klasterin... A ndodhin ndonjëherë kaq "mirë"?
MT: – Asnjëherë nuk kam dëgjuar për gjëra të tilla. Që mund të dëmtohet serveri në këtë mënyrë - kjo nuk është sekret. Të shkathtërosh brenda, duke qenë me protokoll, si përdorues i autorizuar që mund të shkruajë në mesazhin diçka të tillë... Në të vërtetë, nuk mundet, sepse gjithsesi do të verifikohet. Ka mundësi për të çaktivizuar këtë autentikim për ata përdorues që nuk e duan - kjo atëherë është problemi i tyre; ata, thjesht, vetë shkatërruan muret dhe mund të fusin aty një elefant që do t'i shkatërrojë... Në përgjithësi, mund të vishesh si teknik, të vish dhe ta nxjerrësh!
M: – Faleminderit për raportin. Sergey ("Yandex"). Në "Mongo" ka një konstantë që kufizon numrin e anëtarëve votues në Replica Set, dhe kjo konstantë është e barabartë me 7 (shtatë). Pse është kjo konstantë? Pse nuk është ndonjë parametër?
MT: – Replica Set kemi edhe 40 nodule. Aty gjithmonë është shumica. Nuk di cila është versioni...
M: – Në Replica Set mund të nisin anëtarë që nuk votojnë, por për votuesit - maksimumi 7. Si mund të përballohet një ndërprerje nëse kemi një Replica Set të shpërndarë në 3 qendra të dhënash? Një qendër mund të shuhet lehtësisht, dhe një makinë tjetër të bjerë.
MT: – Kjo është jashtë raportit pak. Kjo është një pyetje e përgjithshme. Ndoshta më vonë mund ta tregoj.


Pak reklamë 🙂
Faleminderit që qëndroni me ne. Ju pëlqejnë artikujt tanë? Dëshironi të shihni më shumë materiale interesante? Na mbështetni duke bërë një porosi ose duke na rekomanduar njohurive tuaj, , një analog unik i serverëve entry-level, i ndërtuar për ju: (disponohen variante me RAID1 dhe RAID10, deri në 24 bërthama dhe deri në 40GB DDR4).
Dell R730xd dyfish më i lirë në qendrën e të dhënave Equinix Tier IV në Amsterdam? Vetëm këtu në Holandë! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — nga $99! Lexoni rreth
Burimi: habr.com
