HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

A következő HighLoad++ konferenciát 6. április 7-án és 2020-én tartják Szentpéterváron.
Részletek és jegyek по ссылке. HighLoad++ Szibéria 2019. Csarnok "Krasnojarszk". június 25., 12:00. Tézisek és előadás.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Előfordul, hogy a gyakorlati követelmények ütköznek az elmélettel, ahol a kereskedelmi termék szempontjából fontos szempontokat nem veszik figyelembe. Ez az előadás bemutatja a különböző megközelítések kiválasztásának és kombinálásának folyamatát az ok-okozati konzisztencia összetevőinek létrehozására, tudományos kutatások alapján, egy kereskedelmi termék követelményei alapján. A hallgatók megismerhetik a logikai órák létező elméleti megközelítéseit, a függőségi nyomon követést, a rendszerbiztonságot, az óraszinkronizálást és azt, hogy a MongoDB miért döntött bizonyos megoldások mellett.

Mihail Tyulenev (a továbbiakban: MT): – Az ok-okozati konzisztenciáról fogok beszélni – ezen a funkción dolgoztunk a MongoDB-ben. Elosztott rendszerek csoportjában dolgozom, kb. két éve csináltuk.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Ennek során rengeteg tudományos kutatással kellett megismerkednem, mert ezt a tulajdonságot elég jól tanulmányozták. Kiderült, hogy egyetlen cikk sem fér bele a termelési adatbázisban előírtak közé, mivel nagyon specifikus követelmények vannak, amelyek valószínűleg bármely termelési alkalmazásban jelen vannak.

Arról fogok beszélni, hogy mi, az akadémiai Kutatás fogyasztói, hogyan készítünk belőle valamit, amit aztán kényelmesen és biztonságosan használható kész ételként bemutathatunk felhasználóinknak.

Ok-okozati konzisztencia. Határozzuk meg a fogalmakat

Először is szeretném általánosságban elmondani, mi az oksági konzisztencia. Két karakter van - Leonard és Penny ("The Big Bang Theory" tévésorozat):

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Tegyük fel, hogy Penny Európában van, és Leonard meglepetéspartit akar neki rendezni. És nem is tud jobbat kitalálni, mint kidobni a barátlistájáról, és minden barátjának elküldeni a hírfolyamról: „Tegyük boldoggá Pennyt!” (Európában van, miközben alszik, mindezt nem látja és nem is láthatja, mert nincs ott). Végül törli ezt a bejegyzést, törli a hírfolyamból, és visszaállítja a hozzáférést, hogy ne vegyen észre semmit, és ne legyen botrány.
Ez mind szép és jó, de tegyük fel, hogy a rendszer elosztott, és a dolgok egy kicsit rosszul sültek el. Előfordulhat például, hogy Penny hozzáférési korlátozása a bejegyzés megjelenése után történt, ha az események nem ok-okozati összefüggésben állnak egymással. Valójában ez egy példa arra, amikor az ok-okozati összefüggésre van szükség egy üzleti funkció végrehajtásához (ebben az esetben).

Valójában ezek az adatbázis nem triviális tulajdonságai - nagyon kevesen támogatják őket. Térjünk át a modellekre.

Konzisztencia modellek

Mit is jelent pontosan a konzisztencia modell az adatbázisokban? Ez néhány olyan garancia, amelyet egy elosztott rendszer ad arra vonatkozóan, hogy a kliens milyen adatokat kaphat és milyen sorrendben.

Elvileg minden konzisztenciamodell arra megy ki, hogy mennyire hasonlít egy elosztott rendszer egy olyan rendszerhez, amely például egy laptop egyik csomópontján fut. És ennyire hasonlít egy több ezer geo-elosztott „Node-on” futó rendszer egy laptophoz, amelyben mindezek a tulajdonságok elvileg automatikusan végrehajtódnak.

Ezért a konzisztencia modelleket csak elosztott rendszerekre alkalmazzák. Az összes korábban létező és ugyanazzal a függőleges skálázással működő rendszer nem tapasztalt ilyen problémákat. Egy puffergyorsítótár volt, és mindig abból olvastak ki mindent.

Modell Erős

Valójában a legelső modell a Strong (vagy az emelkedési képesség vonal, ahogy gyakran nevezik). Ez egy konzisztenciamodell, amely biztosítja, hogy minden változás, miután megtörtént, látható legyen a rendszer összes felhasználója számára.

Ez létrehozza az adatbázisban lévő összes esemény globális sorrendjét. Ez egy nagyon erős konzisztencia tulajdonság, és általában nagyon drága. Ez azonban nagyon jól támogatott. Csak nagyon drága és lassú – csak ritkán használják. Ezt emelkedési képességnek nevezik.

Van egy másik, erősebb tulajdonság, amelyet a Spanner támogat – az úgynevezett Külső konzisztencia. Kicsit később beszélünk róla.

Okozati

A következő a Causal, pontosan erről beszéltem. Az Erős és az Ok-okozati összefüggések között van még néhány alszint, amelyekről nem beszélek, de ezek mindegyike az ok-okozati összefüggésbe vezet le. Ez egy fontos modell, mert ez a legerősebb az összes modell közül, a legerősebb konzisztencia hálózat vagy partíciók jelenlétében.

Az ok-okozati összefüggések valójában egy olyan helyzet, amelyben az eseményeket ok-okozati összefüggés köti össze. Nagyon gyakran úgy tekintenek rájuk, mint az ügyfél szemszögéből olvassa el a jogait. Ha az ügyfél megfigyelt bizonyos értékeket, akkor nem láthat olyan értékeket, amelyek a múltban voltak. Már kezdi látni az előtag olvasatait. Minden ugyanarra a dologra vezethető vissza.
Az ok-okozati összefüggések mint konzisztencia modell az események részleges rendezése a szerveren, amelyben az összes kliens eseményei ugyanabban a sorrendben figyelhetők meg. Jelen esetben Leonard és Penny.

