{"id":56365,"date":"2020-02-11T00:00:00","date_gmt":"2020-02-10T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike"},"modified":"2020-02-18T14:04:37","modified_gmt":"2020-02-18T11:04:37","slug":"highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","title":{"rendered":"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Nast\u0119pna konferencja HighLoad++ odb\u0119dzie si\u0119 6 i 7 kwietnia 2020 roku w Petersburgu. <br \/>\nSzczeg\u00f3\u0142y i bilety <noindex><a rel=\"nofollow\" href=\"http:\/\/bit.ly\/2sSxgBx\">pod tym linkiem<\/a><\/noindex>. HighLoad++ Siberia 2019. Sala \u201eKrasnojarsk\u201d. 25 czerwca, 12:00. Streszczenia i <noindex><a rel=\"nofollow\" href=\"https:\/\/www.highload.ru\/siberia\/2019\/abstracts\/5253\">prezentacja<\/a><\/noindex>.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/cded9c5434d670db7295aadf5da0a9f1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCzasami praktyczne wymagania koliduj\u0105 z teori\u0105, w kt\u00f3rej nie uwzgl\u0119dnione s\u0105 wa\u017cne aspekty dla produktu komercyjnego. W tym wyst\u0105pieniu przedstawiony zostanie proces wyboru i \u0142\u0105czenia r\u00f3\u017cnych podej\u015b\u0107 do tworzenia komponent\u00f3w Causal consistency na podstawie bada\u0144 akademickich zgodnie z wymaganiami produktu komercyjnego. S\u0142uchacze dowiedz\u0105 si\u0119 o istniej\u0105cych teoretycznych podej\u015bciach do zegar\u00f3w logicznych, \u015bledzenia zale\u017cno\u015bci, bezpiecze\u0144stwa system\u00f3w, synchronizacji zegara i dlaczego MongoDB zatrzyma\u0142o si\u0119 na takich, a nie innych rozwi\u0105zaniach.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><b>Micha\u0142 Ty\u0142eniew (dalej \u2013 MT):<\/b> \u2013 B\u0119d\u0119 m\u00f3wi\u0142 o Causal consistency \u2013 to funkcjonalno\u015b\u0107, nad kt\u00f3r\u0105 pracowali\u015bmy w MongoDB. Pracuj\u0119 w grupie system\u00f3w rozproszonych, stworzyli\u015bmy to oko\u0142o dwa lata temu.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/b8d0a5b64e715f53b033fa8c398e2eb4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW procesie musia\u0142em zapozna\u0107 si\u0119 z du\u017c\u0105 ilo\u015bci\u0105 bada\u0144 akademickich, poniewa\u017c ta funkcjonalno\u015b\u0107 jest do\u015b\u0107 dobrze zbadana. Okaza\u0142o si\u0119, \u017ce \u017caden z artyku\u0142\u00f3w nie wpisuje si\u0119 w to, co jest wymagane w produkcji baz danych, z uwagi na do\u015b\u0107 specyficzne wymagania, kt\u00f3re wyst\u0119puj\u0105 prawdopodobnie w ka\u017cdej aplikacji produkcyjnej.<\/p>\n<p>B\u0119d\u0119 opowiada\u0107 o tym, jak jako konsumenci bada\u0144 akademickich przygotowujemy co\u015b, co mo\u017cemy p\u00f3\u017aniej przedstawi\u0107 naszym u\u017cytkownikom jako gotowe danie, z kt\u00f3rego \u0142atwo i bezpiecznie korzysta\u0107.<\/p>\n<h3>Przyczynowa zgodno\u015b\u0107 (Causal consistency). Zdefiniujmy poj\u0119cia<\/h3>\n<p>\nNa pocz\u0105tek chcia\u0142bym w og\u00f3lnych zarysach powiedzie\u0107, czym jest Causal consistency. S\u0105 dwie postacie \u2013 Leonard i Penny (serial \u201eTeoria wielkiego podrywu\u201d):<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/ee0835b604ae5d5d6c0fa1bc369e6b18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZa\u0142\u00f3\u017cmy, \u017ce Penny jest w Europie, a Leonard chce zrobi\u0107 dla niej jak\u0105\u015b niespodziank\u0119, imprez\u0119. I nie wymy\u015bla nic lepszego, jak usun\u0105\u0107 j\u0105 z listy znajomych, wys\u0142a\u0107 wszystkim znajomym aktualizacj\u0119 na feed: \u201eSprawmy rado\u015b\u0107 Penny!\u201d (ona jest w Europie, podczas gdy \u015bpi, nie widzi tego wszystkiego i nie mo\u017ce tego zobaczy\u0107, poniewa\u017c jej tam nie ma). W ostatecznym momencie usuwa ten post, wymazuje z \u201eFida\u201d i przywraca dost\u0119p, \u017ceby niczego nie zauwa\u017cy\u0142a i \u017ceby nie by\u0142o skandalu.<br \/>\nTo wszystko jest w porz\u0105dku, ale za\u0142\u00f3\u017cmy, \u017ce system jest rozproszony i wydarzenia potoczy\u0142y si\u0119 nieco inaczej. Mo\u017ce na przyk\u0142ad zdarzy\u0107 si\u0119, \u017ce ograniczenie dost\u0119pu Penny nast\u0105pi\u0142o po tym, jak ten post si\u0119 pojawi\u0142, je\u015bli wydarzenia nie s\u0105 ze sob\u0105 powi\u0105zane przyczynowo. W rzeczywisto\u015bci to przyk\u0142ad sytuacji, w kt\u00f3rej wymagana jest sp\u00f3jno\u015b\u0107 przyczynowa, aby zrealizowa\u0107 funkcj\u0119 biznesow\u0105 (w tym przypadku).<\/p>\n<p>W rzeczywisto\u015bci to do\u015b\u0107 nietrywialne w\u0142a\u015bciwo\u015bci baz danych \u2013 bardzo niewiele z nich je wspiera. Przejd\u017amy do modeli.<\/p>\n<h3>Modele sp\u00f3jno\u015bci (Consistency Models)<\/h3>\n<p>\nCzym tak naprawd\u0119 jest model sp\u00f3jno\u015bci w bazach danych? To pewne gwarancje, jakie rozproszony system daje odno\u015bnie do tego, jakie dane i w jakiej kolejno\u015bci klient mo\u017ce otrzyma\u0107.<\/p>\n<p>W zasadzie wszystkie modele sp\u00f3jno\u015bci sprowadzaj\u0105 si\u0119 do tego, jak bardzo rozproszony system przypomina system, kt\u00f3ry dzia\u0142a, na przyk\u0142ad, na jednym w\u0119\u017ale na laptopie. I jak bardzo system dzia\u0142aj\u0105cy na tysi\u0105cach geograficznie rozproszonych w\u0119z\u0142\u00f3w przypomina laptopa, w kt\u00f3rym wszystkie te w\u0142a\u015bciwo\u015bci s\u0105 automatycznie spe\u0142nione.<\/p>\n<p>Dlatego modele sp\u00f3jno\u015bci stosuje si\u0119 tylko do system\u00f3w rozproszonych. Wszystkie systemy, kt\u00f3re wcze\u015bniej istnia\u0142y i dzia\u0142a\u0142y na jednym poziomie pionowej skalowalno\u015bci, takich problem\u00f3w nie do\u015bwiadcza\u0142y. By\u0142a tam jedna pami\u0119\u0107 podr\u0119czna, z kt\u00f3rej wszystko zawsze by\u0142o odczytywane.<\/p>\n<h3>Model Strong<\/h3>\n<p>\nW\u0142a\u015bciwie, pierwszym modelem jest Strong (lub jak cz\u0119sto nazywa si\u0119 go linearn\u0105 sp\u00f3jno\u015bci\u0105). To model sp\u00f3jno\u015bci, kt\u00f3ry zapewnia, \u017ce ka\u017cda zmiana, gdy tylko uzyska potwierdzenie, staje si\u0119 widoczna dla wszystkich u\u017cytkownik\u00f3w systemu.<\/p>\n<p>To tworzy globalny porz\u0105dek wszystkich zdarze\u0144 w bazie danych. To bardzo silna w\u0142a\u015bciwo\u015b\u0107 sp\u00f3jno\u015bci, a jego implementacja jest kosztowna. Niemniej jednak jest ona dobrze wspierana. Po prostu jest bardzo droga i wolna \u2013 rzadko si\u0119 z niej korzysta. Nazywa si\u0119 to liniow\u0105 sp\u00f3jno\u015bci\u0105.<\/p>\n<p>Jest jeszcze jedna, silniejsza w\u0142a\u015bciwo\u015b\u0107, kt\u00f3ra jest wspierana w \u201eSpannerze\u201d \u2013 nazywa si\u0119 sp\u00f3jno\u015bci\u0105 zewn\u0119trzn\u0105. Om\u00f3wimy j\u0105 p\u00f3\u017aniej.<\/p>\n<h3>Przyczynowa<\/h3>\n<p>\nNast\u0119puj\u0105ce to Causal, o kt\u00f3rym w\u0142a\u015bnie m\u00f3wi\u0142em. Pomi\u0119dzy Strong a Causal istnieje jeszcze kilka podpoziom\u00f3w, o kt\u00f3rych nie b\u0119d\u0119 wspomina\u0107, ale wszystkie sprowadzaj\u0105 si\u0119 do Causal. To wa\u017cny model, poniewa\u017c jest najsilniejszy ze wszystkich modeli, zapewniaj\u0105c najsilniejsz\u0105 sp\u00f3jno\u015b\u0107 w obecno\u015bci sieci lub partitioning\u00f3w.<\/p>\n<p>Causals to sytuacja, w kt\u00f3rej zdarzenia s\u0105 powi\u0105zane relacj\u0105 przyczynowo-skutkow\u0105. Cz\u0119sto postrzega si\u0119 je jako Read your on rights z perspektywy klienta. Je\u015bli klient zauwa\u017cy\u0142 jakie\u015b warto\u015bci, nie mo\u017ce zobaczy\u0107 warto\u015bci, kt\u00f3re by\u0142y w przesz\u0142o\u015bci. Zaczyna widzie\u0107 odczyty prefiksowe. To wszystko sprowadza si\u0119 do jednego i tego samego.<br \/>\nCausals jako model sp\u00f3jno\u015bci to cz\u0119\u015bciowe uporz\u0105dkowanie zdarze\u0144 na serwerze, w kt\u00f3rym zdarzenia ze wszystkich klient\u00f3w s\u0105 obserwowane w tej samej kolejno\u015bci. W tym przypadku \u2013 Leonard i Penny.<\/p>\n<h3>Eventual<\/h3>\n<p>\nTrzeci model to Eventual Consistency. To model, kt\u00f3ry wspiera absolutnie wszystkie systemy rozproszone, minimalny model, kt\u00f3ry w og\u00f3le ma sens. Oznacza to, \u017ce kiedy zachodz\u0105 pewne zmiany w danych, w pewnym momencie staj\u0105 si\u0119 one sp\u00f3jne.<\/p>\n<p>W tym momencie nic nie m\u00f3wi, w przeciwnym razie przekszta\u0142ci\u0142by si\u0119 w External Consistency \u2013 to by\u0142aby zupe\u0142nie inna historia. Niemniej jednak to bardzo popularny model, najcz\u0119\u015bciej spotykany. Domy\u015blnie wszyscy u\u017cytkownicy system\u00f3w rozproszonych korzystaj\u0105 w\u0142a\u015bnie z Eventual Consistency.<\/p>\n<p>Chc\u0119 poda\u0107 kilka por\u00f3wnawczych przyk\u0142ad\u00f3w:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/c23e59b30d96de6ec456aaa76c67ad61.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCo oznaczaj\u0105 te strza\u0142ki?<\/p>\n<ul>\n<li><b>Opoznienie.<\/b> Przy zwi\u0119kszeniu mocy sp\u00f3jno\u015bci staje si\u0119 ono wi\u0119ksze z oczywistych powod\u00f3w: nale\u017cy wykona\u0107 wi\u0119cej zapis\u00f3w, uzyska\u0107 potwierdzenie od wszystkich host\u00f3w i w\u0119z\u0142\u00f3w, kt\u00f3re uczestnicz\u0105 w klastrze, \u017ce dane tam ju\u017c s\u0105. W zwi\u0105zku z tym w Eventual Consistency odpowied\u017a jest najszybsza, poniewa\u017c przewa\u017cnie mo\u017cna nawet w pami\u0119ci przykomitowa\u0107 i tego b\u0119dzie w zasadzie wystarczaj\u0105ce.<\/li>\n<li><b>Dost\u0119pno\u015b\u0107.<\/b> Je\u015bli to zrozumie\u0107 jako mo\u017cliwo\u015b\u0107 systemu do odpowiedzi przy istnieniu przerw w sieci, partitioningach, lub jakichkolwiek awariach \u2013 odporno\u015b\u0107 na awarie wzrasta przy zmniejszeniu modelu sp\u00f3jno\u015bci, poniewa\u017c wystarczy, \u017ce jeden host dzia\u0142a i przy tym dostarcza jakie\u015b dane. Eventual Consistency w og\u00f3le nic nie gwarantuje w zakresie danych \u2013 to mog\u0105 by\u0107 cokolwiek.<\/li>\n<li><b>Anomalie.<\/b> Jednocze\u015bnie oczywi\u015bcie zwi\u0119ksza si\u0119 liczba anomalii. W przypadku Silnej Sp\u00f3jno\u015bci nie powinny one w\u0142a\u015bciwie w og\u00f3le wyst\u0119powa\u0107, natomiast w przypadku Sp\u00f3jno\u015bci Ostatecznej mog\u0105 by\u0107 dowolne. Pojawia si\u0119 pytanie: dlaczego ludzie wybieraj\u0105 Sp\u00f3jno\u015b\u0107 Ostateczn\u0105, skoro zawiera ona anomalie? Odpowied\u017a jest taka, \u017ce modele Sp\u00f3jno\u015bci Ostatecznej s\u0105 odpowiednie, a anomalie wyst\u0119puj\u0105 na przyk\u0142ad przez kr\u00f3tki czas; istnieje mo\u017cliwo\u015b\u0107 korzystania z mastera do odczytu i do\u015b\u0107 sp\u00f3jnego czytania danych; cz\u0119sto mo\u017cna wykorzysta\u0107 silne modele sp\u00f3jno\u015bci. W praktyce to dzia\u0142a, a liczba anomalii jest cz\u0119sto ograniczona czasowo.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Teoria CAP<\/h3>\n<p>\nCo my\u015blisz, gdy widzisz s\u0142owa sp\u00f3jno\u015b\u0107, dost\u0119pno\u015b\u0107? Dok\u0142adnie \u2013 teoria CAP! Chc\u0119 teraz obali\u0107 mit... To nie ja \u2013 to Martin Kleppmann, kt\u00f3ry napisa\u0142 znakomity artyku\u0142, znakomit\u0105 ksi\u0105\u017ck\u0119.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/02a9b84585218c4e85afd65f7e88aa26.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTeoria CAP to zasada sformu\u0142owana w latach 2000, dotycz\u0105ca tego, \u017ce Sp\u00f3jno\u015b\u0107, Dost\u0119pno\u015b\u0107, Partycje: wybierz dowolne dwie, a nie mo\u017cna wybra\u0107 trzech. To by\u0142 pewien zasadniczy koncept. Zosta\u0142 on udowodniony jako twierdzenie kilka lat p\u00f3\u017aniej, dokonali tego Gilbert i Lynch. Nast\u0119pnie zacz\u0119to go stosowa\u0107 jako mantr\u0119 \u2013 systemy zacz\u0119\u0142y dzieli\u0107 si\u0119 na CA, CP, AP i tak dalej.<\/p>\n<p>To twierdzenie zosta\u0142o udowodnione naprawd\u0119 w takich przypadkach... Po pierwsze, dost\u0119pno\u015b\u0107 nie by\u0142a rozumiana jako warto\u015b\u0107 ci\u0105g\u0142a od zera do stu (0 \u2013 system \"martwy\", 100 \u2013 szybko odpowiada; przyzwyczaili\u015bmy si\u0119 tak na to patrze\u0107), ale jako w\u0142a\u015bciwo\u015b\u0107 algorytmu, kt\u00f3ra gwarantuje, \u017ce przy wszystkich jego wykonaniach zwraca dane.<\/p>\n<p>Nie ma tam ani s\u0142owa o czasie odpowiedzi! Jest algorytm, kt\u00f3ry zwraca dane po 100 latach \u2013 doskona\u0142y algorytm dost\u0119pny, kt\u00f3ry jest cz\u0119\u015bci\u0105 teorii CAP.<br \/>\nPo drugie: twierdzenie by\u0142o dowodzone dla zmian w warto\u015bciach tego samego klucza, a te zmiany s\u0105 lini\u0105 resizable. Oznacza to, \u017ce w rzeczywisto\u015bci prawie nie s\u0105 one wykorzystywane, poniewa\u017c istniej\u0105 inne modele Sp\u00f3jno\u015bci Ostatecznej, Sp\u00f3jno\u015bci Silnej (mo\u017ce by\u0107).<\/p>\n<p>O co w tym wszystkim chodzi? O to, \u017ce teoria CAP w takiej formie, w jakiej zosta\u0142a dowiedziona, praktycznie nie ma zastosowania, rzadko jest stosowana. W formie teoretycznej w jaki\u015b spos\u00f3b wszystko ogranicza. Powstaje pewna zasada, kt\u00f3ra jest intuicyjnie prawdziwa, ale w og\u00f3le nie zosta\u0142o to udowodnione.<\/p>\n<h3>Sp\u00f3jno\u015b\u0107 przyczynowa \u2013 najsilniejszy model<\/h3>\n<p>\nObecnie mo\u017cna uzyska\u0107 trzy rzeczy: sp\u00f3jno\u015b\u0107, dost\u0119pno\u015b\u0107 dzi\u0119ki partycjom. W szczeg\u00f3lno\u015bci sp\u00f3jno\u015b\u0107 przyczynowa to najsilniejszy model sp\u00f3jno\u015bci, kt\u00f3ry dzia\u0142a nawet w przypadku partycji (przerwy w sieci). Dlatego jest tak interesuj\u0105cy i dlatego zaj\u0119li\u015bmy si\u0119 tym tematem.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/c4320294320261858a6d22faa97b9e23.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPo pierwsze, upraszcza prac\u0119 programist\u00f3w aplikacji. W szczeg\u00f3lno\u015bci zapewnia du\u017c\u0105 pomoc ze strony serwera: gdy wszystkie zapisane dane z jednego klienta s\u0105 gwarantowane w takiej samej kolejno\u015bci na innym kliencie. Po drugie, wytrzymuje partycje.<\/p>\n<h3>Wewn\u0119trzna kuchnia MongoDB<\/h3>\n<p>\nPami\u0119taj\u0105c o lunchu, przechodzimy do kuchni. Opowiem o modelu systemu, a konkretnie \u2013 czym jest MongoDB dla tych, kt\u00f3rzy pierwszy raz s\u0142ysz\u0105 o tej bazie danych.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/a1784442ff1c44403b5347f4f43a1197.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/a1f9bcb4daebb43e4fc848a5f5f07c60.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMongoDB (dalej \u2013 \"MongoDB\") to rozproszony system, kt\u00f3ry wspiera poziome skalowanie, to znaczy sharding; a wewn\u0105trz ka\u017cdego shardu wspiera r\u00f3wnie\u017c redundancj\u0119 danych, czyli replikacj\u0119.<\/p>\n<p>Sharding w \"MongoDB\" (baza danych nierelacyjna) wykonuje automatyczn\u0105 balansowanie, to znaczy ka\u017cda kolekcja dokument\u00f3w (lub \"tabela\" w terminach danych relacyjnych) jest dzielona na fragmenty, a serwer automatycznie przenosi je mi\u0119dzy shardami.<\/p>\n<p>Router zapyta\u0144, kt\u00f3ry rozdziela zapytania, jest dla klienta pewnym klientem, przez kt\u00f3rego dzia\u0142a. Ju\u017c wie, gdzie i jakie dane si\u0119 znajduj\u0105, kieruj\u0105c wszystkie zapytania do w\u0142a\u015bciwego shardu.<\/p>\n<p>Kolejna wa\u017cna kwestia: MongoDB to pojedynczy master. Jest jeden Primary \u2013 mo\u017ce przyjmowa\u0107 zapisy wspieraj\u0105ce te klucze, kt\u00f3re ma. Nie mo\u017cna wykona\u0107 zapisu w trybie Multi-master.<\/p>\n<p>Wydali\u015bmy wersj\u0119 4.2 \u2013 pojawi\u0142y si\u0119 nowe interesuj\u0105ce funkcje. W szczeg\u00f3lno\u015bci wstawili\u015bmy Lucene \u2013 wyszukiwanie \u2013 dok\u0142adnie wykonalne Java bezpo\u015brednio w \"Mongo\", co umo\u017cliwi\u0142o wykonywanie wyszukiwa\u0144 przez Lucene, podobnie jak w \"Elastyku\".<\/p>\n<p>Stworzono nowy produkt \u2013 Charts, kt\u00f3ry r\u00f3wnie\u017c jest dost\u0119pny w \"Atlasie\" (w\u0142asny Cloud \"Mongo\"). Maj\u0105 darmowy poziom \u2013 mo\u017cna sobie z tym poeksperymentowa\u0107. Charts bardzo mi si\u0119 spodoba\u0142 \u2013 wizualizacja danych, bardzo intuicyjna.<\/p>\n<h3>Sk\u0142adniki sp\u00f3jno\u015bci przyczynowej<\/h3>\n<p>\nPoliczy\u0142em oko\u0142o 230 artyku\u0142\u00f3w opublikowanych na ten temat \u2013 od Lesliera Lamperta. Teraz z pami\u0119ci przeka\u017c\u0119 wam niekt\u00f3re cz\u0119\u015bci tych materia\u0142\u00f3w.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/e88b34b7a724e94837b944a4ddd21a04.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWszystko zacz\u0119\u0142o si\u0119 od artyku\u0142u Lesleya Lamperta, kt\u00f3ry zosta\u0142 napisany w latach 70. Jak wida\u0107, badania w tej dziedzinie wci\u0105\u017c trwaj\u0105. Teraz Causal consistency zyskuje na zainteresowaniu w zwi\u0105zku z rozwojem system\u00f3w rozproszonych.<\/p>\n<h3>Ograniczenia<\/h3>\n<p>\nJakie s\u0105 ograniczenia? To tak naprawd\u0119 jeden z najwa\u017cniejszych punkt\u00f3w, poniewa\u017c ograniczenia, kt\u00f3re nak\u0142adaj\u0105 systemy produkcyjne, znacznie r\u00f3\u017cni\u0105 si\u0119 od ogranicze\u0144, kt\u00f3re wyst\u0119puj\u0105 w artyku\u0142ach akademickich. Cz\u0119sto s\u0105 one dosy\u0107 sztuczne.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/9583ba9ff870e4ddc7aad4ba4c59ecc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Po pierwsze, \u201eMongoDB\u201d to system single master, jak ju\u017c wspomnia\u0142em (co bardzo upraszcza zagadnienie).<\/li>\n<li>Uwa\u017camy, \u017ce system powinien wspiera\u0107 oko\u0142o 10 tysi\u0119cy shard\u00f3w. Nie mo\u017cemy podejmowa\u0107 \u017cadnych decyzji architektonicznych, kt\u00f3re jawnie ogranicza\u0142yby t\u0119 warto\u015b\u0107.<\/li>\n<li>Mamy chmur\u0119, ale zak\u0142adamy, \u017ce u\u017cytkownik powinien mie\u0107 mo\u017cliwo\u015b\u0107 pobrania pliku binarnego, uruchomienia go na swoim laptopie i cieszenia si\u0119, \u017ce wszystko dzia\u0142a doskonale.<\/li>\n<li>Przypuszczamy to, co rzadko si\u0119 wykorzystuje w badaniach: zewn\u0119trzni klienci mog\u0105 robi\u0107, co chc\u0105. \u201eMongoDB\u201d jest open source. W zwi\u0105zku z tym klienci mog\u0105 by\u0107 na tyle sprytni lub z\u0142o\u015bliwi \u2013 mog\u0105 chcie\u0107 wszystko zepsu\u0107. Przypuszczamy, \u017ce mog\u0105 wyst\u0119powa\u0107 bizantyjskie failory.<\/li>\n<li>Dla zewn\u0119trznych klient\u00f3w, kt\u00f3rzy znajduj\u0105 si\u0119 poza perymetrem \u2013 wa\u017cne ograniczenie: je\u015bli ta funkcjonalno\u015b\u0107 jest wy\u0142\u0105czona, nie powinno by\u0107 zauwa\u017calnych degradacji wydajno\u015bci.<\/li>\n<li>Jeszcze jeden aspekt \u2013 og\u00f3lnie antyakademicki: kompatybilno\u015b\u0107 starszych i przysz\u0142ych wersji. Stare sterowniki musz\u0105 wspiera\u0107 nowe aktualizacje, a baza danych musi wspiera\u0107 stare sterowniki.<\/li>\n<\/ul>\n<p>\nOg\u00f3lnie rzecz bior\u0105c, wszystko to nak\u0142ada ograniczenia.<\/p>\n<h3>Komponenty Causal consistency<\/h3>\n<p>\nTeraz opowiem o niekt\u00f3rych komponentach. Je\u015bli rozwa\u017cy\u0107 Causal consistency jako ca\u0142o\u015b\u0107, mo\u017cna wyr\u00f3\u017cni\u0107 poszczeg\u00f3lne bloki. Wybierali\u015bmy z prac, kt\u00f3re odnosz\u0105 si\u0119 do konkretnego bloku: \u015bledzenie zale\u017cno\u015bci, wyb\u00f3r zegar\u00f3w, jak te zegary mo\u017cna synchronizowa\u0107 oraz jak zapewniamy bezpiecze\u0144stwo \u2013 to og\u00f3lny plan tego, o czym b\u0119d\u0119 m\u00f3wi\u0107:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/10c2631d6e61a280139b448628db763e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Pe\u0142ne \u015bledzenie zale\u017cno\u015bci (Full Dependency Tracking)<\/h3>\n<p>\nPo co to potrzebne? Aby przy replikacji danych ka\u017cda rekord, ka\u017cda zmiana danych zawiera\u0142a informacje o zmianach, od kt\u00f3rych zale\u017cy. Najprostsza i najbardziej podstawowa zmiana polega na tym, \u017ce ka\u017cda wiadomo\u015b\u0107, zawieraj\u0105ca rekord, zawiera informacje o poprzednich wiadomo\u015bciach:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/fa5d0086c3c77e33631d8a2cd5c217fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW tym przyk\u0142adzie numery w klamrowych nawiasach to numery rekord\u00f3w. Czasami te rekordy z warto\u015bciami s\u0105 przekazywane w ca\u0142o\u015bci, czasami przekazywane s\u0105 jakie\u015b wersje. Istota polega na tym, \u017ce ka\u017cda zmiana zawiera informacje o poprzednich, co jest dla niej oczywiste.<\/p>\n<p>Dlaczego zdecydowali\u015bmy si\u0119 nie korzysta\u0107 z takiego podej\u015bcia (pe\u0142ne \u015bledzenie)? Oczywiste, poniewa\u017c to podej\u015bcie jest niepraktyczne: ka\u017cda zmiana w sieci spo\u0142eczno\u015bciowej zale\u017cy od wszystkich poprzednich zmian w tej sieci spo\u0142eczno\u015bciowej, przesy\u0142aj\u0105c, powiedzmy, \u201eFacebooka\u201d czy \u201eVKontakte\u201d w ka\u017cdym aktualizacji. Niemniej jednak istnieje wiele bada\u0144 dotycz\u0105cych Full Dependency Tracking \u2013 w przypadku niekt\u00f3rych sytuacji rzeczywi\u015bcie dzia\u0142a.<\/p>\n<h3>Jawne \u015bledzenie zale\u017cno\u015bci (Explicit Dependency Tracking)<\/h3>\n<p>\nNast\u0119pne jest bardziej ograniczone. Tutaj r\u00f3wnie\u017c rozpatrywana jest transmisja informacji, ale tylko tych, kt\u00f3re s\u0105 jawnie zale\u017cne. Co od czego zale\u017cy, zazwyczaj okre\u015bla ju\u017c aplikacja. Gdy dane s\u0105 replikowane, w odpowiedzi wydawane s\u0105 tylko odpowiedzi, gdy poprzednie zale\u017cno\u015bci zosta\u0142y spe\u0142nione, czyli pokazane. W tym tkwi istota dzia\u0142ania sp\u00f3jno\u015bci przyczynowej.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/7fe101b998c1a0c922788d8d36a5243f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWidzi, \u017ce rekord 5 zale\u017cy od rekord\u00f3w 1, 2, 3, 4 \u2013 w zwi\u0105zku z tym czeka, zanim klient uzyska dost\u0119p do zmian wprowadzonych decyzj\u0105 dost\u0119pu Penny, gdy wszystkie poprzednie zmiany zostan\u0105 ju\u017c wprowadzone do bazy danych.<\/p>\n<p>To r\u00f3wnie\u017c nam nie odpowiada, poniewa\u017c wci\u0105\u017c jest zbyt wiele informacji, co b\u0119dzie spowalnia\u0142o. Istnieje inne podej\u015bcie...<\/p>\n<h3>Zegary Lamporta (Lamport Clock)<\/h3>\n<p>\nS\u0105 bardzo stare. Zegar Lamporta oznacza, \u017ce te zale\u017cno\u015bci s\u0105 redukowane do funkcji skalarnej, kt\u00f3ra nosi nazw\u0119 Zegar Lamporta.<\/p>\n<p>Funkcja skalarna to pewna abstrakcyjna liczba. Cz\u0119sto nazywana jest czasem logicznym. Przy ka\u017cdym zdarzeniu ten licznik wzrasta. Licznik, kt\u00f3ry w tym momencie jest znany procesowi, wysy\u0142a ka\u017cd\u0105 wiadomo\u015b\u0107. Oczywiste jest, \u017ce procesy mog\u0105 by\u0107 niesynchronizowane, mog\u0105 mie\u0107 zupe\u0142nie r\u00f3\u017cny czas. Niemniej jednak w taki spos\u00f3b wymiany wiadomo\u015bci system w pewien spos\u00f3b r\u00f3wnowa\u017cy zegary. Co si\u0119 dzieje w takim przypadku?<\/p>\n<p>Rozbi\u0142em ten du\u017cy shard na dwa, \u017ceby by\u0142o jasne: Friends mog\u0105 \u017cy\u0107 w jednym w\u0119\u017ale, kt\u00f3ry zawiera kawa\u0142ek kolekcji, a Feed \u2013 w zupe\u0142nie innym w\u0119\u017ale, w kt\u00f3rym znajduje si\u0119 kawa\u0142ek tej kolekcji. Jak mog\u0105 si\u0119 nie znale\u017a\u0107 w kolejno\u015bci? Na pocz\u0105tku Feed powie: \u201eZreplikowane\u201d, a potem \u2013 Friends. Je\u015bli system nie zapewnia \u017cadnych gwarancji, \u017ce Feed nie b\u0119dzie wy\u015bwietlony, dop\u00f3ki zale\u017cno\u015bci Friends w kolekcji Friends r\u00f3wnie\u017c nie b\u0119d\u0105 dostarczone, to mamy dok\u0142adnie sytuacj\u0119, o kt\u00f3rej wspomnia\u0142em.<\/p>\n<p>Widzicie, jak zwi\u0119ksza si\u0119 logiczny czas licznika na Feedzie:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/bae152d1890b53804f2cb28122983df6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTak wi\u0119c g\u0142\u00f3wn\u0105 cech\u0105 zegara Lamporta i sp\u00f3jno\u015bci przyczynowej (wyja\u015bnionej za pomoc\u0105 zegara Lamporta) jest to, \u017ce je\u015bli mamy zdarzenia A i B, a zdarzenie B zale\u017cy od zdarzenia A*, to wynika z tego, \u017ce LogicalTime zdarzenia A jest mniejsze ni\u017c LogicalTime zdarzenia B.<\/p>\n<p><i>* Czasami m\u00f3wi si\u0119 r\u00f3wnie\u017c, \u017ce A zdarzy\u0142o si\u0119 przed B, czyli A wydarzy\u0142o si\u0119 wcze\u015bniej ni\u017c B \u2013 to rodzaj relacji, kt\u00f3ra cz\u0119\u015bciowo porz\u0105dkuje zbi\u00f3r wszystkich zdarze\u0144, kt\u00f3re w og\u00f3le mia\u0142y miejsce.<\/i><\/p>\n<p>W odwrotn\u0105 stron\u0119 to nie jest prawda. To naprawd\u0119 jeden z g\u0142\u00f3wnych minus\u00f3w zegara Lamporta \u2013 cz\u0119\u015bciowy porz\u0105dek. Istnieje poj\u0119cie zdarze\u0144 r\u00f3wnoczesnych, to znaczy zdarze\u0144, w kt\u00f3rych ani (A zdarzy\u0142o si\u0119 przed B), ani (B zdarzy\u0142o si\u0119 przed A). Przyk\u0142adem mo\u017ce by\u0107 r\u00f3wnoleg\u0142e dodawanie kogo\u015b do znajomych przez Leonarda (nawet nie przez Leonarda, a przez Sheldona, na przyk\u0142ad).<br \/>\nTo jest w\u0142a\u015bciwo\u015b\u0107, z kt\u00f3rej cz\u0119sto korzysta si\u0119 przy pracy z zegarami Lamporta: patrzy si\u0119 dok\u0142adnie na funkcj\u0119 i na tej podstawie wyci\u0105ga si\u0119 wnioski \u2013 mo\u017ce to by\u0107, \u017ce te zdarzenia s\u0105 zale\u017cne. Poniewa\u017c w jedn\u0105 stron\u0119 to jest prawda: je\u015bli LogicalTime A jest mniejsze ni\u017c LogicalTime B, to B nie mo\u017ce si\u0119 zdarzy\u0107 przed A; a je\u015bli jest wi\u0119ksze, to mo\u017ce.<\/p>\n<h3>Zegary wektorowe (Vector Clock)<\/h3>\n<p>\nLogiczn\u0105 kontynuacj\u0105 zegara Lamporta s\u0105 zegary wektorowe. R\u00f3\u017cni\u0105 si\u0119 tym, \u017ce ka\u017cdy w\u0119ze\u0142, kt\u00f3ry tutaj jest, zawiera swoje w\u0142asne, oddzielne zegary, kt\u00f3re s\u0105 przesy\u0142ane jako wektor.<br \/>\nW tym przypadku widzicie, \u017ce zerowy indeks wektora odpowiada za Feed, a pierwszy indeks wektora \u2013 za Friends (ka\u017cdy z tych w\u0119z\u0142\u00f3w). I w\u0142a\u015bnie teraz b\u0119d\u0105 one si\u0119 zwi\u0119ksza\u0107: zerowy indeks \u201eFida\u201d zwi\u0119ksza si\u0119 przy zapisie \u2013 1, 2, 3:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/d89292686ed8dd41aef06090f16db1c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCzym r\u00f3\u017cni\u0105 si\u0119 Zegary Wektorowe? Tym, \u017ce pozwalaj\u0105 zrozumie\u0107, kt\u00f3re zdarzenia wyst\u0119puj\u0105 jednocze\u015bnie i kiedy maj\u0105 miejsce w r\u00f3\u017cnych w\u0119z\u0142ach. To jest bardzo wa\u017cne dla systemu shardingu, jak \u201eMongoDB\u201d. Jednak tego nie wybrali\u015bmy, chocia\u017c to wspania\u0142a rzecz, dzia\u0142a doskonale i prawdopodobnie by nam odpowiada\u0142o\u2026<\/p>\n<p>Je\u015bli mamy 10 tysi\u0119cy shard\u00f3w, nie mo\u017cemy przesy\u0142a\u0107 10 tysi\u0119cy komponent\u00f3w, nawet je\u015bli je kompresujemy, wymy\u015blamy co\u015b innego \u2013 i tak u\u017cyteczno\u015b\u0107 b\u0119dzie wielokrotnie mniejsza ni\u017c obj\u0119to\u015b\u0107 ca\u0142ego tego wektora. Dlatego, z b\u00f3lem serca, zrezygnowali\u015bmy z tego podej\u015bcia i przeszli\u015bmy do innego.<\/p>\n<h3>Spanner TrueTime. Zegary atomowe<\/h3>\n<p>\nM\u00f3wi\u0142em, \u017ce b\u0119dzie mowa o \u201eSpannerze\u201d. To niesamowita rzecz, prosto z XXI wieku: zegary atomowe, synchronizacja GPS.<\/p>\n<p>Jaki jest pomys\u0142? \u201eSpanner\u201d to system stworzony przez Google, kt\u00f3ry niedawno sta\u0142 si\u0119 dost\u0119pny dla ludzi (dodali do niego SQL). Ka\u017cda transakcja ma tam pewien znacznik czasu. Poniewa\u017c czas jest zsynchronizowany*, ka\u017cdemu zdarzeniu mo\u017cna przypisa\u0107 okre\u015blony czas \u2013 zegary atomowe maj\u0105 czas oczekiwania, po kt\u00f3rym gwarantowane jest, \u017ce \u201enast\u0119puje\u201d ju\u017c inny czas.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/707b5998fbb500d201aafffccc666f0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW ten spos\u00f3b, po prostu zapisuj\u0105c do bazy danych i czekaj\u0105c pewien okres czasu, automatycznie gwarantuje si\u0119 serializowalno\u015b\u0107 zdarzenia. Maj\u0105 najsilniejszy model sp\u00f3jno\u015bci, jaki mo\u017cna w zasadzie sobie wyobrazi\u0107 \u2013 jest to sp\u00f3jno\u015b\u0107 zewn\u0119trzna.<\/p>\n<p>* To g\u0142\u00f3wny problem zegar\u00f3w Lamporta \u2013 nigdy nie s\u0105 zsynchronizowane w systemach rozproszonych. Mog\u0105 si\u0119 rozchodzi\u0107, nawet przy obecno\u015bci NTP wci\u0105\u017c nie dzia\u0142aj\u0105 zbyt dobrze. \u201eSpanner\u201d ma zegary atomowe i synchronizacj\u0119, wydaje si\u0119, \u017ce to mikrosekundy.<\/p>\n<p>Dlaczego nie wybrali\u015bmy? Nie zak\u0142adamy, \u017ce nasi u\u017cytkownicy maj\u0105 wbudowane zegary atomowe. Kiedy si\u0119 pojawi\u0105, wbudowane w ka\u017cdy laptop, b\u0119dzie jaka\u015b super fajna synchronizacja GPS \u2013 wtedy tak\u2026 A na razie najlepsze, co jest mo\u017cliwe, to \u201eAmazon\u201d, Stacje Bazowe \u2013 dla zapale\u0144c\u00f3w\u2026 Dlatego u\u017cyli\u015bmy innych zegar\u00f3w.<\/p>\n<h3>Zegary hybrydowe (Hybrid Clock)<\/h3>\n<p>\nTo jest w\u0142a\u015bciwie to, co tyka w \u201eMongoDB\u201d podczas zapewniania sp\u00f3jno\u015bci przyczynowej. W czym s\u0105 hybrydowe? Hybrydowe to skalarn\u0105 warto\u015b\u0107, ale sk\u0142ada si\u0119 z dw\u00f3ch komponent\u00f3w:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/dab03a87d9f6ee2e716f75baff1736bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Pierwszy to epoka unixowa (ile sekund min\u0119\u0142o od \u201epocz\u0105tku \u015bwiata komputerowego\u201d).<\/li>\n<li>Drugi to pewien inkrement, r\u00f3wnie\u017c 32-bitowy unsigned int.<\/li>\n<\/ul>\n<p>\nI to jest wszystko. Istnieje takie podej\u015bcie: cz\u0119\u015b\u0107 odpowiedzialna za czas, synchronizuje si\u0119 ca\u0142y czas z zegarami; za ka\u017cdym razem, gdy dochodzi do aktualizacji, ta cz\u0119\u015b\u0107 synchronizuje si\u0119 z zegarami i okazuje si\u0119, \u017ce czas jest zawsze mniej wi\u0119cej poprawny, a inkrement pozwala rozr\u00f3\u017cnia\u0107 zdarzenia, kt\u00f3re mia\u0142y miejsce w tym samym momencie.<\/p>\n<p>Dlaczego to jest wa\u017cne dla \u201eMongoDB\u201d? Poniewa\u017c pozwala na wykonywanie pewnych backup\u00f3w na okre\u015blony moment czasowy, to znaczy, \u017ce zdarzenie jest indeksowane czasem. To jest wa\u017cne, gdy potrzebne s\u0105 pewne zdarzenia; dla bazy danych zdarzenia to zmiany w bazie, kt\u00f3re mia\u0142y miejsce w okre\u015blonych przedzia\u0142ach czasu.<\/p>\n<p>Powiem ci jedn\u0105, najwa\u017cniejsz\u0105 przyczyn\u0119 (prosz\u0119, nikomu tego nie m\u00f3w)! Zrobili\u015bmy to w ten spos\u00f3b, poniewa\u017c tak wygl\u0105daj\u0105 uporz\u0105dkowane, indeksowane dane w MongoDB OpLog. OpLog to struktura danych, kt\u00f3ra zawiera wszystkie zmiany w bazie: najpierw trafiaj\u0105 do OpLogu, a potem s\u0105 stosowane do Storage w przypadku, gdy to jest replikowane lub shardowane.<\/p>\n<p>To by\u0142a g\u0142\u00f3wna przyczyna. Istniej\u0105 tak\u017ce praktyczne wymagania dotycz\u0105ce tworzenia bazy, co oznacza, \u017ce \u200b\u200bmusi by\u0107 prosto - ma\u0142o kodu, jak najmniej zepsutych rzeczy, kt\u00f3re trzeba przepisa\u0107 i przetestowa\u0107. To, \u017ce nasze oplogi okaza\u0142y si\u0119 by\u0107 indeksowane hybrydowymi zegarami, bardzo pomog\u0142o i pozwoli\u0142o na dokonanie w\u0142a\u015bciwego wyboru. To naprawd\u0119 si\u0119 op\u0142aci\u0142o i jako\u015b zacz\u0119\u0142o dzia\u0142a\u0107 magicznie w pierwszym prototypie. To by\u0142o naprawd\u0119 niesamowite!<\/p>\n<h3>Synchronizacja zegar\u00f3w<\/h3>\n<p>\nIstnieje kilka sposob\u00f3w synchronizacji opisanych w literaturze naukowej. M\u00f3wi\u0119 o synchronizacji, gdy mamy dwa r\u00f3\u017cne shard'y. Je\u015bli mamy jedn\u0105 replik\u0119, nie ma potrzeby synchronizacji: to jest \u00absingle-master\u00bb; mamy OpLog, do kt\u00f3rego trafiaj\u0105 wszystkie zmiany \u2013 w tym przypadku wszystko ju\u017c jest uporz\u0105dkowane sekwencyjnie w samym \u00abOpLogu\u00bb. Ale je\u015bli mamy dwa r\u00f3\u017cne shard'y, tutaj synchronizacja czasu jest wa\u017cna. Tutaj zegary wektorowe by\u0142yby bardziej pomocne! Ale ich nie mamy.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/7d3306747490ac044b7f8130defea0c9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDrug\u0105 opcj\u0105 s\u0105 \u00abHeartbeat'y\u00bb. Mo\u017cna wymienia\u0107 pewne sygna\u0142y, kt\u00f3re wyst\u0119puj\u0105 co jednostk\u0119 czasu. Ale \u00abHeartbeat'y\u00bb s\u0105 zbyt wolne, nie mo\u017cemy zapewni\u0107 klientowi niskiej latencji.<\/p>\n<p>Prawdziwy czas \u2013 to oczywi\u015bcie wspania\u0142a rzecz. Ale, zn\u00f3w, to prawdopodobnie przysz\u0142o\u015b\u0107\u2026 Chocia\u017c w \u00abAtlasie\u00bb mo\u017cna to ju\u017c zrealizowa\u0107, istniej\u0105 ju\u017c szybkie synchronizatory czasu od \u00abAmazonu\u00bb. Ale to nie b\u0119dzie dost\u0119pne dla wszystkich.<\/p>\n<p>Gossiping \u2013 to sytuacja, w kt\u00f3rej wszystkie wiadomo\u015bci zawieraj\u0105 czas. To mniej wi\u0119cej to, co stosujemy. Ka\u017cda wiadomo\u015b\u0107 mi\u0119dzy w\u0119z\u0142ami, sterownik, routeri w\u0119z\u0142\u00f3w danych, absolutnie wszystko w \u00abMongoDB\u00bb \u2013 to jakie\u015b elementy, komponenty baz danych, kt\u00f3re zawieraj\u0105 zegary, kt\u00f3re p\u0142yn\u0105. Wsz\u0119dzie maj\u0105 warto\u015b\u0107 hybrydowego czasu, kt\u00f3ra jest przekazywana. 64 bity? To si\u0119 sprawdza.<\/p>\n<h3>Jak to wszystko dzia\u0142a razem?<\/h3>\n<p>\nTutaj rozwa\u017cam jeden zestaw replik, aby by\u0142o nieco pro\u015bciej. Mamy Primary i Secondary. Secondary wykonuje replikacj\u0119 i nie zawsze jest w pe\u0142ni zsynchronizowany z Primary.<\/p>\n<p>Wstawiana jest (insert) do \u00abPrimary\u00bb z pewn\u0105 warto\u015bci\u0105 czasu. Ta operacja zwi\u0119ksza wewn\u0119trzny licznik o 11, je\u015bli to maksymalne. Lub sprawdza warto\u015bci zegar\u00f3w i synchronizuje si\u0119 wed\u0142ug zegar\u00f3w, je\u015bli warto\u015bci zegar\u00f3w s\u0105 wi\u0119ksze. To pozwala na uporz\u0105dkowanie wed\u0142ug czasu.<\/p>\n<p>Po zapisaniu nast\u0119puje wa\u017cny moment. Zegary w \u00abMongoDB\u00bb inkrementuj\u0105 si\u0119 tylko w przypadku zapisu do \u00abOpLogu\u00bb. To jest wydarzenie, kt\u00f3re zmienia stan systemu. W absolutnie wszystkich klasycznych artyku\u0142ach wydarzeniem uwa\u017ca si\u0119 dotarcie wiadomo\u015bci do w\u0119z\u0142a: wiadomo\u015b\u0107 dotar\u0142a \u2013 oznacza, \u017ce system zmieni\u0142 sw\u00f3j stan.<\/p>\n<p>To jest zwi\u0105zane z tym, \u017ce podczas badania nie do ko\u0144ca mo\u017cna zrozumie\u0107, jak to wiadomo\u015b\u0107 zostanie zinterpretowana. Wiemy na pewno, \u017ce je\u015bli nie jest to odzwierciedlone w \u201eOplogu\u201d, to nie zostanie to zinterpretowane, a zmian\u0105 stanu systemu jest tylko zapis w \u201eOplogu\u201d. To wszystko upraszcza: model jest uproszczony, pozwala na porz\u0105dkowanie w ramach jednego zestawu replik oraz wiele innych przydatnych rzeczy.<\/p>\n<p>Zwracana jest warto\u015b\u0107, kt\u00f3ra ju\u017c zosta\u0142a zapisana w \u201eOplogu\u201d \u2013 wiemy, \u017ce w \u201eOplogu\u201d ju\u017c le\u017cy ta warto\u015b\u0107, a jej czas to 12. Teraz, powiedzmy, rozpoczyna si\u0119 odczyt z innego w\u0119z\u0142a (Secondary) i przekazuje ju\u017c afterClusterTime w samej wiadomo\u015bci. M\u00f3wi: \u201ePotrzebuj\u0119 wszystkiego, co wydarzy\u0142o si\u0119 co najmniej po 12 lub w czasie dwunastej\u201d (patrz rys. powy\u017cej).<\/p>\n<p>To, co nazywamy Causal a consistent (CAT). Istnieje takie poj\u0119cie w teorii, \u017ce to pewne ci\u0119cie czasu, kt\u00f3re jest sp\u00f3jne samo w sobie. W tym przypadku mo\u017cna powiedzie\u0107, \u017ce to stan systemu, kt\u00f3ry zosta\u0142 zaobserwowany w momencie czasu 12.<\/p>\n<p>Na razie tutaj nic nie ma, poniewa\u017c to jakby symuluje sytuacj\u0119, w kt\u00f3rej Secondary musi replikowa\u0107 dane z Primary. Czeka\u2026 A oto dane przyby\u0142y \u2013 zwraca te warto\u015bci z powrotem.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/54d9de3e2696c1e5d19f4da206be090b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTak to mniej wi\u0119cej dzia\u0142a. Prawie.<\/p>\n<p>Co znaczy \u201eprawie\u201d? Za\u0142\u00f3\u017cmy, \u017ce jest kto\u015b, kto przeczyta\u0142 i zrozumia\u0142, jak to wszystko dzia\u0142a. Zrozumia\u0142, \u017ce za ka\u017cdym razem nast\u0119puje ClusterTime, aktualizuje wewn\u0119trzne zegary logiczne, a potem nast\u0119pny zapis zwi\u0119ksza si\u0119 o jeden. Ta funkcja zajmuje 20 linii. Za\u0142\u00f3\u017cmy, \u017ce ta osoba przesy\u0142a maksymaln\u0105 64-bitow\u0105 liczb\u0119, minus jeden.<\/p>\n<p>Dlaczego \u201eminus jeden\u201d? Poniewa\u017c wewn\u0119trzne zegary zostan\u0105 wstawione w t\u0119 warto\u015b\u0107 (oczywi\u015bcie, to najwi\u0119ksza mo\u017cliwa warto\u015b\u0107 i wi\u0119ksza ni\u017c bie\u017c\u0105cy czas), potem nast\u0105pi zapis w \u201eOplogu\u201d, a zegary zostan\u0105 zwi\u0119kszone o jeden \u2013 i b\u0119dzie ju\u017c maksymalna warto\u015b\u0107 (tam s\u0105 po prostu same jedynki, nie ma dok\u0105d i\u015b\u0107, unsaint int\u2019y).<\/p>\n<p>Oczywiste jest, \u017ce po tym system staje si\u0119 ca\u0142kowicie niedost\u0119pny dla czegokolwiek. Mo\u017cna go tylko wy\u0142adowa\u0107, oczy\u015bci\u0107 \u2013 mn\u00f3stwo r\u0119cznej pracy. Pe\u0142na dost\u0119pno\u015b\u0107:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/634b25fe0ef1e0af39181cd59c7b522f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJe\u015bli to jeszcze gdzie\u015b si\u0119 replikuje, to ca\u0142y klaster po prostu zawala. To absolutnie nieakceptowalna sytuacja, kt\u00f3r\u0105 ka\u017cdy mo\u017ce zaorganizowa\u0107 bardzo szybko i \u0142atwo! Dlatego traktowali\u015bmy ten punkt jako jeden z najwa\u017cniejszych. Jak to zapobiec?<\/p>\n<h3>Naszym celem jest podpisywanie clusterTime.<\/h3>\n<p>\nTak jest przekazywane w wiadomo\u015bci (do niebieskiego tekstu). Ale zacz\u0119li\u015bmy tak\u017ce generowa\u0107 podpis (niebieski tekst):<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/c16e985f9610e01a61293e0d6dde459b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPodpis jest generowany kluczem, kt\u00f3ry jest przechowywany wewn\u0105trz bazy danych, wewn\u0105trz chronionego obszaru; sam si\u0119 generuje, aktualizuje (u\u017cytkownicy tego nie widz\u0105). Generowany jest hash, a ka\u017cda wiadomo\u015b\u0107 przy tworzeniu jest podpisywana, a przy odbiorze \u2013 walidowana.<br \/>\nZ pewno\u015bci\u0105 pojawia si\u0119 pytanie u ludzi: \u201eJak bardzo to wszystko spowalnia?\u201d M\u00f3wi\u0142em przecie\u017c, \u017ce powinno dzia\u0142a\u0107 szybko, szczeg\u00f3lnie przy braku tej funkcji.<\/p>\n<p>Co to oznacza w praktyce korzystanie z Causal consistency? To pokazanie parametru afterClusterTime. A bez niego po prostu b\u0119dzie przekazywa\u0142 warto\u015bci w ka\u017cdych okoliczno\u015bciach. Gossiping, zaczynaj\u0105c od wersji 3.6, dzia\u0142a zawsze.<\/p>\n<p>Je\u015bli pozostawimy sta\u0142e generowanie podpis\u00f3w, spowolni to system nawet przy braku funkcji, co nie odpowiada naszym podej\u015bciom i wymaganiom. Co zrobili\u015bmy?<\/p>\n<h3>Zr\u00f3b to szybko!<\/h3>\n<p>\nZdecydowanie prosta sprawa, ale ciekawy trik \u2013 podziel\u0119 si\u0119, mo\u017ce kto\u015b to zainteresuje.<br \/>\nMamy hash, w kt\u00f3rym przechowywane s\u0105 podpisane dane. Wszystkie dane przechodz\u0105 przez cache. Cache podpisuje nie konkretny czas, a Range. Kiedy przychodzi jakie\u015b warto\u015b\u0107, generujemy Range, maskujemy ostatnie 16 bit\u00f3w i to warto\u015b\u0107 podpisujemy:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/f4810456f08ba1cc69730ac0079d4206.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOtrzymuj\u0105c taki podpis, przyspieszamy system (warunkowo) 65 tysi\u0119cy razy. Dzia\u0142a to \u015bwietnie: gdy przeprowadzono eksperymenty \u2013 czas na sekwencyjn\u0105 aktualizacj\u0119 skr\u00f3ci\u0142 si\u0119 rzeczywi\u015bcie 10 tysi\u0119cy razy. Oczywi\u015bcie, \u017ce gdy s\u0105 w nie\u0142adzie, to si\u0119 nie udaje. Ale w wi\u0119kszo\u015bci praktycznych przypadk\u00f3w to dzia\u0142a. Kombinacja podpisu Range razem z podpisem pozwoli\u0142a rozwi\u0105za\u0107 problem bezpiecze\u0144stwa.<\/p>\n<h3>Jasne jest, \u017ce ka\u017cdy serwis stara si\u0119 unika\u0107 przestoj\u00f3w. W naszym przypadku wierzymy, \u017ce ostatnie awarie pomog\u0142y uczyni\u0107 quay.io lepszym. Wyci\u0105gn\u0119li\u015bmy kilka g\u0142\u00f3wnych lekcji, kt\u00f3rymi chcemy si\u0119 podzieli\u0107:<\/h3>\n<p>\nLekcje, kt\u00f3re z tego wyci\u0105gn\u0119li\u015bmy:<\/p>\n<ul>\n<li>Trzeba czyta\u0107 materia\u0142y, historie, artyku\u0142y, bo mamy wiele interesuj\u0105cych rzeczy do om\u00f3wienia. Kiedy pracujemy nad jak\u0105\u015b funkcjonalno\u015bci\u0105 (szczeg\u00f3lnie teraz, gdy realizowali\u015bmy transakcje itp.), trzeba czyta\u0107 i zrozumie\u0107. To zajmuje czas, ale jest bardzo pomocne, bo staje si\u0119 jasne, gdzie si\u0119 znajdujemy. W rzeczywisto\u015bci nic nowego nie wymy\u015blili\u015bmy \u2013 po prostu wykorzystali\u015bmy sk\u0142adniki.\n<p>W rzeczywisto\u015bci istnieje pewna r\u00f3\u017cnica w my\u015bleniu, gdy ma miejsce konferencja akademicka (np. \u201eSigmon\u201d) \u2013 tam wszyscy skupiaj\u0105 si\u0119 na nowych ideach. Jaka jest nowo\u015b\u0107 naszego algorytmu? Tutaj nowo\u015bci nie ma. Nowo\u015b\u0107 polega raczej na tym, jak po\u0142\u0105czyli\u015bmy istniej\u0105ce podej\u015bcia. Dlatego najpierw trzeba czyta\u0107 klasyk\u00f3w, zaczynaj\u0105c od Lamporta.<\/li>\n<li>W produkcji zupe\u0142nie inne s\u0105 wymagania. Jestem pewien, \u017ce wielu z was stwierdza, \u017ce nie ma do czynienia z \u201esferycznymi\u201d bazami danych w abstrakcyjnej pr\u00f3\u017cni, a z normalnymi, rzeczywistymi rzeczami, kt\u00f3re maj\u0105 problemy z dost\u0119pno\u015bci\u0105, op\u00f3\u017anieniami i odporno\u015bci\u0105 na awarie.<\/li>\n<li>Ostatnie to to, \u017ce musieli\u015bmy rozwa\u017cy\u0107 r\u00f3\u017cne pomys\u0142y i po\u0142\u0105czy\u0107 kilka ca\u0142kowicie r\u00f3\u017cnych artyku\u0142\u00f3w w jeden podej\u015bcie. Pomys\u0142 dotycz\u0105cy podpisywania, na przyk\u0142ad, pochodzi\u0142 z artyku\u0142u, kt\u00f3ry omawia\u0142 protok\u00f3\u0142 Paxos, kt\u00f3ry dotyczy\u0142 niewizja\u0144skich awarii w ramach protoko\u0142u autoryzacji, a w przypadku wizja\u0144skich \u2013 poza protoko\u0142em autoryzacji\u2026 Generalnie, to dok\u0142adnie to, co w ko\u0144cu zrobili\u015bmy.\n<p>Nie ma tu absolutnie nic nowego! Ale gdy tylko wszystko to po\u0142\u0105czyli\u015bmy\u2026 To tak, jakby powiedzie\u0107, \u017ce przepis na sa\u0142atk\u0119 Olivier jest niczym, bo jajka, majonez i og\u00f3rki ju\u017c wymy\u015blono\u2026 To w zasadzie ta sama historia.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/2f9e5cb77079f9a0f7bdf76430c3386e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNa tym zako\u0144cz\u0119. Dzi\u0119kuj\u0119!<\/p>\n<h3>Pytania<\/h3>\n<p>\n<b>Pytanie z sali (dalej \u2013 P):<\/b> \u2013 Dzi\u0119kuj\u0119, Michale, za prezentacj\u0119! Temat czasu jest interesuj\u0105cy. U\u017cywasz Gossiping. Powiedzia\u0142e\u015b, \u017ce ka\u017cdy ma sw\u00f3j czas, ka\u017cdy zna sw\u00f3j lokalny czas. Zrozumia\u0142em, \u017ce mamy kierowc\u0119 \u2013 klient\u00f3w z kierowcami mo\u017ce by\u0107 wielu, tak\u017ce planist\u00f3w zapyta\u0144, shard\u00f3w te\u017c wiele\u2026 A do czego doprowadzi system, je\u015bli nagle wyst\u0105pi r\u00f3\u017cnica: kto\u015b uzna, \u017ce jest minut\u0119 do przodu, kto\u015b inny \u2013 minut\u0119 w ty\u0142? Gdzie si\u0119 znajdziemy?<\/p>\n<p><b>MT:<\/b> \u2013 To bardzo dobre pytanie! W\u0142a\u015bnie chcia\u0142em powiedzie\u0107 o shardach. Je\u015bli dobrze rozumiem to pytanie, mamy sytuacj\u0119: jest shard 1 i shard 2, a odczyty odbywaj\u0105 si\u0119 z tych dw\u00f3ch shard\u00f3w \u2013 maj\u0105 one rozbie\u017cno\u015b\u0107, nie wsp\u00f3\u0142dzia\u0142aj\u0105 ze sob\u0105, poniewa\u017c czas, kt\u00f3ry znaj\u0105 \u2013 jest r\u00f3\u017cny, szczeg\u00f3lnie czas, kt\u00f3ry maj\u0105 w oplogach.<br \/>\nZa\u0142\u00f3\u017cmy, \u017ce shard 1 zrobi\u0142 milion zapis\u00f3w, a shard 2 \u2013 w og\u00f3le nic, podczas gdy zapytanie przysz\u0142o do obu shard\u00f3w. I shard pierwszy ma afterClusterTime wi\u0119kszy ni\u017c milion. W takiej sytuacji, jak wyja\u015bni\u0142em, shard 2 w og\u00f3le nigdy nie odpowie.<\/p>\n<p><b>P:<\/b> \u2013 Chcia\u0142em zapyta\u0107, jak one si\u0119 synchronizuj\u0105 i wybieraj\u0105 jeden logiczny czas?<\/p>\n<p><b>MT:<\/b> \u2013 Synchronizuj\u0105 si\u0119 bardzo prosto. Shard, kiedy otrzymuje afterClusterTime i nie znajduje czasu w 'Oplogu' \u2013 inicjuje no approved. To znaczy, \u017ce r\u0119cznie podnosi sw\u00f3j czas do tej warto\u015bci. Oznacza to, \u017ce nie ma zdarze\u0144 odpowiadaj\u0105cych temu zapytaniu. Tworzy to zdarzenie sztucznie i w ten spos\u00f3b staje si\u0119 Causal Consistent.<\/p>\n<p><b>P:<\/b> \u2013 A je\u015bli po tym przyjd\u0105 jakie\u015b zdarzenia, kt\u00f3re gdzie\u015b w sieci znikn\u0119\u0142y?<\/p>\n<p><b>MT:<\/b> \u2013 Shard jest zaprojektowany tak, \u017ce one ju\u017c nie przyjd\u0105, poniewa\u017c to jest single master. Je\u015bli ju\u017c zapisa\u0142, to one ju\u017c nie wr\u00f3c\u0105, a b\u0119d\u0105 p\u00f3\u017aniej. Nie mo\u017ce si\u0119 zdarzy\u0107, \u017ce gdzie\u015b co\u015b utkn\u0119\u0142o, potem on zrobi no write, a potem te zdarzenia przychodz\u0105 \u2013 i Causal consistency zostaje naruszona. Kiedy on robi no write, wszystko musi przyj\u015b\u0107 dalej (poczeka na nie).<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/dbbc7c5c653f0c9fa449cceb88ed62ef.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>P:<\/b> \u2013 Mam kilka pyta\u0144 dotycz\u0105cych kolejek. Causal consistency zak\u0142ada, \u017ce istnieje pewna kolejno\u015b\u0107 dzia\u0142a\u0144 do wykonania. Co si\u0119 stanie, je\u015bli jeden pakiet zaginie? Oto poszed\u0142 10-ty, 11\u2026 12-ty znikn\u0105\u0142, a wszystkie pozosta\u0142e czekaj\u0105, a\u017c zostanie wykonany. A nagle nasza maszyna umar\u0142a, nie mo\u017cemy nic zrobi\u0107. Czy istnieje maksymalna d\u0142ugo\u015b\u0107 kolejki, kt\u00f3ra si\u0119 gromadzi, zanim zostanie wykonana? Jaki b\u0142\u0105d krytyczny wyst\u0119puje przy utracie jakiego\u015b jednego stanu? Zw\u0142aszcza je\u015bli zapisujemy, \u017ce istnieje jakie\u015b wcze\u015bniejsze zdarzenie, to od niego powinni\u015bmy si\u0119 jako\u015b odnie\u015b\u0107? A od niego si\u0119 nie odnie\u015bli\u015bmy!<\/p>\n<p><b>MT:<\/b> \u2013 R\u00f3wnie\u017c wspania\u0142e pytanie! Co robimy? W MongoDB istnieje poj\u0119cie quorum writes, quorum reads. W jakich przypadkach wiadomo\u015b\u0107 mo\u017ce znikn\u0105\u0107? Gdy zapis jest niekworumowy lub gdy odczyt jest niekworumowy (mo\u017ce przyj\u015b\u0107 jaki\u015b \u015bmie\u0107).<br \/>\nW odniesieniu do sp\u00f3jno\u015bci przypadkowej przeprowadzili\u015bmy du\u017c\u0105 eksperymentaln\u0105 weryfikacj\u0119, kt\u00f3rej wynikiem jest to, \u017ce w przypadku, gdy zapisy i odczyty s\u0105 niekworumowe, mog\u0105 wyst\u0119powa\u0107 naruszenia sp\u00f3jno\u015bci przypadkowej. Dok\u0142adnie to, co m\u00f3wisz!<\/p>\n<p>Nasza rada: u\u017cywaj chocia\u017c kworumowego odczytu przy u\u017cyciu sp\u00f3jno\u015bci przypadkowej. W tym przypadku nic nie zaginie, nawet je\u015bli kworumowa zapis zniknie\u2026 To jest ortogonalna sytuacja: je\u015bli u\u017cytkownik nie chce, aby dane znikn\u0119\u0142y, musi korzysta\u0107 z kworumowej zapisu. Sp\u00f3jno\u015b\u0107 przypadkowa nie daje gwarancji trwa\u0142o\u015bci. Gwarancj\u0119 trwa\u0142o\u015bci daje replikacja i powi\u0105zania zwi\u0105zane z replikacj\u0105.<\/p>\n<p><b>P:<\/b> \u2013 Kiedy tworzymy instancj\u0119, kt\u00f3ra wykonuje sharding (nie master, a slave odpowiednio), opiera si\u0119 ona na czasach unixowych w\u0142asnej maszyny lub na czasie \u201emastera\u201d; synchonizuje si\u0119 po raz pierwszy lub regularnie?<\/p>\n<p><b>MT:<\/b> \u2013 Teraz wyja\u015bni\u0119. Shard (tj. pozioma partycja) zawsze ma Primary. W shardzie mo\u017ce by\u0107 \u201emaster\u201d i mog\u0105 by\u0107 repliki. Ale shard zawsze wspiera zapis, poniewa\u017c musi wspiera\u0107 pewn\u0105 domen\u0119 (w shardzie znajduje si\u0119 Primary).<\/p>\n<p><b>P:<\/b> \u2013 Czyli wszystko zale\u017cy wy\u0142\u0105cznie od \u201emastera\u201d? Zawsze u\u017cywane jest \u201emaster\u201d-czas?<\/p>\n<p><b>MT:<\/b> \u2013 Tak. Mo\u017cna metaforycznie powiedzie\u0107: zegary tykaj\u0105, gdy zachodzi zapis w \u201emasterze\u201d, w \u201eOpLog\u201d.<\/p>\n<p><b>P:<\/b> \u2013 Mamy klienta, kt\u00f3ry si\u0119 \u0142\u0105czy i nie musi nic wiedzie\u0107 o czasie?<\/p>\n<p><b>MT:<\/b> \u2013 W og\u00f3le nic nie musi wiedzie\u0107! Je\u015bli m\u00f3wimy o tym, jak to dzia\u0142a po stronie klienta: klient, gdy chce korzysta\u0107 z sp\u00f3jno\u015bci przypadkowej, musi otworzy\u0107 sesj\u0119. Teraz wszystko tam jest: i transakcje w sesji, i odbieranie praw\u2026 Sesja to uporz\u0105dkowanie logicznych zdarze\u0144, kt\u00f3re zachodz\u0105 z klientem.<\/p>\n<p>Je\u015bli otwiera t\u0119 sesj\u0119 i m\u00f3wi, \u017ce chce sp\u00f3jno\u015bci przypadkowej (je\u015bli domy\u015blnie sesja wspiera sp\u00f3jno\u015b\u0107 przypadkow\u0105), wszystko automatycznie dzia\u0142a. Sterownik zapami\u0119tuje ten czas i zwi\u0119ksza go, gdy otrzymuje nowe wiadomo\u015bci. Zapami\u0119tuje, jaka odpowied\u017a wr\u00f3ci\u0142a z serwera, kt\u00f3ry zwr\u00f3ci\u0142 dane. Nast\u0119pne zapytanie b\u0119dzie zawiera\u0142o afterCluster (czas wi\u0119kszy ni\u017c ten).<\/p>\n<p>Klient nie musi zna\u0107 absolutnie nic! Jest to ca\u0142kowicie nieprzezroczyste dla niego. Je\u015bli ludzie korzystaj\u0105 z tych funkcji, co to umo\u017cliwia? Po pierwsze, mo\u017cna bezpiecznie odczytywa\u0107 dane z sekundarnych baz danych: mo\u017cna zapisywa\u0107 w Primary, a czyta\u0107 z geograficznie replikowanych sekundarnych i by\u0107 pewnym, \u017ce to dzia\u0142a. Przy tym sesje zapisane w Primary mo\u017cna przekaza\u0107 nawet na Secondary, tzn. mo\u017cna u\u017cywa\u0107 nie jednej sesji, a kilku.<\/p>\n<p><b>P:<\/b> \u2013 Z tematem sp\u00f3jno\u015bci ostatecznej mocno zwi\u0105zany jest nowy obszar w informatyce \u2013 typy danych CRDT (Conflict-free Replicated Data Types). Czy rozwa\u017cali\u015bcie integracj\u0119 tych typ\u00f3w danych w baz\u0119 i co o tym s\u0105dzicie?<\/p>\n<p><b>MT:<\/b> \u2013 Dobre pytanie! CRDT ma sens przy konfliktach podczas zapisu: w MongoDB \u2013 pojedynczy master.<\/p>\n<p><b>P:<\/b> \u2013 Mam pytanie od devops\u00f3w. W dzisiejszym \u015bwiecie wyst\u0119puj\u0105 takie iezuiterskie sytuacje, kiedy zdarza si\u0119 bizanty\u0144ski b\u0142\u0105d, a \u017ali ludzie w obr\u0119bie chronionego obszaru zaczynaj\u0105 grzeba\u0107 w protokole, wysy\u0142aj\u0105c specjalnie skonstruowane pakiety?<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/99a521d04b416e6978aa68ce7c4a4c46.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>MT:<\/b> \u2013 \u0179li ludzie w obr\u0119bie obszaru \u2013 to jak ko\u0144 troja\u0144ski! \u0179li ludzie w obr\u0119bie obszaru mog\u0105 zrobi\u0107 wiele z\u0142ych rzeczy.<\/p>\n<p><b>P:<\/b> \u2013 Oczywi\u015bcie, \u017ce zostawianie w serwerze, powiedzmy, dziury, przez kt\u00f3r\u0105 mo\u017cna wsun\u0105\u0107 zoo s\u0142oni i obali\u0107 ca\u0142y klaster na zawsze\u2026 To zajmie czas, aby r\u0119cznie to naprawi\u0107\u2026 To, delikatnie m\u00f3wi\u0105c, niew\u0142a\u015bciwe. Z drugiej strony, interesuj\u0105ce jest to: w rzeczywistym \u017cyciu, w praktyce pojawiaj\u0105 si\u0119 takie sytuacje, kiedy takie wewn\u0119trzne ataki rzeczywi\u015bcie wyst\u0119puj\u0105?<\/p>\n<p><b>MT:<\/b> \u2013 Poniewa\u017c rzadko spotykam si\u0119 z naruszeniami bezpiecze\u0144stwa w prawdziwym \u017cyciu, nie mog\u0119 powiedzie\u0107 \u2013 mo\u017ce one si\u0119 zdarzaj\u0105. Ale je\u015bli chodzi o filozofi\u0119 dewelopersk\u0105, to my uwa\u017camy tak: mamy obszar, kt\u00f3ry zapewnia ludziom zajmuj\u0105cym si\u0119 bezpiecze\u0144stwem \u2013 to zamek, mur; a wewn\u0105trz obszaru mo\u017cna robi\u0107 wszystko, co si\u0119 chce. Oczywi\u015bcie, \u017ce s\u0105 u\u017cytkownicy, kt\u00f3rzy mog\u0105 tylko ogl\u0105da\u0107, a s\u0105 te\u017c tacy, kt\u00f3rzy mog\u0105 usun\u0105\u0107 katalog.<\/p>\n<p>W zale\u017cno\u015bci od uprawnie\u0144, szkody, kt\u00f3re u\u017cytkownicy mog\u0105 wyrz\u0105dzi\u0107, mog\u0105 by\u0107 mysz\u0105 lub mog\u0105 by\u0107 tak\u017ce s\u0142oniem. Oczywi\u015bcie, \u017ce u\u017cytkownik z pe\u0142nymi prawami mo\u017ce zrobi\u0107 absolutnie wszystko. U\u017cytkownik z ograniczonymi prawami mo\u017ce wyrz\u0105dzi\u0107 znacznie mniej szk\u00f3d. W szczeg\u00f3lno\u015bci nie mo\u017ce zniszczy\u0107 systemu.<\/p>\n<p><b>P:<\/b> \u2013 W zabezpieczonym obszarze kto\u015b mo\u017ce zacz\u0105\u0107 tworzy\u0107 nieoczekiwane protoko\u0142y dla serwera, by przyprawi\u0107 serwer o b\u00f3l g\u0142owy, a je\u015bli b\u0119dzie szcz\u0119\u015bcie, to tak\u017ce ca\u0142y klaster... Czy mo\u017ce by\u0107 a\u017c tak \"dobrze\"?<\/p>\n<p><b>MT:<\/b> \u2013 Nigdy nie s\u0142ysza\u0142em o takich rzeczach. To, \u017ce w ten spos\u00f3b mo\u017cna zablokowa\u0107 serwer, nie jest tajemnic\u0105. Zablokowa\u0107 wewn\u0105trz, b\u0119d\u0105c na protokole, jako autoryzowany u\u017cytkownik, kt\u00f3ry mo\u017ce wpisa\u0107 co\u015b w wiadomo\u015bci... W\u0142a\u015bciwie nie mo\u017cna, poniewa\u017c i tak b\u0119dzie weryfikowane. Istnieje mo\u017cliwo\u015b\u0107 wy\u0142\u0105czenia tej autoryzacji dla u\u017cytkownik\u00f3w, kt\u00f3rzy jej nie chc\u0105 \u2014 to wtedy ich problem; m\u00f3wi\u0105c wprost, sami zniszczyli mury i mo\u017cna wcisn\u0105\u0107 tam s\u0142onia, kt\u00f3ry je zadepcze... Og\u00f3lnie rzecz bior\u0105c, mo\u017cna si\u0119 przebra\u0107 za serwisanta, przyj\u015b\u0107 i wyci\u0105gn\u0105\u0107!<\/p>\n<p><b>P:<\/b> \u2013 Dzi\u0119kuj\u0119 za prezentacj\u0119. Sergey (\u201eYandex\u201d). W \u201eMongo\u201d jest sta\u0142a, kt\u00f3ra limituje liczb\u0119 g\u0142osuj\u0105cych cz\u0142onk\u00f3w w Replica Set, i ta sta\u0142a wynosi 7 (siedem). Dlaczego to jest sta\u0142a? Dlaczego to nie jest jaki\u015b parametr?<\/p>\n<p><b>MT:<\/b> \u2013 Replica Set mo\u017ce mie\u0107 i 40 w\u0119z\u0142\u00f3w. Tam zawsze jest wi\u0119kszo\u015b\u0107. Nie wiem, kt\u00f3ra to wersja...<\/p>\n<p><b>P:<\/b> \u2013 W Replica Set mo\u017cna uruchamia\u0107 tak\u017ce nieg\u0142osuj\u0105cych cz\u0142onk\u00f3w, ale g\u0142osuj\u0105cych \u2014 maksymalnie 7. Jak w takim przypadku poradzi\u0107 sobie z wy\u0142\u0105czeniem, je\u015bli nasz Replica Set jest rozci\u0105gni\u0119ty na 3 centra danych? Jedno centrum danych mo\u017ce si\u0119 swobodnie wy\u0142\u0105czy\u0107, a jeszcze jedna maszyna mo\u017ce wypa\u015b\u0107.<\/p>\n<p><b>MT:<\/b> \u2013 To ju\u017c troch\u0119 wychodzi poza zakres prezentacji. To og\u00f3lne pytanie. Mo\u017ce p\u00f3\u017aniej mog\u0119 o tym opowiedzie\u0107.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Michai\u0142 Tjuleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki\" src=\"\/wp-content\/uploads\/2020\/02\/161966c7e77704dc619674ff0302ff57.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<center><div class=\"youtube-placeholder\" data-id=\"UnAprFMX1d4\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/UnAprFMX1d4\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<h3>Troch\u0119 reklamy \ud83d\ude42<\/h3>\n<p>\nDzi\u0119kujemy, \u017ce jeste\u015b z nami. Podobaj\u0105 Ci si\u0119 nasze artyku\u0142y? Chcesz zobaczy\u0107 wi\u0119cej interesuj\u0105cych materia\u0142\u00f3w? Wspieraj nas sk\u0142adaj\u0105c zam\u00f3wienie lub polecaj\u0105c nas znajomym, <noindex><a rel=\"nofollow\" href=\"https:\/\/ua-hosting.company\/cloudvps\/nl\">chmurowe VPS dla programist\u00f3w od 4,99 $<\/a><\/noindex>, <b>unikatowy odpowiednik serwer\u00f3w entry-level, kt\u00f3ry zosta\u0142 stworzony przez nas dla Ciebie:<\/b> <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/ua-hosting\/blog\/347386\/\">Ca\u0142a prawda o VPS (KVM) E5-2697 v3 (6 rdzeni) 10GB DDR4 480GB SSD 1Gbps od 19 $ lub jak prawid\u0142owo podzieli\u0107 serwer?<\/a><\/noindex> (dost\u0119pne opcje z RAID1 i RAID10, do 24 rdzeni i do 40GB DDR4).<\/p>\n<p><b>Dell R730xd dwa razy ta\u0144szy w centrum danych Equinix Tier IV w Amsterdamie?<\/b> Tylko u nas <b><noindex><a rel=\"nofollow\" href=\"https:\/\/ua-hosting.company\/serversnl\">2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100TB od 199 dolar\u00f3w<\/a><\/noindex> w Holandii! <b>Dell R420 \u2014 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB \u2014 od 99 dolar\u00f3w!<\/b><\/b> Czytaj o tym <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/ua-hosting\/blog\/329618\/\">Jak zbudowa\u0107 infrastruktur\u0119 klasy korporacyjnej z zastosowaniem serwer\u00f3w Dell R730xd E5-2650 v4 kosztuj\u0105cych 9000 euro za grosze?<\/a><\/noindex><br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ua-hosting\/blog\/487638\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f HighLoad++ \u043f\u0440\u043e\u0439\u0434\u0435\u0442 6 \u0438 7 \u0430\u043f\u0440\u0435\u043b\u044f 2020 \u0433\u043e\u0434\u0430 \u0432 \u0421\u0430\u043d\u043a\u0442-\u041f\u0435\u0442\u0435\u0440\u0431\u0443\u0440\u0433\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438 \u0431\u0438\u043b\u0435\u0442\u044b \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435. HighLoad++ Siberia 2019. \u0417\u0430\u043b \u00ab\u041a\u0440\u0430\u0441\u043d\u043e\u044f\u0440\u0441\u043a\u00bb. 25 \u0438\u044e\u043d\u044f, 12:00. \u0422\u0435\u0437\u0438\u0441\u044b \u0438 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u044f. \u0411\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0443\u044e\u0442 \u0441 \u0442\u0435\u043e\u0440\u0438\u0435\u0439, \u0433\u0434\u0435 \u043d\u0435 \u0443\u0447\u0442\u0435\u043d\u044b \u0432\u0430\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0430\u0441\u043f\u0435\u043a\u0442\u044b. \u0412 \u044d\u0442\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u044b\u0431\u043e\u0440\u0430 \u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-56365","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f HighLoad++ \u043f\u0440\u043e\u0439\u0434\u0435\u0442 6 \u0438 7 \u0430\u043f\u0440\u0435\u043b\u044f 2020 \u0433\u043e\u0434\u0430 \u0432 \u0421\u0430\u043d\u043a\u0442-\u041f\u0435\u0442\u0435\u0440\u0431\u0443\u0440\u0433\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438 \u0431\u0438\u043b\u0435\u0442\u044b \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47HighLoad++, \u041c\u0438\u0445\u0430\u0438\u043b \u0422\u044e\u043b\u0435\u043d\u0435\u0432 (MongoDB): Causal consistency: \u043e\u0442 \u0442\u0435\u043e\u0440\u0438\u0438 \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f HighLoad++ \u043f\u0440\u043e\u0439\u0434\u0435\u0442 6 \u0438 7 \u0430\u043f\u0440\u0435\u043b\u044f 2020 \u0433\u043e\u0434\u0430 \u0432 \u0421\u0430\u043d\u043a\u0442-\u041f\u0435\u0442\u0435\u0440\u0431\u0443\u0440\u0433\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438 \u0431\u0438\u043b\u0435\u0442\u044b \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-10T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:04:37+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47HighLoad++, Michai\u0142 Tyleniew (MongoDB): Sp\u00f3jno\u015b\u0107 przyczynowa: od teorii do praktyki | ProHoster","description":"Nast\u0119pna konferencja HighLoad++ odb\u0119dzie si\u0119 6 i 7 kwietnia 2020 roku w Sankt Petersburgu. Szczeg\u00f3\u0142y i bilety w podanym linku.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47HighLoad++, \u041c\u0438\u0445\u0430\u0438\u043b \u0422\u044e\u043b\u0435\u043d\u0435\u0432 (MongoDB): Causal consistency: \u043e\u0442 \u0442\u0435\u043e\u0440\u0438\u0438 \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 | ProHoster","og:description":"\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f HighLoad++ \u043f\u0440\u043e\u0439\u0434\u0435\u0442 6 \u0438 7 \u0430\u043f\u0440\u0435\u043b\u044f 2020 \u0433\u043e\u0434\u0430 \u0432 \u0421\u0430\u043d\u043a\u0442-\u041f\u0435\u0442\u0435\u0440\u0431\u0443\u0440\u0433\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438 \u0431\u0438\u043b\u0435\u0442\u044b \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-10T21:00:00+00:00","article:modified_time":"2020-02-18T11:04:37+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"56365","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:26:38","updated":"2022-09-29 16:36:31","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/56365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=56365"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/56365\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=56365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=56365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=56365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}