{"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\/it\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","title":{"rendered":"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>La prossima conferenza HighLoad++ si terr\u00e0 il 6 e 7 aprile 2020 a San Pietroburgo. <br \/>\nDettagli e biglietti <noindex><a rel=\"nofollow\" href=\"http:\/\/bit.ly\/2sSxgBx\">al link<\/a><\/noindex>. HighLoad++ Siberia 2019. Sala \u00abKrasnoyarsk\u00bb. 25 giugno, 12:00. Tesi e <noindex><a rel=\"nofollow\" href=\"https:\/\/www.highload.ru\/siberia\/2019\/abstracts\/5253\">presentazione<\/a><\/noindex>.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/cded9c5434d670db7295aadf5da0a9f1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA volte, i requisiti pratici entrano in conflitto con la teoria, dove non sono considerati aspetti importanti per un prodotto commerciale. In questa relazione viene presentato il processo di selezione e combinazione di diversi approcci per la creazione di componenti di Causal consistency basati su ricerche accademiche, in base ai requisiti di un prodotto commerciale. Gli ascoltatori apprenderanno gli approcci teorici esistenti riguardanti orologi logici, tracciamento delle dipendenze, sicurezza dei sistemi, sincronizzazione degli orologi, e perch\u00e9 MongoDB ha scelto determinate soluzioni.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><b>Mikhail Tyulenev (di seguito \u2013 MT):<\/b> \u2013 Parler\u00f2 di Causal consistency \u2013 una caratteristica su cui abbiamo lavorato in MongoDB. Lavoro nel gruppo dei sistemi distribuiti, l'abbiamo realizzata circa due anni fa.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/b8d0a5b64e715f53b033fa8c398e2eb4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNel processo, \u00e8 stato necessario familiarizzare con un gran numero di ricerche accademiche, poich\u00e9 questa caratteristica \u00e8 ben studiata. Si \u00e8 scoperto che nessun articolo soddisfa i requisiti di produzione di un database a causa delle esigenze piuttosto specifiche che possono esistere in qualsiasi applicazione di produzione.<\/p>\n<p>Parler\u00f2 di come, come consumatori della ricerca accademica, trasformiamo queste informazioni in qualcosa che possiamo poi presentare ai nostri utenti come un piatto pronto, facile e sicuro da usare.<\/p>\n<h3>Causal consistency. Definiamo i concetti<\/h3>\n<p>\nPer iniziare, voglio dire a grandi linee cos'\u00e8 la Causal consistency. Ci sono due personaggi \u2013 Leonard e Penny (serie \u00abThe Big Bang Theory\u00bb):<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/ee0835b604ae5d5d6c0fa1bc369e6b18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSupponiamo che Penny sia in Europa, e Leonard voglia farle una sorpresa, una festa. E non trova idea migliore che rimuoverla dalla lista amici, inviando a tutti i suoi amici un aggiornamento sul feed: \u00abFacciamo una sorpresa a Penny!\u00bb (lei \u00e8 in Europa, mentre dorme, non vede nulla e non pu\u00f2 vederlo, perch\u00e9 non \u00e8 l\u00ec). Alla fine, elimina questo post, cancella dal \u00abFeed\u00bb e ripristina l'accesso, affinch\u00e9 lei non se ne accorga e non ci siano scandali.<br \/>\nTutto ci\u00f2 \u00e8 fantastico, ma supponiamo che il sistema sia distribuito e che gli eventi non siano andati come previsto. Pu\u00f2 accadere, ad esempio, che il vincolo di accesso di Penny si sia verificato dopo che questo post \u00e8 apparso, se gli eventi non sono correlati da legami di causa ed effetto. In effetti, questo \u00e8 un esempio di quando \u00e8 necessaria la coerenza causale per eseguire una funzione aziendale (in questo caso).<\/p>\n<p>In realt\u00e0, queste sono propriet\u00e0 piuttosto non banali dei database \u2013 molto pochi le supportano. Passiamo ai modelli.<\/p>\n<h3>Modelli di Coerenza (Consistency Models)<\/h3>\n<p>\nChe cos'\u00e8 in realt\u00e0 un modello di coerenza nei database? Sono alcune garanzie che un sistema distribuito fornisce riguardo a quali dati e in quale sequenza il cliente pu\u00f2 ricevere.<\/p>\n<p>In linea di principio, tutti i modelli di coerenza si riducono a quanto un sistema distribuito assomigli a un sistema che funziona, ad esempio, su un solo nodo su un laptop. E quanto un sistema che funziona su migliaia di nodi geograficamente distribuiti assomiglia a un laptop, in cui tutte queste propriet\u00e0 vengono eseguite fondamentalmente in modo automatico.<\/p>\n<p>Pertanto, i modelli di coerenza si applicano solo ai sistemi distribuiti. Tutti i sistemi che esistevano in precedenza e funzionavano su un'unica scalabilit\u00e0 verticale non aveva tali problemi. C'era un solo Buffer Cache, e da esso veniva sempre letto tutto.<\/p>\n<h3>Modello Strong<\/h3>\n<p>\nLa prima vera modello \u00e8 lo Strong (o la linea di rise ability, come viene spesso chiamato). Questo \u00e8 un modello di coerenza che garantisce che ogni modifica, non appena si riceve conferma che \u00e8 avvenuta, diventi visibile a tutti gli utenti del sistema.<\/p>\n<p>Questo crea un ordine globale di tutti gli eventi nel database. Questa \u00e8 una propriet\u00e0 di coerenza molto forte, ed \u00e8 anche molto costosa. Tuttavia, \u00e8 ben supportata. \u00c8 semplicemente molto costosa e lenta \u2013 viene utilizzata raramente. Questo si chiama rise ability.<\/p>\n<p>C'\u00e8 anche un'altra propriet\u00e0, pi\u00f9 robusta, supportata in 'Spanner' \u2013 chiamata Coerenza Esterna. Ne parleremo pi\u00f9 avanti.<\/p>\n<h3>Causale<\/h3>\n<p>\nIl seguente \u00e8 Causal, proprio ci\u00f2 di cui parlavo. Tra Strong e Causal ci sono ancora alcuni sottolivelli, di cui non parler\u00f2, ma tutti si riducono a Causal. \u00c8 un modello importante perch\u00e9 \u00e8 il pi\u00f9 forte di tutti i modelli, la coerenza pi\u00f9 forte in presenza di reti o partizioni.<\/p>\n<p>I Causals sono la situazione in cui gli eventi sono legati da una relazione causale. Spesso vengono percepiti come Read your own rights dal punto di vista del cliente. Se un cliente ha osservato alcuni valori, non pu\u00f2 vedere i valori che erano nel passato. Inizia gi\u00e0 a vedere letture prefissate. Questo si riduce a una questione comune.<br \/>\nI Causals come modello di coerenza rappresentano un ordinamento parziale degli eventi sul server, in cui gli eventi da tutti i clienti sono osservati nella stessa sequenza. In questo caso: Leonard e Penny.<\/p>\n<h3>Eventual<\/h3>\n<p>\nIl terzo modello \u00e8 la Eventual Consistency. Questo \u00e8 ci\u00f2 che supporta assolutamente tutti i sistemi distribuiti, il modello minimo che ha senso. Significa quanto segue: quando ci sono alcuni cambiamenti nei dati, a un certo punto diventano coerenti.<\/p>\n<p>In quel momento non dice nulla, altrimenti si trasformerebbe in External Consistency \u2013 sarebbe completamente un'altra storia. Tuttavia, \u00e8 un modello molto popolare, il pi\u00f9 comune. Per impostazione predefinita, tutti gli utenti dei sistemi distribuiti utilizzano proprio la Eventual Consistency.<\/p>\n<p>Voglio fornire alcuni esempi comparativi:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/c23e59b30d96de6ec456aaa76c67ad61.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCosa significano queste frecce?<\/p>\n<ul>\n<li><b>Latenza.<\/b> Con l'aumentare della forza della coerenza, diventa maggiore per motivi evidenti: \u00e8 necessario effettuare pi\u00f9 registrazioni, ottenere conferma da tutti gli host e nodi coinvolti nel cluster che i dati sono gi\u00e0 presenti. Pertanto, nella Eventual Consistency la risposta pi\u00f9 rapida \u00e8 la pi\u00f9 comune, perch\u00e9 l\u00ec di solito \u00e8 possibile anche commettere in memoria e questo \u00e8 fondamentalmente sufficiente.<\/li>\n<li><b>Disponibilit\u00e0.<\/b> Se si considera come possibilit\u00e0 del sistema di rispondere in caso di guasti di rete, partizioni o eventuali malfunzionamenti \u2013 la tolleranza ai guasti aumenta con la diminuzione del modello di coerenza, poich\u00e9 \u00e8 sufficiente che un host sia attivo e fornisca alcuni dati. La Eventual Consistency non garantisce nulla riguardo ai dati \u2013 potrebbero essere qualsiasi cosa.<\/li>\n<li><b>Anomalie.<\/b> In questo caso, ovviamente, aumenta il numero di anomalie. In Strong Consistency non dovrebbero praticamente essercene, mentre in Eventual Consistency possono esserci tutti i tipi di anomalie. La domanda \u00e8: perch\u00e9 le persone scelgono Eventual Consistency se contiene anomalie? La risposta \u00e8 che i modelli di Eventual Consistency sono applicabili, e le anomalie esistono, ad esempio, solo per brevi periodi di tempo; c'\u00e8 la possibilit\u00e0 di utilizzare un master per la lettura e di ottenere dati pi\u00f9 o meno consistenti; spesso \u00e8 possibile utilizzare modelli di consistenza forte. In pratica funziona, e spesso il numero di anomalie \u00e8 limitato nel tempo.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Teorema CAP<\/h3>\n<p>\nQuando vedi le parole consistency, availability \u2013 cosa ti viene in mente? Giusto \u2013 il teorema CAP! Ora voglio sfatare il mito\u2026 Non sono io \u2013 \u00e8 Martin Kleppmann, che ha scritto un ottimo articolo, un ottimo libro.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/02a9b84585218c4e85afd65f7e88aa26.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIl teorema CAP \u00e8 un principio formulato negli anni 2000, riguardante Consistency, Availability, Partitions: prendi due a caso, e non puoi scegliere tre. Era un certo principio. \u00c8 stato dimostrato come teorema alcuni anni dopo, da Gilbert e Lynch. Poi \u00e8 stato utilizzato come mantra \u2013 i sistemi sono stati classificati in CA, CP, AP e cos\u00ec via.<\/p>\n<p>Questo teorema \u00e8 stato in realt\u00e0 dimostrato per i seguenti casi\u2026 In primo luogo, Availability \u00e8 stata considerata non come un valore continuo da zero a cento (0 \u2013 sistema \"morto\", 100 \u2013 risponde rapidamente; ci siamo abituati a vederla in questo modo), ma come una propriet\u00e0 dell'algoritmo che garantisce che per tutte le sue esecuzioni restituisca dati.<\/p>\n<p>Non c'\u00e8 nemmeno una parola sul tempo di risposta! Esiste un algoritmo che restituisce dati dopo 100 anni \u2013 un algoritmo available assolutamente magnifico, che fa parte del teorema CAP.<br \/>\nIn secondo luogo: il teorema \u00e8 stato dimostrato per le modifiche nei valori della stessa chiave, pur essendo queste modifiche una linea resizable. Ci\u00f2 significa che in realt\u00e0 non vengono praticamente utilizzate, perch\u00e9 ci sono altri modelli di Eventual Consistency, Strong Consistency (forse).<\/p>\n<p>A cosa serve tutto questo? Al fatto che il teorema CAP, proprio nella forma in cui \u00e8 stato dimostrato, \u00e8 praticamente inapplicabile, usato raramente. Nella forma teorica limita in qualche modo tutto. Risulta un certo principio, che \u00e8 intuitivamente corretto, ma che non \u00e8 in alcun modo dimostrato.<\/p>\n<h3>Causal consistency \u00e8 il modello pi\u00f9 forte<\/h3>\n<p>\nQuello che sta succedendo ora - si possono ottenere tutte e tre le cose: Coerenza, Disponibilit\u00e0 pu\u00f2 essere raggiunta attraverso le Partizioni. In particolare, la coerenza causale \u00e8 il modello di coerenza pi\u00f9 forte, che funziona anche in presenza di Partizioni (interruzioni nella rete). Ecco perch\u00e9 suscita un grande interesse e per questo ci siamo dedicati.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/c4320294320261858a6d22faa97b9e23.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn primo luogo, semplifica il lavoro degli sviluppatori di applicazioni. In particolare, c'\u00e8 un ampio supporto da parte del server: quando tutte le registrazioni che avvengono all'interno di un cliente arrivano garantite in tale sequenza su un altro cliente. In secondo luogo, resiste alle partizioni.<\/p>\n<h3>La cucina interna di MongoDB<\/h3>\n<p>\nRicordando che \u00e8 l'ora del pranzo, ci spostiamo in cucina. Vi parler\u00f2 del modello del sistema, cio\u00e8 di cosa sia MongoDB per coloro che sentono parlare di questo tipo di database per la prima volta.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/a1784442ff1c44403b5347f4f43a1197.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/a1f9bcb4daebb43e4fc848a5f5f07c60.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMongoDB (di seguito \"MongoDB\") \u00e8 un sistema distribuito che supporta la scalabilit\u00e0 orizzontale, cio\u00e8 lo sharding; e all'interno di ogni shard supporta anche la ridondanza dei dati, cio\u00e8 la replica.<\/p>\n<p>Lo sharding in \"MongoDB\" (un DB non relazionale) esegue un bilanciamento automatico, cio\u00e8 ogni raccolta di documenti (o \"tabella\" in termini di dati relazionali) viene suddivisa in parti, e il server sposta automaticamente queste parti tra gli shard.<\/p>\n<p>Il Query Router, che distribuisce le richieste, \u00e8 per il cliente un certo tipo di client, attraverso il quale lavora. Sa gi\u00e0 dove si trovano quali dati e dirige tutte le richieste al giusto shard.<\/p>\n<p>Un'altra cosa importante: MongoDB \u00e8 un single master. C'\u00e8 un Primary - pu\u00f2 gestire le registrazioni che supportano le chiavi che contiene. Non \u00e8 possibile effettuare scritture multi-master.<\/p>\n<p>Abbiamo rilasciato la versione 4.2 - sono emerse nuove cose interessanti. In particolare, abbiamo inserito Lucene - ricerca - ovvero java eseguibile direttamente in \"Mongo\", ed \u00e8 diventato possibile eseguire ricerche attraverso Lucene, proprio come in \"Elasticsearch\".<\/p>\n<p>E abbiamo creato un nuovo prodotto - Charts, che \u00e8 anche disponibile su \"Atlas\" (il cloud di Mongo). Hanno un Free Tier - puoi sperimentare con questo. Mi \u00e8 piaciuto molto Charts - visualizzazione dei dati, molto intuitiva.<\/p>\n<h3>Ingredienti della coerenza causale<\/h3>\n<p>\nHo contato circa 230 articoli pubblicati su questo tema - da Leslie Lampert. Ora vi trasmetter\u00f2 dalla mia memoria alcune parti di questi materiali.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/e88b34b7a724e94837b944a4ddd21a04.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTutto \u00e8 cominciato con un articolo di Leslie Lampert, scritto negli anni '70. Come potete vedere, continuano a esserci ricerche in questo campo. Attualmente, la consistenza causale sta suscitando interesse a causa dello sviluppo delle sistemi distribuiti.<\/p>\n<h3>Limitazioni<\/h3>\n<p>\nQuali sono i limiti? Questo \u00e8 in realt\u00e0 uno dei punti principali, perch\u00e9 i vincoli imposti dai sistemi di produzione sono molto diversi da quelli che esistono negli articoli accademici. Spesso sono piuttosto artificiali.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/9583ba9ff870e4ddc7aad4ba4c59ecc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Innanzitutto, \"MongoDB\" \u00e8 un master singolo, come ho gi\u00e0 detto (questo semplifica molto).<\/li>\n<li>Riteniamo che il sistema debba supportare circa 10.000 shard. Non possiamo prendere decisioni architetturali che limiterebbero esplicitamente questo valore.<\/li>\n<li>Abbiamo un cloud, ma riteniamo che una persona debba avere la possibilit\u00e0 di scaricare un binary, eseguirlo sul proprio laptop e tutto funzioni perfettamente.<\/li>\n<li>Riteniamo che nel Research venga raramente utilizzato: i clienti esterni possono fare qualsiasi cosa. \"MongoDB\" \u00e8 open source. Di conseguenza, i clienti possono essere cos\u00ec intelligenti e maliziosi da volere rompere tutto. Prevediamo che possano verificarsi fasi di Byzantine.<\/li>\n<li>Per i clienti esterni, che si trovano al di fuori del perimetro, c'\u00e8 un'importante limitazione: se questa funzionalit\u00e0 \u00e8 disattivata, non ci dovrebbero essere degradi nelle performance.<\/li>\n<li>Un altro punto, totalmente anti-accademico: la compatibilit\u00e0 tra versioni precedenti e future. I driver vecchi devono supportare i nuovi aggiornamenti, e il database deve supportare i vecchi driver.<\/li>\n<\/ul>\n<p>\nIn generale, tutto ci\u00f2 impone delle limitazioni.<\/p>\n<h3>Componenti della consistenza causale<\/h3>\n<p>\nOra parler\u00f2 di alcuni componenti. Se si considera la consistenza causale, si possono evidenziare vari blocchi. Abbiamo scelto dai lavori che appartengono a un certo blocco: tracciamento delle dipendenze, scelta degli orologi, come sincronizzare questi orologi tra loro e come garantiamo la sicurezza \u2013 questo \u00e8 un piano approssimativo di ci\u00f2 di cui parler\u00f2:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/10c2631d6e61a280139b448628db763e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Tracciamento completo delle dipendenze (Full Dependency Tracking)<\/h3>\n<p>\nA cosa serve? Per garantire che, quando i dati vengono replicati, ogni record e ogni modifica ai dati contenga informazioni su quali modifiche dipende. La prima e pi\u00f9 semplice modifica \u00e8 quando ogni messaggio che contiene un record include informazioni sui messaggi precedenti:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/fa5d0086c3c77e33631d8a2cd5c217fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questo esempio, il numero tra parentesi graffe rappresenta i numeri dei record. A volte questi record con i valori vengono trasferiti anche per intero, in altre occasioni vengono trasferite versioni specifiche. La sostanza sta nel fatto che ogni modifica contiene informazioni sulla precedente (questo \u00e8 ci\u00f2 che normalmente trasporta).<\/p>\n<p>Perch\u00e9 abbiamo deciso di non utilizzare questo approccio (tracciamento completo)? \u00c8 ovvio che questo approccio non \u00e8 pratico: ogni modifica in un social network dipende da tutte le modifiche precedenti in quel social network, trasmettendo, ad esempio, \u2018Facebook\u2019 o \u2018Vkontakte\u2019 in ogni aggiornamento. Tuttavia, ci sono molte ricerche sul Full Dependency Tracking: queste sono reti pre-sociali, per alcune situazioni funziona davvero.<\/p>\n<h3>Tracciamento delle dipendenze esplicite (Explicit Dependency Tracking)<\/h3>\n<p>\nIl successivo \u00e8 pi\u00f9 limitato. Qui viene considerata solo la trasmissione delle informazioni che dipendono esplicitamente. Ci\u00f2 da cui dipende, di solito, \u00e8 gi\u00e0 definito dall'Applicazione. Quando i dati vengono replicati, durante la richiesta vengono forniti solo risposte quando le dipendenze precedenti sono state soddisfatte, cio\u00e8 mostrate. Questo \u00e8 il cuore di come funziona la coerenza causale.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/7fe101b998c1a0c922788d8d36a5243f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVede che il record 5 dipende dai record 1, 2, 3, 4; di conseguenza, aspetta che il cliente acceda alle modifiche apportate dall'accesso di Penny, quando tutte le modifiche precedenti sono gi\u00e0 passate nel database.<\/p>\n<p>Questo non ci soddisfa nemmeno, poich\u00e9 ci sarebbe comunque troppa informazione, il che rallenterebbe. Esiste un altro approccio...<\/p>\n<h3>Orologi di Lamport (Lamport Clock)<\/h3>\n<p>\nSono molto vecchi. Lamport Clock implica che queste dipendenze si riducono a una funzione scalare, che \u00e8 chiamata Lamport Clock.<\/p>\n<p>La funzione scalare \u00e8 un certo numero astratto. Spesso viene chiamato tempo logico. Ad ogni evento, questo counter aumenta. Il counter attualmente conosciuto dal processo invia ogni messaggio. \u00c8 chiaro che i processi possono essere disallineati e avere tempi completamente diversi. Tuttavia, attraverso questo scambio di messaggi, il sistema somehow bilancia gli orologi. Cosa succede in questo caso?<\/p>\n<p>Ho diviso quel grande shard in due, per chiarire: i Friends possono vivere in un nodo che contiene un pezzo della collezione, mentre il Feed pu\u00f2 trovarsi in un altro nodo, che contiene un altro pezzo di questa collezione. \u00c8 chiaro come possano non andare in coda? Prima il Feed dir\u00e0: \"Replicato\", poi i Friends. Se il sistema non garantisce che il Feed non venga mostrato finch\u00e9 le dipendenze dei Friends nella collezione Friends non siano state consegnate, allora ci troveremo esattamente nella situazione di cui ho parlato.<\/p>\n<p>Vedete come aumenta logicalmente il tempo del counter sul Feed:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/bae152d1890b53804f2cb28122983df6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPertanto, la principale caratteristica di questo Lamport Clock e della coerenza causale (spiegata tramite Lamport Clock) \u00e8 la seguente: se abbiamo eventi A e B, e l'evento B dipende dall'evento A *, ne deriva che il LogicalTime dell'Evento A \u00e8 minore del LogicalTime dell'Evento B.<\/p>\n<p><i>* A volte si dice anche che A \u00e8 accaduto prima di B, il che significa che A \u00e8 successo prima di B: \u00e8 una relazione che ordina parzialmente l'intero insieme di eventi che si sono verificati.<\/i><\/p>\n<p>Il contrario non \u00e8 vero. Questo \u00e8 in effetti uno dei principali svantaggi del Lamport Clock: l'ordine parziale. Esiste il concetto di eventi simultanei, cio\u00e8 eventi nei quali n\u00e9 (A \u00e8 successo prima di B), n\u00e9 (A \u00e8 successo dopo B). Un esempio pu\u00f2 essere l'aggiunta simultanea di qualcuno come amico da parte di Leonardo (non necessariamente da Leonardo stesso, ma ad esempio da Sheldon).<br \/>\nQuesto \u00e8 il principio che viene spesso utilizzato quando si lavora con i Lamport Clock: si guarda precisamente alla funzione e da questo si trae una conclusione: forse questi eventi sono dipendenti. Perch\u00e9 in un senso \u00e8 vero: se LogicalTime A \u00e8 minore di LogicalTime B, allora B non pu\u00f2 essere successo prima di A; mentre se \u00e8 maggiore, potrebbe.<\/p>\n<h3>Orologi vettoriali (Vector Clock)<\/h3>\n<p>\nLo sviluppo logico degli orologi di Lamport sono gli orologi vettoriali. Si differenziano in quanto ogni nodo qui contiene i propri orologi separati, che vengono trasmessi come un vettore.<br \/>\nIn questo caso, vedete che l'indice zero del vettore corrisponde al Feed, mentre il primo indice del vettore si riferisce ai Friends (ognuno di questi nodi). E ora stanno per aumentare: l'indice zero del \"Feed\" aumenta durante la scrittura \u2013 1, 2, 3:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/d89292686ed8dd41aef06090f16db1c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPerch\u00e9 gli Orologi Vettoriali sono migliori? Perch\u00e9 consentono di capire quali eventi sono simultanei e quando si verificano su diversi nodi. Questo \u00e8 molto importante per il sistema di shard, come \"MongoDB\". Tuttavia, non abbiamo optato per questo, anche se \u00e8 una cosa magnifico, funziona meravigliosamente e probabilmente ci sarebbe stata utile...<\/p>\n<p>Se abbiamo 10 mila shard, non possiamo trasmettere 10 mila componenti, anche se comprimiamo, pensiamo a qualche altra soluzione \u2013 la payload utile sar\u00e0 comunque di gran lunga inferiore al volume totale di questo vettore. Pertanto, con grande riluttanza, abbiamo abbandonato questo approccio e siamo passati a un altro.<\/p>\n<h3>Spanner TrueTime. Orologi atomici<\/h3>\n<p>\nHo detto che parler\u00f2 di \"Spanner\". \u00c8 una cosa fantastica, proprio del XXI secolo: orologi atomici, sincronizzazione GPS.<\/p>\n<p>Qual \u00e8 l'idea? \"Spanner\" \u00e8 un sistema di Google, che recentemente \u00e8 persino diventato accessibile alle persone (vi hanno aggiunto SQL). Ogni transazione ha un certo timestamp. Poich\u00e9 il tempo \u00e8 sincronizzato*, a ogni evento pu\u00f2 essere assegnato un determinato orario: gli orologi atomici hanno un tempo di attesa, dopo il quale avviene garantito un altro orario.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/707b5998fbb500d201aafffccc666f0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questo modo, semplicemente registrando nel DB e aspettando un certo periodo di tempo, si garantisce automaticamente la Serializability dell'evento. Hanno il modello di Consistency pi\u00f9 forte che si possa immaginare \u2013 si tratta di External Consistency.<\/p>\n<p>* Questo \u00e8 il principale problema degli orologi di Lamport \u2013 non sono mai sincronizzati nei sistemi distribuiti. Possono divergere, anche in presenza di NTP funzionano comunque non molto bene. \"Spanner\" ha orologi atomici e sincronizzazione, sembra, nell'ordine dei microsecondi.<\/p>\n<p>Perch\u00e9 non l'abbiamo scelto? Non presupponiamo che i nostri utenti abbiano orologi atomici integrati. Quando appariranno, essendo integrati in ogni laptop, ci sar\u00e0 una sorta di super-sincronizzazione GPS \u2013 allora s\u00ec... Ma per ora, la cosa migliore che sia possibile \u2013 \u00e8 \"Amazon\", le Stazioni Base \u2013 per i fanatici... Pertanto, abbiamo utilizzato altri orologi.<\/p>\n<h3>Orologi Ibridi (Hybrid Clock)<\/h3>\n<p>\nQuesto \u00e8 praticamente ci\u00f2 che scatta in \u00abMongoDB\u00bb assicurando la coerenza causale. In cosa consistono gli ibridi? Un ibrido \u00e8 un valore scalare, ma \u00e8 composto da due componenti:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/dab03a87d9f6ee2e716f75baff1736bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Il primo \u00e8 l'epoca unix (quanti secondi sono passati dall'inizio del \"mondo informatico\").<\/li>\n<li>Il secondo \u00e8 un certo incremento, anch'esso un intero unsigned a 32 bit.<\/li>\n<\/ul>\n<p>\nQuesto \u00e8 sostanzialmente tutto. Esiste un approccio in cui la parte che si occupa del tempo \u00e8 sempre sincronizzata con l'orologio; ogni volta che avviene un aggiornamento, questa parte si sincronizza con l'orologio e si scopre che il tempo \u00e8 sempre pi\u00f9 o meno corretto, mentre l'incremento consente di distinguere gli eventi che sono accaduti nello stesso momento.<\/p>\n<p>Perch\u00e9 \u00e8 importante per \u00abMongoDB\u00bb? Perch\u00e9 consente di effettuare backup e ripristini a un determinato momento, cio\u00e8 gli eventi vengono indicizzati nel tempo. Questo \u00e8 importante quando sono necessari alcuni eventi; per il database, gli eventi sono quelle modifiche nel DB che si sono verificate in determinati intervalli di tempo.<\/p>\n<p>Vi dir\u00f2 il motivo principale solo a voi (per favore, non ditelo a nessuno)! Lo abbiamo fatto perch\u00e9 cos\u00ec appaiono i dati ordinati e indicizzati nel MongoDB OpLog. L'OpLog \u00e8 una struttura dati che contiene tutte le modifiche nel database: inizialmente entrano nell'OpLog e solo successivamente vengono applicate al proprio Storage nel caso in cui si tratti di dati replicati o shard.<\/p>\n<p>Questa \u00e8 stata la motivazione principale. Ci sono comunque anche requisiti pratici per lo sviluppo del database, il che significa che deve essere semplice: poco codice, il minor numero possibile di cose rotte da riscrivere e testare. Il fatto che i nostri oplog siano stati indicizzati con orologi ibridi ha aiutato notevolmente e ha permesso di compiere scelte corrette. Questo si \u00e8 rivelato efficace e in qualche modo ha funzionato magicamente, nel primo prototipo. \u00c8 stato davvero fantastico!<\/p>\n<h3>Sincronizzazione degli orologi<\/h3>\n<p>\nEsistono diversi modi di sincronizzazione descritti nella letteratura scientifica. Parlo di sincronizzazione quando abbiamo due shard diversi. Se c'\u00e8 un replica set \u2013 non \u00e8 necessaria alcuna sincronizzazione: \u00e8 un \"single-master\"; abbiamo un OpLog, in cui tutte le modifiche vengono registrate \u2013 in questo caso tutto \u00e8 gi\u00e0 ordinato sequenzialmente nell'\"OpLog\". Ma se abbiamo due shard diversi, qui la sincronizzazione del tempo \u00e8 importante. Qui gli orologi vettoriali sono stati di maggiore aiuto! Ma noi non li abbiamo.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/7d3306747490ac044b7f8130defea0c9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIl secondo modo \u00e8 rappresentato dai \"Heartbeats\". \u00c8 possibile scambiarsi alcuni segnali che avvengono ogni unit\u00e0 di tempo. Ma i \"Heartbeats\" sono troppo lenti, non possiamo garantire la latenza ai nostri clienti.<\/p>\n<p>Il tempo vero \u2013 \u00e8 sicuramente una cosa splendida. Ma, di nuovo, \u00e8 probabilmente il futuro\u2026 Anche se in \"Atlas\" \u00e8 gi\u00e0 possibile farlo, ci sono gi\u00e0 rapidi sincronizzatori di tempo \"amazoniani\". Ma questo non sar\u00e0 disponibile per tutti.<\/p>\n<p>Gossiping \u2013 \u00e8 quando tutti i messaggi includono il tempo. \u00c8 grosso modo quello che utilizziamo. Ogni messaggio tra nodi, driver, router di data node, assolutamente tutto per \"MongoDB\" \u2013 sono elementi, componenti del database che contengono orologi che scorrono. Ovunque c'\u00e8 un valore di tempo ibrido, viene trasmesso. 64 bit? Questo \u00e8 possibile.<\/p>\n<h3>Come funziona tutto questo insieme?<\/h3>\n<p>\nQui considero un replica set per semplificare un po'. C'\u00e8 un Primary e un Secondary. Il Secondary esegue la replicazione e non \u00e8 sempre completamente sincronizzato con il Primary.<\/p>\n<p>Avviene un inserimento nel \"Primary\" con un certo valore di tempo. Questo inserimento aumenta il contatore interno di 11, se \u00e8 il massimo. Oppure controller\u00e0 i valori degli orologi e si sincronizzer\u00e0 in base agli orologi, se i valori sono superiori. Questo consente di ordinare per tempo.<\/p>\n<p>Dopo che viene effettuata la registrazione, avviene un momento importante. Gli orologi in \"MongoDB\" vengono incrementati solo in caso di registrazione nell'\"OpLog\". Questo \u00e8 l'evento che modifica lo stato del sistema. In tutti gli articoli classici, un evento si considera l'arrivo di un messaggio nel nodo: se il messaggio \u00e8 arrivato, significa che il sistema ha cambiato il proprio stato.<\/p>\n<p>Questo \u00e8 dovuto al fatto che durante la ricerca non \u00e8 possibile capire completamente come questo messaggio verr\u00e0 interpretato. Sappiamo con certezza che se non \u00e8 riflesso nell'\u00abOpLog\u00bb, non verr\u00e0 interpretato in alcun modo, e il cambiamento di stato del sistema \u00e8 solo la registrazione nell'\u00abOpLog\u00bb. Questo ci semplifica tutto: sia il modello \u00e8 semplificato, sia consente di gestire l'ordinamento all'interno di un unico replica-set, e molte altre cose utili.<\/p>\n<p>Viene restituito il valore che \u00e8 gi\u00e0 registrato nell'\u00abOpLog\u00bb \u2013 sappiamo che in \u00abOpLog\u00bb c'\u00e8 gi\u00e0 questo valore, e il suo tempo \u00e8 \u2013 12. Ora, supponiamo che inizi la lettura da un'altra nodo (Secondary), e lui trasmette gi\u00e0 afterClusterTime nel messaggio stesso. Dice: \u00abHo bisogno di tutto ci\u00f2 che \u00e8 accaduto almeno dopo le 12 o durante le dodici\u00bb (vedi l'immagine sopra).<\/p>\n<p>Questo \u00e8 ci\u00f2 che viene chiamato Causal a consistent (CAT). Esiste un concetto nella teoria che rappresenta un certo intervallo di tempo, che \u00e8 coerente in s\u00e9. In questo caso si pu\u00f2 dire che questo \u00e8 lo stato del sistema che \u00e8 stato osservato al momento 12.<\/p>\n<p>Al momento qui non c'\u00e8 nulla, perch\u00e9 questo simula una situazione in cui \u00e8 necessario che il nodo Secondario replichi i dati dal Primario. Sta aspettando... Ecco che i dati sono arrivati \u2013 restituisce questi valori.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/54d9de3e2696c1e5d19f4da206be090b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCos\u00ec funziona pi\u00f9 o meno tutto. Quasi.<\/p>\n<p>Cosa significa \u00abquasi\u00bb? Supponiamo che ci sia una persona che ha letto e capito come funziona tutto. Ha capito che ogni volta si verifica ClusterTime, aggiorna gli orologi logici interni, e poi la successiva registrazione incrementa di uno. Questa funzione occupa 20 righe. Supponiamo che questa persona trasmetta il numero intero massimo a 64 bit, meno uno.<\/p>\n<p>Perch\u00e9 \u00abmeno uno\u00bb? Perch\u00e9 gli orologi interni verranno inseriti in questo valore (ovviamente, si tratta del massimo possibile e maggiore del tempo attuale), poi ci sar\u00e0 la registrazione nell'\u00abOpLog\u00bb, e gli orologi saranno incrementati di un'unit\u00e0 in pi\u00f9 \u2013 e avremo gi\u00e0 il valore massimo (ci saranno solo tutti gli uni, non c'\u00e8 oltre, unsaint int).<\/p>\n<p>\u00c8 chiaro che dopo questo il sistema diventa assolutamente inaccessibile a qualsiasi cosa. Pu\u00f2 essere solo scaricato, pulito \u2013 molto lavoro manuale. Disponibilit\u00e0 completa:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/634b25fe0ef1e0af39181cd59c7b522f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nInoltre, se questo si replica da qualche altra parte, tutto il cluster si bloccano. Una situazione assolutamente inaccettabile che chiunque pu\u00f2 organizzare in modo molto rapido e semplice! Perci\u00f2, abbiamo considerato questo aspetto come uno dei pi\u00f9 importanti. Come prevenirlo?<\/p>\n<h3>Il nostro approccio \u00e8 firmare clusterTime<\/h3>\n<p>\nCos\u00ec viene trasmesso nel messaggio (fino al testo blu). Ma abbiamo anche cominciato a generare una firma (testo blu):<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/c16e985f9610e01a61293e0d6dde459b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa firma \u00e8 generata da una chiave che \u00e8 conservata all'interno del database, all'interno di un perimetro protetto; viene generata e aggiornata (gli utenti non vedono nulla di tutto questo). Viene generato un hash e ogni messaggio, al momento della creazione, \u00e8 firmato e, al momento della ricezione, \u00e8 validato.<br \/>\nProbabilmente sorge la domanda tra le persone: \u00abQuanto rallenta tutto ci\u00f2?\u00bb Ho detto che deve funzionare rapidamente, specialmente in assenza di questa funzione.<\/p>\n<p>Cosa significa utilizzare la coerenza causale in questo caso? Significa mostrare il parametro afterClusterTime. E senza questo, semplicemente passer\u00e0 i valori in ogni caso. Gossiping, a partire dalla versione 3.6, funziona sempre.<\/p>\n<p>Se lasciamo la generazione continua delle firme, questo rallenter\u00e0 il sistema anche in assenza della funzione, il che non si allinea con i nostri approcci e requisiti. E cosa abbiamo fatto?<\/p>\n<h3>Falllo in fretta!<\/h3>\n<p>\nUna cosa abbastanza semplice, ma il trucco \u00e8 interessante \u2013 lo condivider\u00f2, magari a qualcuno interesser\u00e0.<br \/>\nAbbiamo un hash che contiene dati firmati. Tutti i dati passano attraverso la cache. La cache non firma un tempo specifico, ma un Range. Quando arriva un certo valore, generiamo un Range, mascheriamo gli ultimi 16 bit, e questo valore lo firmiamo:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/f4810456f08ba1cc69730ac0079d4206.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOttenendo una tale firma, accelera il sistema (condizionalmente) di 65 mila volte. Funziona magnificamente: quando abbiamo condotto esperimenti \u2013 l\u00ec il tempo di aggiornamento sequenziale \u00e8 realmente ridotto di 10 mila volte. \u00c8 chiaro che quando sono disordinati, non \u00e8 possibile. Ma nella maggior parte dei casi pratici funziona. La combinazione della firma Range insieme alla firma ha permesso di risolvere il problema della sicurezza.<\/p>\n<h3>Cosa abbiamo imparato?<\/h3>\n<p>\nLe lezioni che abbiamo tratto da questo:<\/p>\n<ul>\n<li>\u00c8 necessario leggere materiali, storie, articoli, perch\u00e9 abbiamo molte cose interessanti da dire. Quando lavoriamo su una nuova funzionalit\u00e0 (soprattutto ora, quando stiamo facendo transazioni ecc.), bisogna leggere e capire. Questo richiede tempo, ma \u00e8 davvero molto utile, perch\u00e9 diventa chiaro dove ci troviamo. Non abbiamo inventato nulla di nuovo, abbiamo semplicemente preso gli ingredienti.\n<p>In generale, si osserva una certa differenza nel modo di pensare quando si tiene una conferenza accademica (per esempio, \u00abSigmon\u00bb) \u2013 l\u00ec tutti si concentrano su nuove idee. Qual \u00e8 l'innovazione del nostro algoritmo? Qui non c'\u00e8 nulla di particolarmente nuovo. L'innovazione risiede piuttosto nel modo in cui abbiamo combinato approcci esistenti. Quindi per prima cosa \u2013 bisogna leggere i classici, a partire da Lamport.<\/li>\n<li>In produzione ci sono requisiti completamente diversi. Sono sicuro che molti di voi non affrontano \u00abdatabase sferici\u00bb in un vuoto astratto, ma cose normali e reali, che hanno problemi di disponibilit\u00e0, latenza e tolleranza ai guasti.<\/li>\n<li>Infine, abbiamo dovuto considerare diverse idee e combinare insieme vari articoli completamente diversi in un unico approccio. L'idea della firma, per esempio, \u00e8 venuta da un articolo che considerava il protocollo Paxos, utilizzato per i failover non bizantini all'interno di un protocollo di autorizzazione, e per quelli bizantini al di fuori di esso... In sostanza, \u00e8 esattamente quello che abbiamo fatto.\n<p>Non c'\u00e8 assolutamente nulla di nuovo qui! Ma non appena abbiamo mescolato tutto insieme... \u00c8 come dire che la ricetta dell'insalata Olivier \u00e8 sciocca, perch\u00e9 le uova, la maionese e i cetrioli sono gi\u00e0 stati inventati... \u00c8 pi\u00f9 o meno la stessa storia.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/2f9e5cb77079f9a0f7bdf76430c3386e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nConcludo qui. Grazie!<\/p>\n<h3>Domande<\/h3>\n<p>\n<b>Domanda dal pubblico (da qui in poi \u2013 D):<\/b> \u2013 Grazie, Mikhail, per la relazione! Il tema del tempo \u00e8 interessante. Tu utilizzi Gossiping. Hai detto che ognuno ha il proprio tempo, tutti conoscono il proprio tempo locale. Ho capito che abbiamo un driver \u2013 ci possono essere molti clienti con driver, molti query-planner e anche diversi shard... Cosa succede al sistema se ci dovesse essere una discrepanza: qualcuno decide di essere un minuto avanti, qualcuno \u2013 un minuto indietro? Dove ci ritroveremo?<\/p>\n<p><b>MT:<\/b> \u2013 Ottima domanda, in effetti! Volevo proprio parlare dei shard. Se ho capito correttamente la domanda, la situazione \u00e8 questa: ci sono lo shard 1 e lo shard 2, la lettura avviene da questi due shard \u2013 sono in disaccordo, non interagiscono tra loro, perch\u00e9 il tempo che conoscono \u00e8 diverso, specialmente il tempo che hanno negli oplog.<br \/>\nSupponiamo che lo shard 1 abbia effettuato un milione di registrazioni, lo shard 2 \u2013 nessuna, e la richiesta sia arrivata a entrambi gli shard. E il primo ha un afterClusterTime superiore a un milione. In questa situazione, come ho spiegato, lo shard 2 non risponder\u00e0 mai.<\/p>\n<p><b>D:<\/b> \u2013 Volevo sapere come si sincronizzano e scelgono un tempo logico unico?<\/p>\n<p><b>MT:<\/b> \u2013 Si sincronizzano molto semplicemente. Lo shard, quando riceve l'afterClusterTime e non trova il tempo nell'\u00abOplog\u00bb, inizia un no approved. Cio\u00e8, alza manualmente il proprio tempo fino a quel valore. Questo significa che non ha eventi che corrispondono a questa richiesta. Crea quindi questo evento artificialmente e diventa cos\u00ec Causal Consistent.<\/p>\n<p><b>D:<\/b> \u2013 E se dopo ci\u00f2 arrivano eventi che si sono persi nella rete?<\/p>\n<p><b>MT:<\/b> \u2013 Lo shard \u00e8 strutturato in modo tale che non arriveranno pi\u00f9, poich\u00e9 si tratta di un single master. Se ha gi\u00e0 registrato, non arriveranno pi\u00f9, ma saranno successivi. Non pu\u00f2 succedere che qualcosa si perda da qualche parte, poi faccia un no write e dopo che quegli eventi siano arrivati \u2013 e sia stata violata la Causal consistency. Quando fa un no write, tutti devono arrivare successivamente (lui li aspetter\u00e0).<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/dbbc7c5c653f0c9fa449cceb88ed62ef.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>D:<\/b> \u2013 Ho alcune domande riguardo alle code. La Causal consistency implica che ci sia una certa coda di azioni da eseguire. Cosa succede se un pacchetto va perso? Ecco che \u00e8 arrivato il 10\u00b0, 11\u00b0... il 12\u00b0 \u00e8 andato perso, e tutti gli altri aspettano che venga eseguito. E improvvisamente la macchina \u00e8 morta, non possiamo fare nulla. C'\u00e8 una lunghezza massima della coda che si accumula prima che venga eseguita? Qual \u00e8 il fatal failure che si verifica con la perdita di uno qualsiasi stato? Soprattutto se registriamo che c'\u00e8 uno stato precedente, da esso dobbiamo in qualche modo partire? Ma non ci si \u00e8 partiti!<\/p>\n<p><b>MT:<\/b> \u2013 Anche questa \u00e8 un'ottima domanda! Cosa facciamo? In MongoDB esiste il concetto di registrazioni di quorum, lettura di quorum. In quali casi un messaggio pu\u00f2 andare perso? Quando la registrazione non \u00e8 di quorum o quando la lettura non \u00e8 di quorum (pu\u00f2 anche arrivare qualche spazzatura).<br \/>\nPer quanto riguarda la coerenza causale, abbiamo effettuato un ampio esperimento che ha mostrato che, nel caso in cui le operazioni di scrittura e lettura siano non-quorum, si verificano violazioni della coerenza causale. Proprio quello che stai dicendo!<\/p>\n<p>Il nostro consiglio: utilizzare almeno letture quorum quando si utilizza la coerenza causale. In questo caso, non andr\u00e0 perso nulla, anche se la scrittura quorum dovesse andare persa... \u00c8 una situazione ortogonale: se l'utente non vuole perdere dati, deve utilizzare scritture quorum. La coerenza causale non garantisce durabilit\u00e0. La garanzia di durabilit\u00e0 \u00e8 fornita dalla replicazione e dal meccanismo collegato alla replicazione.<\/p>\n<p><b>D:<\/b> \u2013 Quando creiamo un'istanza, che esegue lo sharding (non il master, ma lo slave corrispondentemente), si basa sul tempo UNIX della propria macchina o sul tempo del \"master\"; si sincronizza la prima volta o periodicamente?<\/p>\n<p><b>MT:<\/b> \u2013 Adesso chiarisco. Lo shard (cio\u00e8 la partizione orizzontale) ha sempre un primario. All'interno dello shard pu\u00f2 esserci un \"master\" e possono esserci repliche. Ma lo shard sostiene sempre la scrittura, perch\u00e9 deve mantenere un certo dominio (lo shard ha un Primario).<\/p>\n<p><b>D:<\/b> \u2013 Quindi tutto dipende esclusivamente dal \"master\"? Si usa sempre il tempo del \"master\"?<\/p>\n<p><b>MT:<\/b> \u2013 S\u00ec. Si potrebbe dire in modo figurato: gli orologi ticchettano quando avviene una scrittura nel \"master\", nel \"OpLog\".<\/p>\n<p><b>D:<\/b> \u2013 Abbiamo un cliente che si connette, e non ha bisogno di sapere nulla riguardo al tempo?<\/p>\n<p><b>MT:<\/b> \u2013 Assolutamente non ha bisogno di sapere nulla! Parlando di come funziona lato cliente: quando il cliente desidera utilizzare la coerenza causale, deve aprire una sessione. Ora ci sono tutte: le transazioni nella sessione e l'ottenimento dei diritti... La sessione \u00e8 un ordinamento di eventi logici che avvengono con il cliente.<\/p>\n<p>Se apre questa sessione e dice che desidera la coerenza causale (se per impostazione predefinita la sessione supporta la coerenza causale), tutto funziona automaticamente. Il driver memorizza questo tempo e lo aumenta quando riceve un nuovo messaggio. Memorizza quale risposta ha restituito il server precedente, che ha restituito i dati. La richiesta successiva conterr\u00e0 afterCluster (\"tempo maggiore di questo\").<\/p>\n<p>Al cliente non serve sapere assolutamente nulla! \u00c8 completamente opaco per lui. Se le persone utilizzano queste funzionalit\u00e0, cosa consente di fare? Innanzitutto, si possono leggere in modo sicuro le secondarie: si pu\u00f2 scrivere su Primary e leggere da secondarie replicate geograficamente, essendo certi che funzioni. Inoltre, le sessioni registrate su Primary possono essere trasferite anche su Secondary, ossia \u00e8 possibile utilizzare pi\u00f9 di una sessione.<\/p>\n<p><b>D:<\/b> \u2013 La tematica della Eventual consistency \u00e8 strettamente legata a un nuovo elemento della scienza informatica: i tipi di dati CRDT (Conflict-free Replicated Data Types). Avete preso in considerazione l'integrazione di questi tipi di dati nel database e cosa ne pensate?<\/p>\n<p><b>MT:<\/b> \u2013 Ottima domanda! I CRDT hanno senso per i conflitti in scrittura: in MongoDB abbiamo un master unico.<\/p>\n<p><b>D:<\/b> \u2013 Ho una domanda dai DevOps. Nel mondo reale ci sono situazioni cos\u00ec ingannevoli quando si verifica un Failure bizantino, e persone malevole all'interno di un perimetro protetto iniziano a intromettersi nel protocollo, inviando pacchetti craftati in modo specifico?<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" src=\"\/wp-content\/uploads\/2020\/02\/99a521d04b416e6978aa68ce7c4a4c46.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>MT:<\/b> \u2013 Persone malevole all'interno del perimetro sono come un cavallo di Troia! Possono fare molte cose cattive.<\/p>\n<p><b>D:<\/b> \u2013 \u00c8 chiaro che lasciare nel server, per cos\u00ec dire, un buco attraverso cui far passare un intero zoo di elefanti e abbattersi sull'intero cluster per sempre... Ci vorrebbe tempo per un ripristino manuale... Questo, per usare un eufemismo, \u00e8 sbagliato. D'altra parte, \u00e8 interessante sapere: nella vita reale, nella pratica, ci sono situazioni in cui tali attacchi interni si verificano realmente?<\/p>\n<p><b>MT:<\/b> \u2013 Poich\u00e9 non mi capita spesso di affrontare brecce di sicurezza nella vita reale, non posso dire se effettivamente accadano. Ma se parliamo di filosofia dello sviluppo, noi riteniamo questo: abbiamo un perimetro che protegge i ragazzi che si occupano della sicurezza: \u00e8 un lucchetto, un muro; e all'interno del perimetro si pu\u00f2 fare qualsiasi cosa. \u00c8 chiaro che ci sono utenti con la possibilit\u00e0 solo di visualizzare e vi sono utenti con la possibilit\u00e0 di cancellare un catalogo.<\/p>\n<p>In base ai diritti, il danno che gli utenti possono infliggere pu\u00f2 variare da un clic di mouse a un'azione da elefante. \u00c8 chiaro che un utente con diritti completi pu\u00f2 fare praticamente qualsiasi cosa. Un utente con diritti limitati pu\u00f2 infliggere danni significativamente minori. In particolare, non pu\u00f2 compromettere il sistema.<\/p>\n<p><b>D:<\/b> \u2013 Nel perimetro protetto qualcuno ha tentato di formare protocolli inaspettati per il server, per mandare il server in crash e, se tutto va bene, l'intero cluster... \u00c8 possibile che sia cos\u00ec \"positivo\"?<\/p>\n<p><b>MT:<\/b> \u2013 Non ne ho mai sentito parlare. Non \u00e8 un segreto che si possa mandare in tilt un server in questo modo. Mandare in tilt dall'interno, rimanendo autorizzato come utente che pu\u00f2 scrivere qualcosa nel messaggio... In realt\u00e0 non \u00e8 possibile, perch\u00e9 verr\u00e0 comunque verificato. \u00c8 possibile disattivare questa autenticazione per gli utenti che non la desiderano \u2013 queste sono le loro problematiche; in parole povere, hanno abbattuto loro stessi le mura e si pu\u00f2 infilare un elefante che calpesta... In generale, dai, puoi vestirti da tecnico, venire e tirarlo fuori!<\/p>\n<p><b>D:<\/b> \u2013 Grazie per la relazione. Sergey (\"Yandex\"). In \"Mongo\" c'\u00e8 una costante che limita il numero dei membri votanti nel Replica Set, e questa costante \u00e8 pari a 7 (sette). Perch\u00e9 \u00e8 una costante? Perch\u00e9 non \u00e8 un parametro qualsiasi?<\/p>\n<p><b>MT:<\/b> \u2013 Nel Replica Set abbiamo anche 40 nodi. Ci deve sempre essere una maggioranza. Non so quale sia la versione...<\/p>\n<p><b>D:<\/b> \u2013 Nel Replica Set \u00e8 possibile avviare membri non votanti, ma i votanti sono al massimo 7. Come ci si comporta in caso di disattivazione, se il nostro Replica Set \u00e8 distribuito su 3 data center? Un data center pu\u00f2 spegnersi facilmente, e un'altra macchina pu\u00f2 andare offline.<\/p>\n<p><b>MT:<\/b> \u2013 Questo \u00e8 gi\u00e0 leggermente al di fuori della relazione. \u00c8 una domanda generale. Forse posso parlarne pi\u00f9 tardi.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Coerenza causale: dalla teoria alla pratica\" 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=\"Guarda il video\" 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>Un po' di pubblicit\u00e0 \ud83d\ude42<\/h3>\n<p>\nGrazie per rimanere con noi. Ti piacciono i nostri articoli? Vuoi vedere pi\u00f9 contenuti interessanti? Supportaci effettuando un ordine o raccomandandoci a qualcuno. <noindex><a rel=\"nofollow\" href=\"https:\/\/ua-hosting.company\/cloudvps\/nl\">VPS cloud per sviluppatori a partire da $4.99.<\/a><\/noindex>, <b>unica alternativa ai server entry-level, concepita da noi per te:<\/b> <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/ua-hosting\/blog\/347386\/\">Tutta la verit\u00e0 sui VPS (KVM) E5-2697 v3 (6 Core) 10GB DDR4 480GB SSD 1Gbps a partire da $19 o come dividere correttamente un server?<\/a><\/noindex> (sono disponibili opzioni con RAID1 e RAID10, fino a 24 core e fino a 40GB DDR4).<\/p>\n<p><b>Dell R730xd a met\u00e0 prezzo nel data center Equinix Tier IV ad Amsterdam?<\/b> Solo da noi <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 100 TB a partire da $199<\/a><\/noindex> nei Paesi Bassi! <b>Dell R420 \u2014 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB \u2014 a partire da $99!<\/b><\/b> Leggi di <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/ua-hosting\/blog\/329618\/\">Come costruire un'infrastruttura di livello enterprise utilizzando server Dell R730xd E5-2650 v4 del valore di 9000 euro a pochi spiccioli?<\/a><\/noindex><br \/>\n<br \/>Fonte: <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\/it\/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=\"it_IT\" \/>\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\/it\/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++, Mikhail Tyulenyev (MongoDB): Causal consistency: dalla teoria alla pratica | ProHoster","description":"La prossima conferenza HighLoad++ si terr\u00e0 il 6 e 7 aprile 2020 a San Pietroburgo. Maggiori dettagli e biglietti al link.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/56365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=56365"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/56365\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=56365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=56365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=56365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}