Végső

A harmadik modell az esetleges konzisztencia. Ez az, amit abszolút minden elosztott rendszer támogatja, az a minimális modell, aminek egyáltalán van értelme. Ez a következőt jelenti: amikor az adatokban változás történik, azok egy ponton konzisztenssé válnak.

Ebben a pillanatban nem mond semmit, különben külső konzisztenciává változna - ez egy teljesen más történet. Ennek ellenére ez egy nagyon népszerű modell, a leggyakoribb. Alapértelmezés szerint az elosztott rendszerek összes felhasználója az Esetleges konzisztenciát használja.

Néhány összehasonlító példát szeretnék mondani:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Mit jelentenek ezek a nyilak?

  • Késleltetés. A konzisztencia erősségének növekedésével nyilvánvaló okokból nagyobb lesz: több rekordot kell készítenie, meg kell erősítenie a fürtben részt vevő összes gazdagéptől és csomóponttól, hogy az adatok már megvannak. Ennek megfelelően az Eventual Consistency-nek van a leggyorsabb a válasza, mert ott rendszerint akár a memóriába is jegyezhető, és ez elvileg elég lesz.
  • Elérhetőség. Ha ezt úgy értjük, hogy a rendszer képes reagálni hálózati megszakítások, partíciók vagy valamilyen meghibásodás esetén, akkor a hibatűrés a konzisztenciamodell csökkenésével növekszik, hiszen nekünk elég, ha egy gazdagép él és egyben. az idő termel bizonyos adatokat. Az esetleges konzisztencia egyáltalán nem garantál semmit az adatokról – bármi lehet.
  • Anomáliák. Ezzel párhuzamosan természetesen nő az anomáliák száma. Az Erős Konzisztenciában szinte egyáltalán nem kellene létezniük, de az Esetleges konzisztenciában bármi lehet. Felmerül a kérdés: miért választják az emberek a Végső konzisztenciát, ha az anomáliákat tartalmaz? A válasz az, hogy a végső konzisztencia modellek alkalmazhatók, és az anomáliák például rövid időn belül léteznek; lehetőség van a varázsló használatával konzisztens adatok olvasására és többé-kevésbé olvasására; Gyakran lehetséges erős konzisztencia modellek alkalmazása. A gyakorlatban ez működik, és gyakran az anomáliák száma időben korlátozott.

CAP tétel

Ha a következetesség, elérhetőség szavakat látod – mi jut eszedbe? Így van – CAP tétel! Most szeretném eloszlatni a mítoszt... Nem én vagyok az, hanem Martin Kleppmann, aki egy csodálatos cikket, egy csodálatos könyvet írt.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

A CAP-tétel a 2000-es években megfogalmazott alapelv, miszerint konzisztencia, elérhetőség, partíciók: vegyünk bármelyik kettőt, és nem választhatunk hármat. Ez egy bizonyos elv volt. Néhány évvel később Gilbert és Lynch tételként bebizonyította. Aztán ezt kezdték mantraként használni - a rendszereket CA, CP, AP és így tovább osztották.

Ez a tétel a következő esetekre tulajdonképpen be is igazolódott... Először is, az Elérhetőséget nem nullától százig terjedő folytonos értéknek tekintettük (0 - a rendszer „halott”, 100 – gyorsan reagál; megszoktuk, hogy így tekintjük) , hanem az algoritmus tulajdonságaként, amely garantálja, hogy minden végrehajtásához adatokat ad vissza.

A válaszidőről egy szó sincs! Létezik egy algoritmus, amely 100 év után visszaadja az adatokat – egy teljesen csodálatos elérhető algoritmus, amely a CAP-tétel része.
Másodszor: a tétel bizonyítást nyert ugyanazon kulcs értékeinek változására, annak ellenére, hogy ezek a változások átméretezhetők. Ez azt jelenti, hogy a valóságban gyakorlatilag nem használják őket, mert a modellek különbözőek. Lehetséges konzisztencia, erős konzisztencia (talán).

Minek ez az egész? Ezenkívül a CAP-tétel pontosan abban a formában, amelyben igazolták, gyakorlatilag nem alkalmazható, és ritkán használják. Elméleti formában valahogy mindent behatárol. Kiderül egy bizonyos elv, amely intuitívan helyes, de általában nem bizonyított.

Az ok-okozati konzisztencia a legerősebb modell

Ami most történik, az az, hogy mindhárom dolgot elérheti: konzisztencia, elérhetőség partíciókkal. Különösen az oksági konzisztencia a legerősebb konzisztencia-modell, amely partíciók (hálózati megszakítások) esetén is működik. Ezért olyan nagy az érdeklődés, és ezért vállaltuk fel.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Először is leegyszerűsíti az alkalmazásfejlesztők munkáját. Különösen a szerver nagy támogatása: amikor az egyik kliensen belül előforduló összes rekord garantáltan ugyanabban a sorrendben érkezik egy másik kliensre. Másodszor, ellenáll a partícióknak.

MongoDB belső konyha

Eszébe jutva, hogy ebéd van, kimentünk a konyhába. A rendszermodellről, nevezetesen arról, hogy mi az a MongoDB, elmondom azoknak, akik először hallanak ilyen adatbázisról.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

A MongoDB (a továbbiakban: „MongoDB”) egy elosztott rendszer, amely támogatja a vízszintes skálázást, azaz a shardingot; és minden szilánkon belül támogatja az adatredundanciát, vagyis a replikációt is.

A MongoDB (nem relációs adatbázis) felosztása automatikus egyensúlyozást hajt végre, vagyis minden dokumentumgyűjtemény (vagy relációs adatokkal „táblázat”) darabokra van osztva, és a szerver automatikusan áthelyezi őket a szilánkok között.

A Query Router, amely elosztja a kéréseket egy ügyfél számára, egy olyan ügyfél, amelyen keresztül működik. Már tudja, hol és milyen adatok találhatók, és minden kérést a megfelelő szilánkra irányít.

Egy másik fontos pont: a MongoDB egyetlen mester. Van egy elsődleges – olyan rekordokat vehet fel, amelyek támogatják a benne lévő kulcsokat. Nem írhat több mestert.

Elkészítettük a 4.2-es kiadást – új érdekességek jelentek meg ott. Konkrétan a Lucene - search - azaz végrehajtható java-t illesztették be közvetlenül a Mongo-ba, és ott lehetővé vált a Lucene-en keresztüli keresés, ugyanúgy, mint az Elasticában.

És készítettek egy új terméket - Charts-ot, amely az Atlas-on (Mongo saját felhője) is elérhető. Van egy ingyenes szintjük – játszhatsz vele. Nagyon tetszett a Charts - adatvizualizáció, nagyon intuitív.

Összetevők Ok-okozati konzisztencia

Körülbelül 230 cikket számoltam meg, amelyek megjelentek ebben a témában - Leslie Lamperttől. Most emlékezetem szerint átadok Önnek ezeknek az anyagoknak néhány részét.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Az egész Leslie Lampert cikkével kezdődött, amely az 1970-es években íródott. Mint látható, néhány kutatás még folyamatban van ebben a témában. Most az oksági konzisztencia iránt érdeklődik az elosztott rendszerek fejlesztése kapcsán.

Korlátozások

Milyen korlátozások vannak? Valójában ez az egyik fő szempont, mert a termelési rendszer által támasztott korlátozások nagyon különböznek az akadémiai cikkekben szereplő korlátozásoktól. Gyakran meglehetősen mesterségesek.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

  • Először is, a „MongoDB” egyetlen mester, amint már mondtam (ez nagyban leegyszerűsíti).
  • Úgy gondoljuk, hogy a rendszernek körülbelül 10 ezer szilánkot kellene támogatnia. Nem hozhatunk olyan építészeti döntéseket, amelyek ezt az értéket kifejezetten korlátozzák.
  • Van egy felhőnk, de feltételezzük, hogy az embernek továbbra is meg kell adni a lehetőséget, amikor letölti a bináris fájlt, futtatja a laptopján, és minden remekül működik.
  • Feltételezünk valamit, amit a Research ritkán feltételez: a külső ügyfelek azt tehetnek, amit akarnak. A MongoDB nyílt forráskódú. Ennek megfelelően az ügyfelek olyan okosak és dühösek lehetnek – mindent össze akarhatnak törni. Azt gyanítjuk, hogy bizánci feilorok származhatnak.
  • A kerületen kívüli külső kliensek esetében van egy fontos korlátozás: ha ez a funkció le van tiltva, akkor nem figyelhető meg a teljesítmény romlása.
  • Egy másik szempont általában anti-akadémia: a korábbi és a jövőbeli verziók kompatibilitása. A régi illesztőprogramoknak támogatniuk kell az új frissítéseket, az adatbázisnak pedig a régi illesztőprogramokat.

Általában mindez korlátozásokat támaszt.

Ok-okozati konzisztencia összetevői

Most néhány összetevőről fogok beszélni. Ha az ok-okozati konzisztenciát általánosságban vesszük figyelembe, akkor kijelölhetünk blokkokat. Egy bizonyos blokkhoz tartozó művek közül válogattunk: Dependency Tracking, óraválasztás, hogyan lehet ezeket az órákat szinkronizálni egymással, és hogyan biztosítjuk a biztonságot - ez egy hozzávetőleges vázlat, amiről beszélni fogok:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Teljes függőségkövetés

Miért van rá szükség? Annak érdekében, hogy az adatok replikálásakor minden rekord, minden adatváltozás információt tartalmazzon arról, hogy milyen változásoktól függ. A legelső és naiv változás az, amikor minden rekordot tartalmazó üzenet tartalmaz információkat a korábbi üzenetekről:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Ebben a példában a zárójelben lévő szám a rekordszám. Néha ezeket az értékeket tartalmazó rekordokat teljes egészükben, néha egyes verziókat is átadnak. A lényeg az, hogy minden változtatás információt tartalmaz az előzőről (nyilván mindezt magában hordozza).

Miért döntöttünk úgy, hogy nem alkalmazzuk ezt a megközelítést (teljes nyomon követés)? Nyilvánvalóan azért, mert ez a megközelítés nem praktikus: a közösségi hálózaton végzett bármilyen változtatás az adott közösségi hálózat összes korábbi módosításától függ, mondjuk a Facebook vagy a VKontakte minden frissítésnél átkerül. Ennek ellenére sok kutatás folyik a teljes függőség nyomon követéséről – ezek pre-szociális hálózatok; bizonyos helyzetekben valóban működik.

Explicit Dependency Tracking

A következő korlátozottabb. Itt is szóba kerül az információátadás, de csak az egyértelműen függő. Az, hogy mitől függ, általában az Alkalmazás határozza meg. Adatok replikálásakor a lekérdezés csak akkor ad vissza válaszokat, ha a korábbi függőségek teljesültek, azaz megjelennek. Ez az oksági konzisztencia működésének lényege.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Látja, hogy az 5. rekord az 1., 2., 3., 4. rekordtól függ – ennek megfelelően megvárja, mielőtt az ügyfél hozzáférhet a Penny hozzáférési döntése által végrehajtott módosításokhoz, amikor az összes korábbi módosítás már átment az adatbázison.

Ez sem felel meg nekünk, mert még mindig túl sok az információ, és ez lelassítja a dolgokat. Van egy másik megközelítés is...

Lamport óra

Nagyon öregek. A Lamport Clock azt jelenti, hogy ezek a függőségek egy skaláris függvénybe vannak hajtva, amelyet Lamport órának neveznek.

A skalárfüggvény egy absztrakt szám. Ezt gyakran logikai időnek nevezik. Ez a számláló minden eseménnyel növekszik. A folyamat számára jelenleg ismert számláló minden üzenetet elküld. Egyértelmű, hogy a folyamatok szinkronban lehetnek, teljesen eltérő időpontok lehetnek. Ennek ellenére a rendszer valahogy egyensúlyba hozza az órát az ilyen üzenetekkel. Mi történik ebben az esetben?

Ezt a nagy szilánkot kettéosztottam, hogy egyértelmű legyen: a barátok egy csomópontban élhetnek, amely a gyűjtemény egy darabját tartalmazza, és a Feed egy másik csomópontban, amely ennek a gyűjteménynek egy darabját tartalmazza. Világos, hogyan tudnak kilógni a sorból? Az első hírcsatorna a következőt fogja mondani: „Replicated”, majd a Friends. Ha a rendszer nem ad valamiféle garanciát arra, hogy a hírfolyam addig nem jelenik meg, amíg a Friends gyűjteményben lévő Friends függőségeket is át nem szállítják, akkor pontosan az általam említett helyzet lesz.

Láthatja, hogyan növekszik logikusan a hírfolyam számláló ideje:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Tehát ennek a Lamport-órának és az oksági konzisztenciának a fő tulajdonsága (a Lamport-órán keresztül magyarázva) a következő: ha van A és B eseményünk, és B esemény az A* eseménytől függ, akkor ebből az következik, hogy az A esemény logikai ideje kisebb, mint Logikai idő a B eseményből.

* Néha azt is mondják, hogy A történt B előtt, vagyis A történt B előtt - ez egy bizonyos összefüggés, amely részben rendezi az általában megtörtént események teljes halmazát.

Az ellenkezője helytelen. Valójában ez a Lamport Clock egyik fő hátránya - részleges rendelés. Létezik egy fogalom az egyidejű eseményekről, vagyis olyan eseményekről, amelyekben sem (A történt B előtt), sem (A nem történt B előtt). Példa erre, ha Leonard párhuzamosan valaki mást is barátként ad hozzá (nem is Leonardot, hanem például Sheldont).
Ez az a tulajdonság, amit gyakran használnak a Lamport órákkal való munkavégzés során: konkrétan a funkciót nézik, és ebből arra következtetnek, hogy talán ezek az események függőek. Mert egy mód igaz: ha A logikai idő kisebb, mint B logikai idő, akkor B nem történhet meg A előtt; és ha több, akkor talán.

vektoros óra

A Lamport óra logikai fejlesztése a Vector Clock. Abban különböznek egymástól, hogy minden itt található csomópont külön órával rendelkezik, és vektorként továbbítják őket.
Ebben az esetben azt látja, hogy a vektor nulladik indexe felelős a hírfolyamért, a vektor első indexe pedig a Friends (ezek a csomópontok mindegyike). És most növekedni fognak: a „Feed” nulla indexe növekszik írás közben - 1, 2, 3:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Miért jobb a Vector Clock? Mert lehetővé teszik, hogy kitaláljuk, mely események egyidejűek, és mikor következnek be a különböző csomópontokon. Ez nagyon fontos egy olyan felosztási rendszernél, mint a MongoDB. Viszont nem ezt választottuk, pedig csodálatos dolog, és remekül működik, és valószínűleg megfelelne nekünk...

Ha van 10 ezer szilánkunk, nem tudunk 10 ezer komponenst átvinni, még akkor sem, ha tömörítjük, vagy kitalálunk valami mást - a hasznos teher akkor is többszöröse lesz, mint ennek a vektornak a térfogata. Ezért a szívünket és a fogunkat csikorgatva felhagytunk ezzel a megközelítéssel, és áttértünk egy másikra.

Villáskulcs TrueTime. Atomóra

Azt mondtam, hogy lesz egy történet Spannerről. Ez egy klassz dolog, egyenesen a XNUMX. századból: atomórák, GPS szinkronizálás.

mi az ötlet? A „Spanner” egy Google rendszer, amely nemrég még az emberek számára is elérhetővé vált (az SQL-t hozzáadták hozzá). Minden tranzakciónak van időbélyegzője. Mivel az idő szinkronizált*, minden eseményhez hozzá lehet rendelni egy adott időpontot – az atomóráknak van várakozási ideje, ami után garantáltan más időpont „történik”.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Így ha egyszerűen írunk az adatbázisba és várunk egy ideig, az esemény sorozatozhatósága automatikusan garantált. Náluk van a legerősebb konzisztencia-modell, ami elvileg elképzelhető – ez a külső konzisztencia.

* Ez a fő probléma a Lampart órákkal – soha nem szinkronizálnak elosztott rendszereken. Eltérhetnek egymástól; még az NTP-vel sem működnek túl jól. A "Spanner"-nek atomórája van, és a szinkronizálás, úgy tűnik, mikroszekundum.

Miért nem választottunk? Nem feltételezzük, hogy felhasználóink ​​beépített atomórával rendelkeznek. Amikor megjelennek, minden laptopba beépítve lesz valami szuper menő GPS szinkronizálás - akkor igen... De egyelőre a lehető legjobb az Amazon, Base Stations - fanatikusoknak... Szóval más órákat használtunk .

Hibrid óra

Valójában ez az, ami a MongoDB-ben ketyeg az oksági konzisztencia biztosításakor. Hogy hibridek? A hibrid skaláris érték, de két összetevőből áll:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

  • Az első a Unix-korszak (hány másodperc telt el a „számítógép-világ kezdete óta”).
  • A második némi növekmény, szintén egy 32 bites előjel nélküli int.

Valójában ennyi. Létezik ez a megközelítés: az időért felelős rész folyamatosan szinkronban van az órával; Minden alkalommal, amikor frissítés történik, ez a rész szinkronizálódik az órával, és kiderül, hogy az idő többé-kevésbé helyes, és a növekmény lehetővé teszi az azonos időpontban bekövetkezett események megkülönböztetését.

Miért fontos ez a MongoDB számára? Mert lehetővé teszi, hogy egy adott időpontban készítsünk valamilyen tartalék éttermet, vagyis az eseményt idő szerint indexeljük. Ez akkor fontos, ha bizonyos eseményekre van szükség; Egy adatbázis esetében az események bizonyos időközönként bekövetkezett változások az adatbázisban.

A legfontosabb okot csak neked mondom el (kérlek, ne mondd el senkinek)! Azért tettük ezt, mert így néznek ki a szervezett, indexelt adatok a MongoDB OpLogban. Az OpLog egy olyan adatstruktúra, amely az adatbázisban végbemenő összes változást tartalmazza: először az OpLog-ba kerülnek, majd magára a Storage-ra kerülnek alkalmazásra abban az esetben, ha az egy replikált dátum vagy szilánk.

Ez volt a fő ok. Ennek ellenére gyakorlati követelményei is vannak az adatbázis fejlesztésének, ami azt jelenti, hogy egyszerűnek kell lennie - kevés kódot, minél kevesebb hibás, újraírandó és tesztelnivaló dolgot. Az a tény, hogy az oplogjainkat hibrid órákkal indexelték, sokat segített, és lehetővé tette a helyes választást. Nagyon kifizetődött, és valahogy varázslatosan működött a legelső prototípuson. Nagyon klassz volt!

Óra szinkronizálás

A tudományos irodalomban számos szinkronizálási módszert ismertetnek. Szinkronizálásról beszélek, amikor két különböző szilánkunk van. Ha egy replikakészlet van, akkor nincs szükség szinkronizálásra: ez egy „egyetlen mester”; Van egy OpLog-unk, amelybe minden változás beleesik - ebben az esetben már minden szekvenciálisan el van rendezve magában az „Oplogban”. De ha két különböző szilánkunk van, akkor itt fontos az időszinkronizálás. Itt a vektoros óra segített többet! De nálunk nincsenek.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

A második megfelelő - ez a „Heartbeats”. Lehetőség van olyan jelek cseréjére, amelyek minden időegységben előfordulnak. De a szívverések túl lassúak, nem tudunk késleltetést biztosítani ügyfelünknek.

Az igazi idő természetesen csodálatos dolog. De, ismét, valószínűleg ez a jövő... Bár Atlasban már meg lehet csinálni, vannak már gyors „Amazon” időszinkronizálók. De nem lesz mindenki számára elérhető.

A pletyka az, amikor minden üzenet tartalmaz időt. Nagyjából ezt használjuk. A MongoDB számára minden csomópont közötti üzenet, illesztőprogram, adatcsomópont-útválasztó, abszolút minden egyfajta elem, egy adatbázis-komponens, amely egy futó órát tartalmaz. Hibrididő jelentéssel bírnak mindenhol, közvetítik. 64 bites? Ez lehetővé teszi, ez lehetséges.

Hogyan működik mindez együtt?

Itt egy replikakészletet nézek meg, hogy egy kicsit könnyebb legyen. Van elsődleges és másodlagos. A másodlagos replikációt végez, és nincs mindig teljesen szinkronizálva az elsődlegesvel.

Beszúrás történik a „Primery”-be egy bizonyos időértékkel. Ez a betét 11-gyel növeli a belső számot, ha ez a maximum. Vagy ellenőrzi az óra értékeit, és szinkronizálja az órával, ha az óraértékek nagyobbak. Ez lehetővé teszi az idő szerinti rendszerezést.

A felvétel elkészítése után egy fontos pillanat következik. Az óra a "MongoDB"-ben van, és csak akkor növekszik, ha az "Oplog"-ba ír. Ez az az esemény, amely megváltoztatja a rendszer állapotát. Abszolút minden klasszikus cikkben eseménynek azt tekintjük, amikor egy üzenet eltalál egy csomópontot: az üzenet megérkezett, ami azt jelenti, hogy a rendszer megváltoztatta az állapotát.

Ennek az az oka, hogy a kutatás során nem teljesen világos, hogyan értelmezik ezt az üzenetet. Pontosan tudjuk, hogy ha ez nem jelenik meg az „Oplogban”, akkor az semmilyen módon nem értelmezhető, a rendszer állapotának változása pedig csak egy bejegyzés az „Oplogban”. Ez mindent leegyszerűsít számunkra: a modell leegyszerűsíti, és lehetővé teszi, hogy egyetlen replikakészletbe rendezzük, és sok más hasznos dolog.

Az „Oplog”-ba már beírt érték kerül visszaadásra – tudjuk, hogy az „Oplog” már tartalmazza ezt az értéket, és az ideje 12. Most mondjuk az olvasás egy másik csomópontról (Másodlagos) kezdődik, és a ClusterTime után továbbítja az üzenet. Azt mondja: „Mindenre szükségem van, ami legalább 12 óra után vagy tizenkét óra alatt történt” (lásd a fenti képet).

Ezt hívják oksági konzisztensnek (CAT). Elméletileg létezik egy olyan koncepció, hogy ez az idő egy szelete, ami önmagában is konzisztens. Ebben az esetben azt mondhatjuk, hogy ez a rendszer állapota, amelyet a 12. időpontban figyeltünk meg.

Most itt még nincs semmi, mert ez a fajta szimulálja azt a helyzetet, amikor a másodlagosra van szükség az adatok replikálásához az elsődlegesből. Vár... És most megérkeztek az adatok – visszaadja ezeket az értékeket.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Nagyjából így működik az egész. Majdnem.

Mit jelent a "majdnem"? Tegyük fel, hogy van valaki, aki elolvasta és megértette, hogyan működik mindez. Rájöttem, hogy minden alkalommal, amikor a ClusterTime előfordul, frissíti a belső logikai órát, majd a következő bejegyzés eggyel nő. Ez a függvény 20 sort foglal. Tegyük fel, hogy ez a személy a legnagyobb 64 bites számot továbbítja, mínusz egy.

Miért "mínusz egy"? Mivel a belső óra behelyettesítésre kerül ebbe az értékbe (nyilván ez a lehető legnagyobb és nagyobb, mint az aktuális idő), akkor az „Oplog”-ban megjelenik egy bejegyzés, és az óra egy másik egységgel növekszik – és máris ott lesz. legyen egy maximális érték (egyszerűen minden egység van, nincs hová menni) , unsaint ints).

Nyilvánvaló, hogy ezek után a rendszer semmire sem lesz elérhető. Csak kirakható és takarítható - sok kézi munka. Teljes elérhetőség:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Sőt, ha ezt máshol megismétlik, akkor az egész klaszter egyszerűen leesik. Abszolút elfogadhatatlan helyzet, amit bárki nagyon gyorsan és egyszerűen meg tud szervezni! Ezért ezt a pillanatot tartottuk az egyik legfontosabbnak. Hogyan lehet megelőzni?

A mi módszerünk a clusterTime aláírása

Így kerül továbbításra az üzenetben (a kék szöveg előtt). De elkezdtünk aláírást generálni (kék szöveg):

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Az aláírást egy kulcs generálja, amely az adatbázisban, egy biztonságos kerületen belül van tárolva; magát generálja és frissíti (a felhasználók nem látnak róla semmit). A rendszer létrehoz egy hash-t, és minden üzenetet aláírnak a létrehozáskor és érvényesítenek, amikor megkapják.
Valószínűleg felvetődik az emberekben a kérdés: „Mennyire lassítja ez a dolgokat?” Mondtam, hogy gyorsan kell működnie, különösen ennek a funkciónak a hiányában.

Mit jelent ebben az esetben az oksági következetesség használata? Ez az afterClusterTime paraméter megjelenítésére szolgál. E nélkül úgyis egyszerűen átadja az értékeket. A pletyka a 3.6-os verziótól kezdve mindig működik.

Ha elhagyjuk a folyamatos aláírás-generálást, az olyan funkció hiányában is lelassítja a rendszert, amely nem felel meg megközelítéseinknek és követelményeinknek. Szóval mit csináltunk?

Csináld gyorsan!

Elég egyszerű dolog, de a trükk érdekes – megosztom, hátha valakit érdekel.
Van egy hashünk, amely az aláírt adatokat tárolja. Minden adat átmegy a gyorsítótáron. A gyorsítótár nem a konkrét időt írja alá, hanem a tartományt. Amikor valamilyen érték megérkezik, generálunk egy tartományt, maszkoljuk az utolsó 16 bitet, és aláírjuk ezt az értéket:

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Egy ilyen aláírás fogadásával (viszonylag) 65 ezerszeresére gyorsítjuk fel a rendszert. Remekül működik: amikor kísérleteket végeztünk, az idő 10 ezerszeresére csökkent, amikor szekvenciális frissítést kaptunk. Nyilvánvaló, hogy ha ellentmondásban vannak, ez nem működik. De a legtöbb gyakorlati esetben működik. A Range aláírás és az aláírás kombinációja megoldotta a biztonsági problémát.

Mit tanultunk?

Ebből tanultunk:

  • El kell olvasnunk anyagokat, történeteket, cikkeket, mert sok érdekességünk van. Amikor valamilyen funkción dolgozunk (főleg most, amikor tranzakciókat bonyolítottunk stb.), el kell olvasnunk és értenünk kell. Időbe telik, de valójában nagyon hasznos, mert világossá teszi, hol vagyunk. Úgy tűnt, nem találtunk ki semmi újat – csak a hozzávalókat vettük.

    Általánosságban elmondható, hogy van egy bizonyos gondolkodásbeli különbség, amikor egy tudományos konferencia van (például Sigmon) - mindenki az új ötletekre összpontosít. Mi az új algoritmusunkban? Nincs itt semmi különös újdonság. Az újdonság inkább abban rejlik, ahogyan a meglévő megközelítéseket ötvöztük. Ezért az első dolog az, hogy olvassa el a klasszikusokat, kezdve a Lamparttal.

  • A gyártásban teljesen mások a követelmények. Biztos vagyok benne, hogy sokan nem absztrakt légüres térben „gömb alakú” adatbázisokkal szembesülnek, hanem normális, valós dolgokkal, amelyeknek problémái vannak az elérhetőséggel, a késleltetéssel és a hibatűréssel.
  • Az utolsó dolog az, hogy különböző ötleteket kellett mérlegelnünk, és több, egymástól teljesen eltérő cikket kellett egy megközelítésben kombinálnunk. Az aláírás gondolata például általában egy olyan cikkből származik, amely a Paxos-protokollról szól, ami a nem bizánciak esetében az engedélyezési protokollon belül van, a bizánciak esetében pedig az engedélyezési protokollon kívül... Általánosságban elmondható, hogy pontosan ez az, amit mi végezte.

    Itt abszolút semmi új nincs! De amint összekevertük az egészet... Ez ugyanaz, mintha azt mondanám, hogy az Olivier saláta receptje hülyeség, mert a tojást, a majonézt és az uborkát már feltalálták... Ugyanarról a történetről van szó.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Ezzel befejezem. Köszönöm!

kérdések

A hallgatóság kérdése (a továbbiakban: B): – Köszönöm, Mikhail, a jelentést! Érdekes az idő témaköre. Ön a pletykálkodást használja. Azt mondták, mindenkinek megvan a maga ideje, mindenki ismeri a helyi időt. Ha jól értem, van driverünk - sok kliens lehet driverrel, lekérdezés-tervező is, szilánkok is... És mire megy ki a rendszer, ha hirtelen eltérés támad: valaki úgy dönt, hogy ez egy perccel előrébb, valaki egy perccel lemaradva? Hol fogunk végezni?

MT: - Valóban remek kérdés! Csak a szilánkokról akartam beszélni. Ha jól értem a kérdést, a következő helyzet áll előttünk: van 1. és 2. szilánk, ebből a két szilánkból történik az olvasás - eltérés van, nem lépnek kölcsönhatásba egymással, mert más az idő, amit tudnak, különösen az az idő, amikor léteznek az oplogokban.
Tegyük fel, hogy az 1. szilánk millió rekordot készített, a 2. szilánk semmit sem csinált, és a kérés két shardhoz érkezett. Az elsőnek pedig több mint egymillió az afterClusterTime-je. Ilyen helyzetben, ahogy kifejtettem, a 2. szilánk soha nem fog reagálni.

BAN BEN: – Azt szerettem volna tudni, hogyan szinkronizálnak, és hogyan választanak ki egy logikai időt?

MT: - Nagyon könnyen szinkronizálható. Szilánk, amikor az afterClusterTime megérkezik hozzá, és nem talál időt az „Oplogban”, nem kezdeményez jóváhagyást. Vagyis erre az értékre emeli a kezével az idejét. Ez azt jelenti, hogy nincs a kérésnek megfelelő esemény. Ezt az eseményt mesterségesen hozza létre, és ezáltal oksági konzisztenssé válik.

BAN BEN: – Mi van, ha ezek után újabb események érik, amelyek valahol elvesztek a hálózatban?

MT: – A Shard úgy van megtervezve, hogy ne jöjjenek többé, hiszen egyetlen mesterről van szó. Ha már jelentkezett, akkor nem jönnek, hanem később. Nem fordulhat elő, hogy valami elakad valahol, akkor nem ír, és akkor megérkeznek ezek az események - és megtörik az oksági konzisztencia. Ha nem ír, akkor mindegyik következzen (ő megvárja őket).

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

BAN BEN: – Több kérdésem is lenne a sorokkal kapcsolatban. Az ok-okozati konzisztencia azt feltételezi, hogy van egy meghatározott sor a végrehajtandó műveleteknek. Mi történik, ha valamelyik csomagunk eltűnik? Jön a 10., 11.... a 12. eltűnt, a többiek pedig arra várnak, hogy ez megvalósuljon. És hirtelen meghalt az autónk, nem tehetünk semmit. Van-e maximális hossza a várólista, amely felhalmozódik a végrehajtás előtt? Milyen végzetes kudarc következik be, ha bármelyik állapot elveszik? Sőt, ha leírjuk, hogy van valami korábbi állapot, akkor abból kell valahogy kiindulni? De nem lökték el!

MT: - Szintén remek kérdés! Mit csinálunk? A MongoDB rendelkezik a kvorum írás, kvórum olvasás fogalmával. Milyen esetekben veszhet el egy üzenet? Amikor egy írás nem határozatképes, vagy ha az olvasás nem határozatképes (valamiféle szemét is leragadhat).
Az ok-okozati konzisztenciát illetően nagy kísérleti tesztet végeztünk, melynek eredménye az volt, hogy abban az esetben, ha az írás és az olvasás nem határozatképes, az oksági konzisztencia megsértése következik be. Pontosan azt, amit mondasz!

Tanácsunk: az ok-okozati konzisztencia használatakor használjon legalább határozatképességi felolvasást. Ebben az esetben semmi sem vész el, még akkor sem, ha a kvórumrekord elveszik... Ez egy ortogonális helyzet: ha a felhasználó nem akarja, hogy adatok vesszenek el, akkor kvórumrekordot kell használnia. Az ok-okozati konzisztencia nem garantálja a tartósságot. A tartósságot a replikáció és a replikációhoz kapcsolódó gépezet garantálja.

BAN BEN: – Amikor létrehozunk egy példányt, amely shardingot hajt végre helyettünk (nem master, hanem slave), akkor a saját gépének Unix idejére vagy a „master” idejére támaszkodik; Először vagy rendszeresen szinkronizálódik?

MT: - Most pontosítok. Szilánk (azaz vízszintes partíció) – mindig van ott egy elsődleges. És egy szilánknak lehet „gazdája”, és lehetnek replikák. De a szilánk mindig támogatja a rögzítést, mert támogatnia kell valamilyen tartományt (a shardnak elsődleges van).

BAN BEN: – Tehát minden tisztán a „mesteren” múlik? Mindig kihasználják a mesteridőt?

MT: - Igen. Képletesen mondhatjuk: az óra ketyeg, amikor belépés történik a „mesterbe”, az „Oplogba”.

BAN BEN: – Van egy ügyfelünk, aki csatlakozik, és nem kell semmit tudnia az időről?

MT: - Egyáltalán nem kell tudnod semmit! Ha arról beszélünk, hogy ez hogyan működik az ügyfélen: amikor az ügyfél az oksági konzisztenciát akarja használni, meg kell nyitnia egy munkamenetet. Most már minden megvan: tranzakciók a munkamenetben, és jogok lekérése... A munkamenet a klienssel előforduló logikai események sorrendje.

Ha megnyitja ezt a munkamenetet, és azt mondja, hogy oksági konzisztenciát akar (ha a munkamenet alapértelmezés szerint támogatja az oksági konzisztenciát), minden automatikusan működik. A vezető megjegyzi ezt az időt, és növeli, ha új üzenetet kap. Emlékszik, hogy az előző milyen választ adott az adatokat visszaadó szervertől. A következő kérés tartalmazza az afterCluster("ennél nagyobb idő") tartalmat.

Az ügyfélnek egyáltalán nem kell tudnia semmit! Ez teljesen átláthatatlan számára. Ha az emberek használják ezeket a funkciókat, mit tehetnek? Először is nyugodtan olvashatja a másodlagos elemeket: írhat az Elsődlegesbe, és olvashat a földrajzilag replikált másodlagos elemekből, és biztos lehet benne, hogy működik. Ugyanakkor az Elsődlegesen rögzített munkamenetek akár másodlagosba is átvihetők, azaz nem egy, hanem több munkamenetet használhat.

BAN BEN: – A számítástudomány új rétege – a CRDT (Conflict-free Replicated Data Types) adattípusok – szorosan kapcsolódik az esetleges konzisztencia témájához. Gondolt-e arra, hogy ilyen típusú adatokat integráljon az adatbázisba, és mit tud mondani erről?

MT: - Jó kérdés! A CRDT értelmes írási ütközések esetén: a MongoDB-ben egyetlen mester.

BAN BEN: – Lenne egy kérdésem a devopstól. A való világban vannak ilyen jezsuita helyzetek, amikor bekövetkezik a bizánci kudarc, és a védett peremen belül gonosz emberek kezdenek beletúrni a protokollba, különleges módon kézműves csomagokat küldeni?

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

MT: - A gonosz emberek a kerületen belül olyanok, mint egy trójai faló! A kerületen belüli gonosz emberek sok rosszat tehetnek.

BAN BEN: – Egyértelmű, hogy durván szólva egy lyukat hagyva a szerveren, amelyen keresztül elefántállatkertet rakhatsz, és örökre összeomolhatod az egész klasztert... Időbe fog telni a kézi helyreállítás... Ez finoman szólva is rossz. Másrészt ez érdekes: a való életben, a gyakorlatban vannak olyan helyzetek, amikor természetesen hasonló belső támadások fordulnak elő?

MT: – Mivel a való életben ritkán találkozom biztonsági megsértésekkel, nem tudom megmondani, hogy megtörténnek-e. De ha a fejlesztési filozófiáról beszélünk, akkor így gondolkodunk: van egy kerületünk, amely biztosítja a biztonságot végző srácokat - ez egy vár, egy fal; és a kerületen belül azt csinálhat, amit akar. Nyilvánvaló, hogy vannak olyan felhasználók, akik csak megtekinthetik, és vannak olyanok, akik törölhetik a könyvtárat.

A jogoktól függően a felhasználók által okozott kár lehet egy egér vagy egy elefánt. Nyilvánvaló, hogy egy teljes jogú felhasználó bármit megtehet. A korlátozott jogokkal rendelkező felhasználó lényegesen kevesebb kárt okozhat. Különösen nem tudja megtörni a rendszert.

BAN BEN: – A védett peremen valaki megpróbált váratlan protokollokat létrehozni a szerver számára, hogy teljesen tönkretegye a szervert, és ha szerencséd van, akkor az egész klasztert... Bejön valaha ilyen „jó”?

MT: – Soha nem hallottam ilyen dolgokról. Az a tény, hogy ilyen módon összeomolhat egy szerver, nem titok. Fail bent, hogy a protokollból, hogy egy jogosult felhasználó, aki írhat ilyesmit az üzenetben... Sőt, lehetetlen, mert akkor is ellenőrizni fogják. Lehetőség van letiltani ezt a hitelesítést azoknak a felhasználóknak, akik nem akarják – akkor ez az ő problémájuk; ők, durván szólva, maguk rombolták le a falakat és oda lehet tolni egy elefántot, ami majd letapos... De úgy általában beöltözhetsz szerelőnek, gyere és húzd ki!

BAN BEN: – Köszönöm a jelentést. Szergej (Yandex). A Mongban van egy konstans, amely korlátozza a szavazati joggal rendelkező tagok számát a replikakészletben, és ez a konstans 7 (hét). Miért állandó ez? Ez miért nem valamiféle paraméter?

MT: – 40 csomópontot tartalmazó replikakészleteink vannak. Mindig van többség. Nem tudom melyik verzió...

BAN BEN: – A Replica Setben szavazati joggal nem rendelkező tagokat is futtathat, de szavazati joggal rendelkező tagok száma maximum 7. Hogyan éljük túl a leállást ebben az esetben, ha a Replica Set 3 adatközpontban van szétszórva? Egy adatközpont könnyen kikapcsolhat, egy másik gép pedig kieshet.

MT: – Ez már egy kicsit meghaladja a jelentés kereteit. Ez egy általános kérdés. Talán később mesélhetek róla.

HighLoad++, Mihail Tyulenev (MongoDB): Oksági konzisztencia: az elmélettől a gyakorlatig

Néhány hirdetés 🙂

Köszönjük, hogy velünk tartott. Tetszenek cikkeink? További érdekes tartalmakat szeretne látni? Támogass minket rendeléssel vagy ajánlj ismerőseidnek, felhő VPS fejlesztőknek 4.99 dollártól, a belépő szintű szerverek egyedülálló analógja, amelyet mi találtunk ki Önnek: A teljes igazság a VPS-ről (KVM) E5-2697 v3 (6 mag) 10 GB DDR4 480 GB SSD 1 Gbps 19 dollártól, vagy hogyan oszthat meg egy szervert? (RAID1 és RAID10, akár 24 maggal és akár 40 GB DDR4-gyel is elérhető).

A Dell R730xd kétszer olcsóbb az amszterdami Equinix Tier IV adatközpontban? Csak itt 2x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6 GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV 199 dollártól Hollandiában! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 dollártól! Olvasni valamiről Hogyan építsünk infrastrukturális vállalatot? osztályú Dell R730xd E5-2650 v4 szerverek használatával 9000 eurót ér egy fillérért?

Forrás: will.com

Hozzászólás