{"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\/es\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","title":{"rendered":"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>La pr\u00f3xima conferencia HighLoad++ se llevar\u00e1 a cabo el 6 y 7 de abril de 2020 en San Petersburgo. <br \/>\nDetalles y entradas <noindex><a rel=\"nofollow\" href=\"http:\/\/bit.ly\/2sSxgBx\">en el enlace<\/a><\/noindex>. HighLoad++ Siberia 2019. Sal\u00f3n \"Krasnoyarsk\". 25 de junio, 12:00. Res\u00famenes y <noindex><a rel=\"nofollow\" href=\"https:\/\/www.highload.ru\/siberia\/2019\/abstracts\/5253\">presentaci\u00f3n<\/a><\/noindex>.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/cded9c5434d670db7295aadf5da0a9f1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA veces, los requisitos pr\u00e1cticos entran en conflicto con la teor\u00eda, donde no se han considerado aspectos importantes para un producto comercial. En esta presentaci\u00f3n se presenta el proceso de selecci\u00f3n y combinaci\u00f3n de diferentes enfoques para crear componentes de consistencia causal basados en investigaciones acad\u00e9micas a partir de los requisitos de un producto comercial. Los oyentes conocer\u00e1n los enfoques te\u00f3ricos existentes sobre relojes l\u00f3gicos, seguimiento de dependencias, seguridad del sistema, sincronizaci\u00f3n de relojes y por qu\u00e9 MongoDB eligi\u00f3 ciertas soluciones.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><b>Mikhail Tyulenev (en adelante \u2013 MT):<\/b> \u2013 Voy a hablar sobre la consistencia causal; es una caracter\u00edstica en la que hemos trabajado en MongoDB. Trabajo en el grupo de sistemas distribuidos, la creamos hace aproximadamente dos a\u00f1os.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/b8d0a5b64e715f53b033fa8c398e2eb4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn el proceso tuve que familiarizarme con una gran cantidad de investigaci\u00f3n acad\u00e9mica, ya que esta caracter\u00edstica est\u00e1 bastante bien estudiada. Result\u00f3 que ning\u00fan art\u00edculo se ajusta a lo que se requiere en producci\u00f3n, a la base de datos, debido a los requisitos bastante espec\u00edficos que existen, probablemente, en cualquier aplicaci\u00f3n de producci\u00f3n.<\/p>\n<p>Voy a hablar sobre c\u00f3mo, como consumidores de la investigaci\u00f3n acad\u00e9mica, preparamos algo de ello que luego podemos presentar a nuestros usuarios como un plato terminado, con el que sea conveniente y seguro de usar.<\/p>\n<h3>Consistencia causal. Definamos los conceptos<\/h3>\n<p>\nPara comenzar, quiero esbozar en t\u00e9rminos generales qu\u00e9 es la consistencia causal. Hay dos personajes: Leonard y Penny (de la serie \"The Big Bang Theory\"):<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/ee0835b604ae5d5d6c0fa1bc369e6b18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSupongamos que Penny est\u00e1 en Europa, y Leonard quiere hacerle una sorpresa, una fiesta. Y no se le ocurre nada mejor que eliminarla de su lista de amigos, enviar a todos sus amigos una actualizaci\u00f3n en el feed: \"\u00a1Celebremos a Penny!\" (ella est\u00e1 en Europa, mientras duerme, no ve nada de esto y no puede verlo, porque no est\u00e1 all\u00ed). En un momento final elimina esa publicaci\u00f3n, la borra del \"Feed\" y restaura el acceso, para que ella no se de cuenta y no haya esc\u00e1ndalo.<br \/>\nTodo esto es maravilloso, pero supongamos que el sistema es distribuido, y las cosas no salieron exactamente como se esperaba. Puede suceder, por ejemplo, que la restricci\u00f3n de acceso a Penny se aplicara despu\u00e9s de que se public\u00f3 esta entrada, si los eventos no est\u00e1n conectados entre s\u00ed de manera causal. Este es un ejemplo de cu\u00e1ndo se requiere consistencia causal para llevar a cabo una funci\u00f3n comercial (en este caso).<\/p>\n<p>En realidad, estas son propiedades bastante no triviales de las bases de datos, muy pocos las soportan. Pasemos a los modelos.<\/p>\n<h3>Modelos de consistencia (Consistency Models)<\/h3>\n<p>\n\u00bfQu\u00e9 es en realidad un modelo de consistencia en bases de datos? Son ciertas garant\u00edas que un sistema distribuido proporciona sobre qu\u00e9 datos y en qu\u00e9 secuencia un cliente puede recibir.<\/p>\n<p>En principio, todos los modelos de consistencia se reducen a cu\u00e1n parecido es un sistema distribuido a uno que opere, por ejemplo, en un solo nodo en una laptop. Y cu\u00e1n similar es un sistema que opera en miles de nodos geogr\u00e1ficamente distribuidos a una laptop, donde todas estas propiedades se cumplen autom\u00e1ticamente.<\/p>\n<p>Por lo tanto, los modelos de consistencia solo se aplican a sistemas distribuidos. Todos los sistemas que existieron antes y funcionaron con una escalabilidad vertical no enfrentaban tales problemas. Hab\u00eda un solo Buffer Cache, y de \u00e9l siempre se le\u00eda.<\/p>\n<h3>Modelo Strong<\/h3>\n<p>\nEn realidad, el primer modelo es el Strong (o modelo de capacidad de crecimiento, como se le suele llamar). Este es un modelo de consistencia que garantiza que cada cambio, tan pronto como se recibe la confirmaci\u00f3n de que ocurri\u00f3, se vuelve visible para todos los usuarios del sistema.<\/p>\n<p>Esto crea un orden global de todos los eventos en la base de datos. Esta es una propiedad de consistencia muy fuerte, y es bastante costosa. Sin embargo, se mantiene muy bien. Es simplemente muy cara y lenta; por ello, se usa raramente. Esto se llama capacidad de crecimiento.<\/p>\n<p>Hay otra propiedad, a\u00fan m\u00e1s fuerte, que se mantiene en 'Spanner' \u2013 se llama consistencia externa. Hablaremos de esto m\u00e1s adelante.<\/p>\n<h3>Causal<\/h3>\n<p>\nLo siguiente es Causal, justo de lo que hablaba. Existen varios subniveles entre Strong y Causal, de los cuales no hablar\u00e9, pero todos se reducen a Causal. Este es un modelo importante porque es el m\u00e1s fuerte de todos los modelos, la consistencia m\u00e1s fuerte en presencia de una red o particiones.<\/p>\n<p>Causals son, de hecho, la situaci\u00f3n en la que los eventos est\u00e1n relacionados por una relaci\u00f3n de causa y efecto. A menudo se perciben como Read your own rights desde la perspectiva del cliente. Si un cliente ha observado ciertos valores, no puede ver los valores que estaban en el pasado. Ya empieza a ver lecturas prefijadas. Todo esto se reduce a lo mismo.<br \/>\nCausals como modelo de consistencia - un orden parcial de los eventos en el servidor, donde los eventos de todos los clientes se observan en la misma secuencia. En este caso - Leonard y Penny.<\/p>\n<h3>Eventual<\/h3>\n<p>\nEl tercer modelo es la Consistencia Eventual. Este es el que mantienen absolutamente todos los sistemas distribuidos, el modelo m\u00ednimo que tiene sentido. Significa lo siguiente: cuando ocurren ciertos cambios en los datos, en alg\u00fan momento se vuelven consistentes.<\/p>\n<p>En ese momento no dice nada, de lo contrario se convertir\u00eda en Consistencia Externa, ser\u00eda una historia completamente diferente. Sin embargo, este es un modelo muy popular, el m\u00e1s com\u00fan. Por defecto, todos los usuarios de sistemas distribuidos utilizan precisamente la Consistencia Eventual.<\/p>\n<p>Quiero dar algunos ejemplos comparativos:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/c23e59b30d96de6ec456aaa76c67ad61.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00bfQu\u00e9 significan estas flechas?<\/p>\n<ul>\n<li><b>Latencia.<\/b> Con un aumento en la fuerza de la consistencia, aumenta por razones evidentes: hay que realizar m\u00e1s escrituras, obtener confirmaci\u00f3n de todos los hosts y nodos que participan en el cl\u00faster, de que los datos ya est\u00e1n all\u00ed. Por tanto, en la Consistencia Eventual la respuesta m\u00e1s r\u00e1pida, porque all\u00ed, por lo general, se puede incluso confirmar en memoria y eso ser\u00e1, en principio, suficiente.<\/li>\n<li><b>Disponibilidad.<\/b> Si esto se entiende como la capacidad del sistema para responder a la existencia de interrupciones en la red, particiones o alguna falla, la resistencia a fallos aumenta al reducir el modelo de consistencia, ya que nos basta con que un host funcione y, al mismo tiempo, proporcione algunos datos. La Consistencia Eventual no garantiza nada acerca de los datos, puede ser cualquier cosa.<\/li>\n<li><b>Anomal\u00edas.<\/b> Sin embargo, naturalmente, aumenta la cantidad de anomal\u00edas. En la Consistencia Fuerte casi no deber\u00eda haber ninguna, mientras que en la Consistencia Eventual pueden existir muchas. Surge la pregunta: \u00bfpor qu\u00e9 la gente elige la Consistencia Eventual si contiene anomal\u00edas? La respuesta radica en que los modelos de Consistencia Eventual son aplicables, y las anomal\u00edas existen, por ejemplo, durante un corto per\u00edodo de tiempo; existe la posibilidad de usar un maestro para leer y obtener datos m\u00e1s o menos consistentes; a menudo hay la posibilidad de utilizar fuertes modelos de consistencia. Pr\u00e1cticamente funciona, y a menudo el n\u00famero de anomal\u00edas est\u00e1 limitado en el tiempo.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Teorema CAP<\/h3>\n<p>\nCuando escucha las palabras consistencia, disponibilidad, \u00bfqu\u00e9 le viene a la mente? \u00a1Correcto: el teorema CAP! Ahora quiero desmentir un mito\u2026 No soy yo, es Martin Kleppmann, quien escribi\u00f3 un excelente art\u00edculo, un excelente libro.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/02a9b84585218c4e85afd65f7e88aa26.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEl teorema CAP es un principio formulado en los a\u00f1os 2000, sobre que Consistencia, Disponibilidad, Particiones: toma cualquiera de los dos, y no puedes elegir los tres. Era un cierto principio. Fue probado como teorema algunos a\u00f1os despu\u00e9s, lo hicieron Gilbert y Lynch. Luego comenz\u00f3 a utilizarse como un mantra: los sistemas se dividieron en CA, CP, AP, y as\u00ed sucesivamente.<\/p>\n<p>Este teorema fue probado en realidad para ciertos casos\u2026 Primero, la Disponibilidad no se consideraba como un valor continuo de cero a cien (0 \u2013 sistema 'muerto', 100 \u2013 responde r\u00e1pidamente; as\u00ed solemos considerarlo), sino como una propiedad del algoritmo que garantiza que, en todas sus ejecuciones, devuelve datos.<\/p>\n<p>\u00a1No se menciona nada sobre el tiempo de respuesta! Hay un algoritmo que devuelve datos despu\u00e9s de 100 a\u00f1os \u2013 un algoritmo disponible absolutamente maravilloso, que forma parte del teorema CAP.<br \/>\nEn segundo lugar: el teorema se demostr\u00f3 para cambios en los valores de una misma clave, siendo estos cambios una l\u00ednea redimensionable. Esto significa que, en realidad, se utilizan poco, porque hay otros modelos de Consistencia Eventual, Consistencia Fuerte (puede ser).<\/p>\n<p>\u00bfA qu\u00e9 viene todo esto? A que el teorema CAP, en la forma en que fue demostrado, es pr\u00e1cticamente inaplicable, se utiliza raramente. En su forma te\u00f3rica, de alguna manera limita todo. Resulta ser un principio que es intuitivamente verdadero, pero que en general no est\u00e1 demostrado.<\/p>\n<h3>La consistencia causal es el modelo m\u00e1s fuerte.<\/h3>\n<p>\nLo que est\u00e1 sucediendo ahora es que se pueden obtener las tres cosas: Consistencia, Disponibilidad se pueden lograr con Particiones. En particular, la consistencia causal es el modelo m\u00e1s fuerte de consistencia que, en presencia de particiones (interrupciones en la red), sigue funcionando. Por eso es de gran inter\u00e9s y por eso nos hemos ocupado de ello.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/c4320294320261858a6d22faa97b9e23.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn primer lugar, simplifica el trabajo de los desarrolladores de aplicaciones. En particular, la gran cantidad de soporte del servidor: cuando todas las grabaciones que se realizan dentro de un solo cliente llegan garantizadas en tal secuencia a otro cliente. En segundo lugar, es resistente a particiones.<\/p>\n<h3>La cocina interna de MongoDB<\/h3>\n<p>\nTeniendo en cuenta que es hora del almuerzo, nos trasladamos a la cocina. Les hablar\u00e9 sobre el modelo del sistema, es decir, qu\u00e9 es MongoDB para aquellos que escuchan sobre esta base de datos por primera vez.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" 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): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/a1f9bcb4daebb43e4fc848a5f5f07c60.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMongoDB (en adelante, 'MongoDB') es un sistema distribuido que soporta escalabilidad horizontal, es decir, sharding; y dentro de cada shard tambi\u00e9n soporta redundancia de datos, es decir, replicaci\u00f3n.<\/p>\n<p>El sharding en 'MongoDB' (una base de datos no relacional) realiza la balanceo autom\u00e1tico, es decir, cada colecci\u00f3n de documentos (o 'tabla' en t\u00e9rminos de datos relacionales) se divide en partes, y el servidor ya mueve autom\u00e1ticamente esas partes entre los shards.<\/p>\n<p>El Query Router, que distribuye las consultas, para el cliente es como un cliente a trav\u00e9s del cual trabaja. Ya sabe d\u00f3nde y qu\u00e9 datos se encuentran, y dirige todas las consultas al shard correcto.<\/p>\n<p>Otro punto importante: MongoDB es un \u00fanico maestro. Hay un Primary que puede tomar las grabaciones que soportan las claves que contiene. No se puede hacer escritura multi-maestro.<\/p>\n<p>Hicimos el lanzamiento 4.2: aparecieron cosas nuevas e interesantes. En particular, se incorpor\u00f3 Lucene: b\u00fasqueda - es decir, java ejecutable directamente en 'Mongo', y ahora es posible realizar b\u00fasquedas a trav\u00e9s de Lucene, igual que en 'Elasticsearch'.<\/p>\n<p>Y lanzamos un nuevo producto: Charts, que tambi\u00e9n est\u00e1 disponible en 'Atlas' (nube propia de 'Mongo'). Tienen un Free Tier \u2013 se puede experimentar con eso. Charts me gust\u00f3 mucho: visualizaci\u00f3n de datos, muy intuitiva.<\/p>\n<h3>Ingredientes de la consistencia causal<\/h3>\n<p>\nCont\u00e9 aproximadamente 230 art\u00edculos que se han publicado sobre este tema \u2013 de Leslie Lampert. Ahora desde mi memoria les transmitir\u00e9 algunas partes de esos materiales.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/e88b34b7a724e94837b944a4ddd21a04.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTodo comenz\u00f3 con un art\u00edculo de Leslie Lampert, escrito en la d\u00e9cada de 1970. Como pueden ver, todav\u00eda se llevan a cabo algunas investigaciones en este tema. Hoy en d\u00eda, la consistencia causal est\u00e1 recibiendo inter\u00e9s debido al desarrollo de sistemas distribuidos.<\/p>\n<h3>Limitaciones<\/h3>\n<p>\n\u00bfCu\u00e1les son las limitaciones? Este es, de hecho, uno de los puntos principales, porque las limitaciones impuestas por los sistemas de producci\u00f3n difieren significativamente de las limitaciones que existen en los art\u00edculos acad\u00e9micos. A menudo, son bastante artificiales.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/9583ba9ff870e4ddc7aad4ba4c59ecc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Primero, 'MongoDB' es un maestro \u00fanico, como ya he mencionado (lo que simplifica mucho).<\/li>\n<li>Consideramos que el sistema deber\u00eda soportar alrededor de 10,000 shards. No podemos tomar decisiones arquitect\u00f3nicas que restrinjan claramente este valor.<\/li>\n<li>Tenemos la nube, pero suponemos que una persona debe tener la opci\u00f3n, cuando descarga el binario, de ejecutarlo en su laptop, y todo debe funcionar perfectamente.<\/li>\n<li>Suponemos que en la investigaci\u00f3n se usa raramente: los clientes externos pueden hacer lo que quieran. 'MongoDB' es de c\u00f3digo abierto. En consecuencia, los clientes pueden ser lo suficientemente inteligentes y maliciosos como para querer romper todo. Suponemos que pueden ocurrir fallos bizantinos.<\/li>\n<li>Para clientes externos, que est\u00e1n fuera del per\u00edmetro, una limitaci\u00f3n importante es: si esta funci\u00f3n est\u00e1 desactivada, no deber\u00eda haber degradaci\u00f3n del rendimiento.<\/li>\n<li>Otro punto, en general anti-acad\u00e9mico: la compatibilidad de versiones anteriores y futuras. Los controladores antiguos deben soportar nuevas actualizaciones, y la base de datos debe ser compatible con los controladores antiguos.<\/li>\n<\/ul>\n<p>\nEn general, todo esto impone limitaciones.<\/p>\n<h3>Componentes de la consistencia causal<\/h3>\n<p>\nAhora hablar\u00e9 sobre algunos componentes. Si consideramos en general la consistencia causal, podemos destacar bloques. Elegimos trabajos que pertenecen a alg\u00fan bloque: seguimiento de dependencias, elecci\u00f3n de relojes, c\u00f3mo sincronizar estos relojes entre s\u00ed y c\u00f3mo garantizamos la seguridad; este es un esquema aproximado de lo que voy a discutir:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/10c2631d6e61a280139b448628db763e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Seguimiento completo de dependencias (Full Dependency Tracking)<\/h3>\n<p>\n\u00bfPara qu\u00e9 sirve? Para que, cuando se replican los datos, cada registro, cada cambio de datos contenga informaci\u00f3n sobre de cu\u00e1les cambios depende. El primer y m\u00e1s ingenuo cambio es cuando cada mensaje que contiene un registro incluye informaci\u00f3n sobre los mensajes anteriores:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/fa5d0086c3c77e33631d8a2cd5c217fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn este ejemplo, el n\u00famero entre llaves corresponde a los n\u00fameros de los registros. A veces, estos registros con valores se transmiten en su totalidad, a veces se env\u00edan algunas versiones. La esencia reside en que cada cambio contiene informaci\u00f3n sobre el anterior (lo lleva impl\u00edcitamente).<\/p>\n<p>\u00bfPor qu\u00e9 decidimos no utilizar este enfoque (seguimiento completo)? Obviamente, porque este enfoque es impr\u00e1ctico: cualquier cambio en una red social depende de todos los cambios anteriores en esa red social, transmitiendo, digamos, \u201cFacebook\u201d o \u201cVKontakte\u201d en cada actualizaci\u00f3n. Sin embargo, hay muchos estudios sobre el Full Dependency Tracking; para ciertas situaciones, realmente funciona.<\/p>\n<h3>Seguimiento expl\u00edcito de dependencias (Explicit Dependency Tracking)<\/h3>\n<p>\nEl siguiente es m\u00e1s limitado. Aqu\u00ed tambi\u00e9n se considera la transmisi\u00f3n de informaci\u00f3n, pero solo aquella que depende expl\u00edcitamente. Lo que depende de qu\u00e9, generalmente lo determina la Aplicaci\u00f3n. Cuando se replican los datos, en la consulta solo se devuelven respuestas cuando se han satisfecho las dependencias anteriores, es decir, se han mostrado. Esta es la esencia de c\u00f3mo funciona la consistencia causal.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/7fe101b998c1a0c922788d8d36a5243f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVe que el registro 5 depende de los registros 1, 2, 3, 4; por lo tanto, espera antes de que el cliente acceda a los cambios realizados por la autorizaci\u00f3n de Penny, cuando todos los cambios anteriores ya han pasado en la base de datos.<\/p>\n<p>Esto tambi\u00e9n nos desagrada, porque la informaci\u00f3n sigue siendo excesiva y eso ralentizar\u00e1. Hay otro enfoque...<\/p>\n<h3>Relojes de Lamport (Lamport Clock)<\/h3>\n<p>\nSon muy antiguos. El reloj de Lamport implica que estas dependencias se consolidan en una funci\u00f3n escalar, que es lo que se llama el reloj de Lamport.<\/p>\n<p>Una funci\u00f3n escalar es un cierto n\u00famero abstracto. A menudo se le llama tiempo l\u00f3gico. En cada evento, este contador aumenta. El contador que en este momento es conocido por el proceso env\u00eda cada mensaje. Es evidente que los procesos pueden estar desincronizados, pueden tener tiempos completamente diferentes. Sin embargo, mediante este intercambio de mensajes, el sistema equilibra de alguna manera los relojes. \u00bfQu\u00e9 sucede en este caso?<\/p>\n<p>Divid\u00ed esa gran fragmentaci\u00f3n en dos partes para que quede claro: Friends puede vivir en un nodo que contiene una parte de la colecci\u00f3n, mientras que Feed est\u00e1 en otro nodo que contiene otra parte de esta colecci\u00f3n. \u00bfEs obvio c\u00f3mo pueden no estar en cola? Primero Feed dir\u00e1: \"Se ha replicado\", y luego \u2013 Friends. Si el sistema no garantiza que Feed no se mostrar\u00e1 hasta que las dependencias de Friends en la colecci\u00f3n Friends tambi\u00e9n est\u00e9n entregadas, entonces se generar\u00e1 la situaci\u00f3n de la que habl\u00e9.<\/p>\n<p>Ves c\u00f3mo aumenta el tiempo l\u00f3gico del contador en Feed:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/bae152d1890b53804f2cb28122983df6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAs\u00ed, la propiedad principal de este Reloj de Lamport y la consistencia causal (explicada a trav\u00e9s del Reloj de Lamport) es la siguiente: si tenemos eventos A y B, y el evento B depende del evento A *, entonces se deduce que el LogicalTime del Evento A es menor que el LogicalTime del Evento B.<\/p>\n<p><i>* A veces tambi\u00e9n se dice que A ocurri\u00f3 antes que B, es decir, A sucedi\u00f3 antes de B \u2013 esta es una relaci\u00f3n que parcialmente ordena todo el conjunto de eventos que han ocurrido.<\/i><\/p>\n<p>Lo contrario no es cierto. De hecho, esta es una de las principales desventajas del Reloj de Lamport: el orden parcial. Hay un concepto de eventos simult\u00e1neos, es decir, eventos en los que ni (A ocurri\u00f3 antes que B) ni (A ocurri\u00f3 despu\u00e9s de B). Un ejemplo podr\u00eda ser la adici\u00f3n paralela de alguien a la lista de amigos por Leonard (incluso no Leonard, sino Sheldon, por ejemplo).<br \/>\nEsta es la propiedad que a menudo se utiliza al trabajar con relojes de Lamport: se observan precisamente la funci\u00f3n y se infiere de esto \u2013 puede ser que estos eventos sean dependientes. Porque en un sentido esto es cierto: si LogicalTime A es menor que LogicalTime B, entonces B no puede haber ocurrido antes que A; y si es mayor, entonces puede ser.<\/p>\n<h3>Relojes vectoriales (Vector Clock)<\/h3>\n<p>\nEl desarrollo l\u00f3gico de los relojes de Lamport son los Relojes Vectoriales. Se diferencian en que cada nodo que hay aqu\u00ed contiene sus propios relojes separados, y se transmiten como un vector.<br \/>\nEn este caso, ves que el \u00edndice cero del vector corresponde a Feed, y el primer \u00edndice del vector corresponde a Friends (cada uno de estos nodos). Y ahora van a aumentar: el \u00edndice cero de \"Feed\" aumenta al registrar - 1, 2, 3:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/d89292686ed8dd41aef06090f16db1c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00bfPor qu\u00e9 son mejores los relojes vectoriales? Porque permiten entender qu\u00e9 eventos son simult\u00e1neos y cu\u00e1ndo ocurren en diferentes nodos. Esto es muy importante para los sistemas de particionado, como MongoDB. Sin embargo, no lo elegimos, aunque es una gran herramienta, funciona de maravilla y probablemente nos hubiera servido...<\/p>\n<p>Si tenemos 10,000 shards, no podemos transferir 10,000 componentes, incluso si comprimimos o encontramos alguna otra soluci\u00f3n, a\u00fan as\u00ed la carga \u00fatil ser\u00e1 mucho menor que el volumen total de este vector. Por lo tanto, a rega\u00f1adientes, optamos por abandonar este enfoque y pasar a otro.<\/p>\n<h3>Spanner TrueTime. Relojes at\u00f3micos<\/h3>\n<p>\nDije que habr\u00eda una explicaci\u00f3n sobre el \"Spanner\". Es algo genial, realmente del siglo XXI: relojes at\u00f3micos, sincronizaci\u00f3n GPS.<\/p>\n<p>\u00bfCu\u00e1l es la idea? \"Spanner\" es un sistema de Google que recientemente se volvi\u00f3 accesible para las personas (le a\u00f1adieron SQL). Cada transacci\u00f3n all\u00ed tiene un cierto timestamp. Dado que el tiempo est\u00e1 sincronizado*, a cada evento se le puede asignar un tiempo espec\u00edfico: los relojes at\u00f3micos tienen un tiempo de espera, despu\u00e9s del cual se garantiza que \"ocurre\" un tiempo diferente.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/707b5998fbb500d201aafffccc666f0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDe esta manera, simplemente registrando en la base de datos y esperando un cierto per\u00edodo de tiempo, se garantiza autom\u00e1ticamente la serializabilidad del evento. Tienen el modelo de consistencia m\u00e1s fuerte que se puede imaginar: es una consistencia externa.<\/p>\n<p>* Este es el principal problema de los relojes de Lamport: nunca est\u00e1n sincronizados en sistemas distribuidos. Pueden desviarse, incluso con NTP funcionan bastante mal. \"Spanner\" tiene relojes at\u00f3micos y sincronizaci\u00f3n, parece que est\u00e1 en microsegundos.<\/p>\n<p>\u00bfPor qu\u00e9 no lo elegimos? No suponemos que nuestros usuarios tengan relojes at\u00f3micos integrados. Cuando estos existan, integrados en cada laptop, habr\u00e1 una super-sincronizaci\u00f3n GPS \u2013 entonces s\u00ed... Pero por ahora lo mejor que se puede hacer son los \"Amazon\", estaciones base \u2013 para los fan\u00e1ticos... Por eso usamos otros relojes.<\/p>\n<h3>Relojes h\u00edbridos (Hybrid Clock)<\/h3>\n<p>\nEsto es, de hecho, lo que tic-tac en \u00abMongoDB\u00bb al garantizar la consistencia causal. \u00bfEn qu\u00e9 son h\u00edbridos? H\u00edbrido es un valor escalar, pero consta de dos componentes:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/dab03a87d9f6ee2e716f75baff1736bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>El primero es la \u00e9poca unix (cu\u00e1ntos segundos han pasado desde el 'inicio del mundo de la computaci\u00f3n').<\/li>\n<li>El segundo es un cierto incremento, tambi\u00e9n un entero sin signo de 32 bits.<\/li>\n<\/ul>\n<p>\nEso es todo. Hay un enfoque en el que la parte que se encarga del tiempo se sincroniza siempre con los relojes; cada vez que hay una actualizaci\u00f3n, esta parte se sincroniza con los relojes y resulta que el tiempo es m\u00e1s o menos correcto, mientras que el incremento permite distinguir eventos que ocurrieron en el mismo momento.<\/p>\n<p>\u00bfPor qu\u00e9 es esto importante para \u00abMongoDB\u00bb? Porque permite hacer copias de seguridad y restauraciones en un momento espec\u00edfico, es decir, el evento se indexa en el tiempo. Esto es importante cuando se necesitan ciertos eventos; para la base de datos, los eventos son cambios en la base de datos que ocurrieron en intervalos de tiempo espec\u00edficos.<\/p>\n<p>La raz\u00f3n principal se la dir\u00e9 solo a usted (\u00a1por favor, no se lo diga a nadie m\u00e1s)! Lo hicimos as\u00ed porque as\u00ed es como se ven los datos ordenados e indexados en MongoDB OpLog. OpLog es una estructura de datos que contiene todos los cambios en la base: primero van al OpLog y luego se aplican a Storage en caso de que sea una fecha replicada o shard.<\/p>\n<p>Esta fue la raz\u00f3n principal. Sin embargo, tambi\u00e9n existen requisitos pr\u00e1cticos para el desarrollo de la base, lo que significa que debe ser simple: poco c\u00f3digo, la menor cantidad posible de cosas rotas que deban reescribirse y probarse. El hecho de que nuestros oplogs se indexaran con relojes h\u00edbridos ayud\u00f3 mucho y permiti\u00f3 tomar la decisi\u00f3n correcta. Realmente vali\u00f3 la pena y funcion\u00f3 de manera casi m\u00e1gica en el primer prototipo. \u00a1Fue genial!<\/p>\n<h3>Sincronizaci\u00f3n de relojes<\/h3>\n<p>\nExisten varias formas de sincronizaci\u00f3n descritas en la literatura cient\u00edfica. Estoy hablando de la sincronizaci\u00f3n cuando tenemos dos shards diferentes. Si hay un replica set, no se necesita ninguna sincronizaci\u00f3n: es un 'single-master'; tenemos un OpLog en el que se registran todos los cambios - en este caso, todo ya est\u00e1 ordenado secuencialmente en el propio 'OpLog'. Pero si tenemos dos shards diferentes, aqu\u00ed la sincronizaci\u00f3n del tiempo es importante. \u00a1Aqu\u00ed es donde los relojes vectoriales ayudan m\u00e1s! Pero no los tenemos.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/7d3306747490ac044b7f8130defea0c9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEl segundo m\u00e9todo es el de los 'Heartbeats'. Se pueden intercambiar algunas se\u00f1ales que ocurren cada unidad de tiempo. Pero los 'Heartbeats' son demasiado lentos, no podemos garantizar la latencia a nuestro cliente.<\/p>\n<p>El tiempo verdadero es, por supuesto, algo maravilloso. Pero, de nuevo, probablemente es el futuro... Aunque en 'Atlas' ya se puede hacer, ya existen r\u00e1pidos sincronizadores de tiempo 'amazonianos'. Pero esto no estar\u00e1 disponible para todos.<\/p>\n<p>El 'Gossiping' es cuando todos los mensajes contienen un tiempo. Es aproximadamente lo que usamos. Cada mensaje entre nodos, controladores, enrutadores de nodos de datos, absolutamente todo para 'MongoDB' - son elementos, componentes de la base de datos, que contienen relojes que fluyen. Todos tienen un valor de tiempo h\u00edbrido que se transmite. \u00bf64 bits? Eso es posible.<\/p>\n<h3>\u00bfC\u00f3mo funciona todo esto junto?<\/h3>\n<p>\nAqu\u00ed estoy considerando un replica set para que sea un poco m\u00e1s simple. Hay un Primary y uno Secondary. El Secondary realiza la replicaci\u00f3n y no siempre est\u00e1 completamente sincronizado con el Primary.<\/p>\n<p>Se produce una inserci\u00f3n en el 'Primary' con alg\u00fan valor de tiempo. Esta inserci\u00f3n incrementa un contador interno en 11, si es m\u00e1ximo. O verificar\u00e1 los valores de los relojes y se sincronizar\u00e1 seg\u00fan el reloj, si los valores de los relojes son mayores. Esto permite ordenar por tiempo.<\/p>\n<p>Despu\u00e9s de que hace la escritura, ocurre un momento importante. Los relojes en 'MongoDB' solo se incrementan en caso de que se escriba en el 'OpLog'. Este es el evento que cambia el estado del sistema. En todos los art\u00edculos cl\u00e1sicos, el evento se considera como la llegada de un mensaje a un nodo: el mensaje ha llegado, lo que significa que el sistema ha cambiado su estado.<\/p>\n<p>Esto se debe a que al investigar no se puede entender completamente c\u00f3mo se interpretar\u00e1 este mensaje. Sabemos con certeza que si no se refleja en el \"Oplog\", no ser\u00e1 interpretado de ninguna manera, y el \u00fanico cambio en el estado del sistema es el registro en el \"Oplog\". Esto nos facilita todo: simplifica el modelo, permite organizar dentro de un \u00fanico conjunto de r\u00e9plicas y muchas otras cosas \u00fatiles.<\/p>\n<p>Se devuelve un valor que ya est\u00e1 registrado en el \"Oplog\"; sabemos que en el \"Oplog\" ya se encuentra este valor, y su tiempo es 12. Ahora, digamos que se comienza a leer desde otro nodo (Secundario), y ya transmite afterClusterTime en el mismo mensaje. \u00c9l dice: \"Necesito todo lo que ocurri\u00f3 al menos despu\u00e9s del 12 o en el momento de las doce\" (ver la figura anterior).<\/p>\n<p>Esto se denomina causalmente consistente (CAT). Hay un concepto en teor\u00eda que se refiere a un corte de tiempo que es consistente en s\u00ed mismo. En este caso, se puede decir que este es el estado del sistema que se observ\u00f3 en el momento 12.<\/p>\n<p>Ahora aqu\u00ed no hay nada, porque simula la situaci\u00f3n en la que se necesita que el Secundario replique datos del Primario. \u00c9l espera... Y aqu\u00ed llegan los datos, devolviendo estos valores de nuevo.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/54d9de3e2696c1e5d19f4da206be090b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAs\u00ed es como funciona todo m\u00e1s o menos. Casi.<\/p>\n<p>\u00bfQu\u00e9 quiere decir \"casi\"? Supongamos que hay una persona que ha le\u00eddo y entendido c\u00f3mo funciona todo. Entendi\u00f3 que cada vez ocurre un ClusterTime, actualiza los relojes l\u00f3gicos internos, y el siguiente registro incrementa en uno. Esta funci\u00f3n ocupa 20 l\u00edneas. Supongamos que esta persona transmite un n\u00famero m\u00e1ximo de 64 bits, menos uno.<\/p>\n<p>\u00bfPor qu\u00e9 \"menos uno\"? Porque los relojes internos se ajustar\u00e1n a este valor (obviamente, este es el m\u00e1s grande posible y mayor que el tiempo actual), luego ocurrir\u00e1 el registro en el \"Oplog\", y el reloj se incrementar\u00e1 en uno m\u00e1s, y ya tendr\u00e1 el valor m\u00e1ximo (all\u00ed simplemente son todos unos, no hay m\u00e1s, unsaint int\u2019s).<\/p>\n<p>Es claro que despu\u00e9s de esto el sistema se vuelve absolutamente inaccesible para nada. Solo se puede descargar, limpiar: mucho trabajo manual. Disponibilidad total:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/634b25fe0ef1e0af39181cd59c7b522f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDe hecho, si esto se replica a otro lugar, todo el cl\u00faster simplemente colapsa. \u00a1Una situaci\u00f3n absolutamente inaceptable que cualquier persona puede organizar muy r\u00e1pido y f\u00e1cil! Por eso consideramos este aspecto como uno de los m\u00e1s importantes. \u00bfC\u00f3mo prevenirlo?<\/p>\n<h3>Nuestro enfoque es firmar clusterTime<\/h3>\n<p>\nAs\u00ed se transmite en el mensaje (antes del texto azul). Pero tambi\u00e9n comenzamos a generar una firma (texto azul):<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/c16e985f9610e01a61293e0d6dde459b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa firma se genera con una clave que se almacena dentro de la base de datos, dentro de un per\u00edmetro protegido; se genera y actualiza autom\u00e1ticamente (los usuarios no ven esto). Se genera un hash, y cada mensaje se firma al crearlo, y al recibirlo se valida.<br \/>\nProbablemente, la gente se preguntar\u00e1: '\u00bfCu\u00e1nto ralentiza todo esto?' Dije que deber\u00eda funcionar r\u00e1pidamente, especialmente en ausencia de esta funci\u00f3n.<\/p>\n<p>\u00bfQu\u00e9 significa usar la consistencia causal en este caso? Esto implica mostrar el par\u00e1metro afterClusterTime. Sin esto, simplemente transmitir\u00e1 valores de cualquier forma. Gossiping, a partir de la versi\u00f3n 3.6, siempre funciona.<\/p>\n<p>Si dejamos la generaci\u00f3n constante de firmas, esto ralentizar\u00e1 el sistema incluso en ausencia de la funci\u00f3n, lo que no se alinea con nuestros enfoques y requisitos. \u00bfY qu\u00e9 hicimos?<\/p>\n<h3>\u00a1Hazlo r\u00e1pido!<\/h3>\n<p>\nEs algo bastante simple, pero el truco es interesante: lo compartir\u00e9, tal vez a alguien le interese.<br \/>\nTenemos un hash que almacena los datos firmados. Todos los datos pasan a trav\u00e9s de la cach\u00e9. La cach\u00e9 no firma un tiempo espec\u00edfico, sino un rango. Cuando llega un cierto valor, generamos un rango, enmascaramos los \u00faltimos 16 bits y firmamos este valor:<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/f4810456f08ba1cc69730ac0079d4206.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAl obtener tal firma, aceleramos el sistema (condicionalmente) 65 mil veces. Funciona perfectamente: cuando realizamos los experimentos, realmente se redujo el tiempo en 10 mil veces en nuestro proceso de actualizaci\u00f3n secuencial. Es evidente que cuando est\u00e1n desincronizados, esto no se logra. Pero en la mayor\u00eda de los casos pr\u00e1cticos, esto funciona. La combinaci\u00f3n de la firma del rango junto con la firma permiti\u00f3 resolver el problema de seguridad.<\/p>\n<h3>\u00bfQu\u00e9 hemos aprendido?<\/h3>\n<p>\nLas lecciones que hemos extra\u00eddo de esto:<\/p>\n<ul>\n<li>Es necesario leer materiales, historias, art\u00edculos, porque tenemos muchas cosas interesantes. Cuando estamos trabajando en alguna funcionalidad (especialmente ahora, cuando hemos hecho transacciones, etc.), es necesario leer y entender. Esto lleva tiempo, pero en realidad es muy \u00fatil, porque queda claro d\u00f3nde estamos. No hemos inventado nada nuevo, simplemente hemos tomado ingredientes.\n<p>De hecho, hay una diferencia notable en el pensamiento cuando se lleva a cabo una conferencia acad\u00e9mica (como \u2018Sigmon\u2019, por ejemplo) \u2013 all\u00ed todos se enfocan en nuevas ideas. \u00bfCu\u00e1l es la novedad de nuestro algoritmo? Aqu\u00ed no hay gran novedad. La novedad radica m\u00e1s en c\u00f3mo hemos combinado enfoques existentes. Por lo tanto, primero, hay que leer a los cl\u00e1sicos, comenzando por Lamport.<\/li>\n<li>En producci\u00f3n, los requisitos son completamente diferentes. Estoy seguro de que muchos de ustedes no se enfrentan a bases de datos 'esf\u00e9ricas' en un vac\u00edo abstracto, sino a cosas normales y reales que tienen problemas de disponibilidad, latencia y resistencia a fallos.<\/li>\n<li>Lo \u00faltimo es que tuvimos que considerar diferentes ideas y combinar varios art\u00edculos muy distintos en un solo enfoque. La idea sobre la firma, por ejemplo, provino de un art\u00edculo que trataba sobre el protocolo Paxos, que es para fallos no bizantinos dentro del protocolo de autorizaci\u00f3n, y para bizantinos, fuera del protocolo de autorizaci\u00f3n\u2026 En resumen, eso es exactamente lo que hemos hecho.\n<p>No hay nada absolutamente nuevo aqu\u00ed. Pero en cuanto combinamos todo\u2026 Es como decir que la receta de la ensalada Olivier es una tonter\u00eda porque ya se han inventado los huevos, la mayonesa y los pepinos\u2026 Es pr\u00e1cticamente la misma historia.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/2f9e5cb77079f9a0f7bdf76430c3386e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCon esto concluyo. \u00a1Gracias!<\/p>\n<h3>Preguntas<\/h3>\n<p>\n<b>Pregunta del p\u00fablico (en adelante \u2013 P):<\/b> \u2013 Gracias, Mikhail, por la presentaci\u00f3n. El tema del tiempo es interesante. Ustedes utilizan Gossiping. Dijo que todos tienen su propio tiempo, todos conocen su hora local. Entiendo que tenemos controladores \u2013 puede haber muchos clientes con controladores, tambi\u00e9n habr\u00e1 muchos planificadores de consultas, y muchos fragmentos\u2026 \u00bfA qu\u00e9 puede llevar el sistema si de repente hay una discrepancia: alguien decide que est\u00e1 un minuto adelantado, y otro que est\u00e1 un minuto retrasado? \u00bfD\u00f3nde terminaremos?<\/p>\n<p><b>MT:<\/b> \u2013 \u00a1Es una excelente pregunta! Justo quer\u00eda hablar sobre los shards. Si entiendo bien la pregunta, tenemos la siguiente situaci\u00f3n: shard 1 y shard 2, la lectura ocurre desde estos dos shards \u2014 tienen discrepancias, no interact\u00faan entre s\u00ed, porque el tiempo que conocen es diferente, especialmente el tiempo que existe en sus oplogs.<br \/>\nSupongamos que shard 1 hizo un mill\u00f3n de registros, shard 2 \u2014 nada, y la solicitud lleg\u00f3 a los dos shards. Y el primero tiene afterClusterTime superior a un mill\u00f3n. En esta situaci\u00f3n, como expliqu\u00e9, shard 2 nunca responder\u00e1.<\/p>\n<p><b>Q:<\/b> \u2013 Quer\u00eda saber c\u00f3mo se sincronizan y eligen un tiempo l\u00f3gico \u00fanico.<\/p>\n<p><b>MT:<\/b> \u2013 Se sincronizan de manera muy sencilla. Cuando shard recibe afterClusterTime y no encuentra tiempo en el \u2018Oplog\u2019 \u2014 inicia no approved. Es decir, establece manualmente su tiempo a ese valor. Esto significa que no tiene eventos que respondan a esa solicitud. Crea este evento de manera artificial y as\u00ed se vuelve Causal Consistent.<\/p>\n<p><b>Q:<\/b> \u2013 \u00bfY si despu\u00e9s de eso llegan eventos que se perdieron en la red?<\/p>\n<p><b>MT:<\/b> \u2013 La arquitectura de los shards es tal que ya no llegar\u00e1n, ya que es single master. Si ya se ha registrado, no llegar\u00e1n m\u00e1s, vendr\u00e1n despu\u00e9s. No puede suceder que algo se quede atascado, luego se haga no write y despu\u00e9s esos eventos lleguen \u2014 y se rompa la consistencia causal. Cuando hace no write, todos deben llegar despu\u00e9s (los esperar\u00e1).<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/dbbc7c5c653f0c9fa449cceb88ed62ef.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Q:<\/b> \u2013 Tengo algunas preguntas sobre las colas. La consistencia causal implica que hay una cola de acciones que deben ejecutarse. \u00bfQu\u00e9 sucede si se pierde un paquete? Digamos que va el 10, el 11\u2026 el 12 se pierde, y todos los dem\u00e1s esperan a que se ejecute. Y de repente la m\u00e1quina se muere, no podemos hacer nada. \u00bfHay una longitud m\u00e1xima de la cola que se acumula antes de ser ejecutada? \u00bfQu\u00e9 falla fatal ocurre al perder un solo estado? M\u00e1s a\u00fan, si estamos registrando que hay un estado anterior, \u00bfno deber\u00edamos basarnos en eso? \u00a1Pero no nos basamos en \u00e9l!<\/p>\n<p><b>MT:<\/b> \u2013 \u00a1Tambi\u00e9n es una excelente pregunta! \u00bfQu\u00e9 hacemos? En MongoDB existe el concepto de registros de qu\u00f3rum y lectura de qu\u00f3rum. \u00bfEn qu\u00e9 casos puede perderse un mensaje? Cuando la escritura no es qu\u00f3rum o cuando la lectura no es qu\u00f3rum (tambi\u00e9n puede haber alg\u00fan garbage).<br \/>\nRealizamos una extensa verificaci\u00f3n experimental sobre la consistencia causal, cuyo resultado indica que en los casos donde las escrituras y lecturas son no cu\u00f3rum, se producen violaciones de la consistencia causal. \u00a1Exactamente lo que dices!<\/p>\n<p>Nuestro consejo: utilizar al menos lecturas de cu\u00f3rum al emplear la consistencia causal. De esta manera, no se perder\u00e1 nada, incluso si la escritura de cu\u00f3rum desaparece... Esta es una situaci\u00f3n ortogonal: si el usuario no quiere que los datos se pierdan, debe utilizar escritura de cu\u00f3rum. La consistencia causal no garantiza durabilidad. La durabilidad es proporcionada por la replicaci\u00f3n y la maquinaria asociada a la replicaci\u00f3n.<\/p>\n<p><b>Q:<\/b> \u2013 Cuando creamos una instancia que realiza el sharding (no maestro, sino esclavo), se basa en el tiempo Unix de su propia m\u00e1quina o en el tiempo del 'maestro'; \u00bfsincroniza por primera vez o peri\u00f3dicamente?<\/p>\n<p><b>MT:<\/b> \u2013 Ahora aclaro. Un shard (es decir, una partici\u00f3n horizontal) siempre tiene un Primario. Y en el shard puede haber un 'maestro' y puede haber r\u00e9plicas. Pero el shard siempre mantiene la escritura, porque debe soportar alg\u00fan dominio (en el shard est\u00e1 el Primario).<\/p>\n<p><b>Q:<\/b> \u2013 Entonces, \u00bftodo depende estrictamente del 'maestro'? \u00bfSiempre se utiliza el tiempo del 'maestro'?<\/p>\n<p><b>MT:<\/b> \u2013 S\u00ed. Se puede decir de manera figurada: los relojes avanzan cuando se realiza una escritura en el 'maestro', en el 'OpLog'.<\/p>\n<p><b>Q:<\/b> \u2013 Tenemos un cliente que se conecta y no necesita saber nada sobre el tiempo?<\/p>\n<p><b>MT:<\/b> \u2013 \u00a1No necesita saber nada en absoluto! Si hablamos de c\u00f3mo funciona en el cliente: el cliente, cuando desea usar la consistencia causal, necesita abrir una sesi\u00f3n. Ahora all\u00ed est\u00e1 todo: tanto las transacciones en la sesi\u00f3n como el recuperar derechos... La sesi\u00f3n es la ordenaci\u00f3n de eventos l\u00f3gicos que ocurren con el cliente.<\/p>\n<p>Si abre esta sesi\u00f3n y dice que quiere consistencia causal (si por defecto la sesi\u00f3n soporta consistencia causal), todo funciona autom\u00e1ticamente. El controlador recuerda este tiempo y lo incrementa cuando recibe un nuevo mensaje. Recuerda qu\u00e9 respuesta devolvi\u00f3 el servidor que proporcion\u00f3 los datos. La siguiente solicitud contendr\u00e1 afterCluster ('hora mayor que esta').<\/p>\n<p>\u00a1El cliente no necesita saber nada en absoluto! Es completamente opaco para \u00e9l. Si las personas utilizan estas caracter\u00edsticas, \u00bfqu\u00e9 se puede hacer? Primero, se pueden leer secundarias de manera segura: se puede escribir en Primaria y leer desde secundarias replicadas geogr\u00e1ficamente y estar seguros de que funciona. Al mismo tiempo, las sesiones que se escribieron en Primaria se pueden transferir incluso a Secundaria, es decir, se puede utilizar no una sesi\u00f3n, sino varias.<\/p>\n<p><b>Q:<\/b> \u2013 La consistencia eventual est\u00e1 muy relacionada con una nueva rama de la ciencia computacional: los tipos de datos CRDT (Tipos de Datos Replicados Sin Conflictos). \u00bfHan considerado integrar estos tipos de datos en la base y qu\u00e9 pueden decir al respecto?<\/p>\n<p><b>MT:<\/b> \u2013 \u00a1Buena pregunta! CRDT tiene sentido para los conflictos al escribir: en MongoDB hay un \u00fanico maestro.<\/p>\n<p><b>Q:<\/b> \u2013 Tengo una pregunta de los devops. En el mundo real, hay situaciones que se parecen a esto, donde ocurre una falla bizantina, y personas maliciosas dentro del per\u00edmetro protegido comienzan a interferir con el protocolo, enviando paquetes dise\u00f1ados a medida de manera especial.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" src=\"\/wp-content\/uploads\/2020\/02\/99a521d04b416e6978aa68ce7c4a4c46.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>MT:<\/b> \u2013 Las personas maliciosas dentro del per\u00edmetro son como un caballo de Troya. Pueden hacer muchas cosas malas.<\/p>\n<p><b>Q:<\/b> \u2013 Est\u00e1 claro que dejar un peque\u00f1o agujero en el servidor, por as\u00ed decirlo, a trav\u00e9s del cual se puede introducir un zool\u00f3gico de elefantes y colapsar todo el cl\u00faster para siempre\u2026 Tomar\u00e1 tiempo para la recuperaci\u00f3n manual\u2026 Esto, por decirlo suavemente, no est\u00e1 bien. Por otro lado, es interesante saber: en la vida real, en la pr\u00e1ctica, \u00bfhay situaciones en las que ocurren de forma natural ataques internos como este?<\/p>\n<p><b>MT:<\/b> \u2013 Como no me encuentro a menudo con brechas de seguridad en la vida real, no puedo decirlo, tal vez s\u00ed ocurran. Pero si hablamos de la filosof\u00eda de desarrollo, pensamos as\u00ed: tenemos un per\u00edmetro que protege a los chicos que hacen la seguridad, es como una cerradura, una pared; y dentro del per\u00edmetro se puede hacer lo que se quiera. Est\u00e1 claro que hay usuarios con acceso solo para ver y hay usuarios con acceso para borrar un directorio.<\/p>\n<p>Dependiendo de los derechos, el da\u00f1o que los usuarios pueden causar puede ser como con un rat\u00f3n, o tambi\u00e9n con un elefante. Es evidente que un usuario con derechos completos puede hacer cualquier cosa. Un usuario con derechos limitados puede causar mucho menos da\u00f1o. En particular, no puede romper el sistema.<\/p>\n<p><b>Q:<\/b> \u2013 En el per\u00edmetro protegido, alguien est\u00e1 intentando formar protocolos inesperados para el servidor, con el fin de comprometerlo y, con suerte, todo el cl\u00faster\u2026 \u00bfPuede llegar a ser tan \"bueno\"?<\/p>\n<p><b>MT:<\/b> \u2013 Nunca he o\u00eddo hablar de tales cosas. Que se puede colapsar un servidor de esta manera no es un secreto. Colapsar desde dentro, estando en el protocolo, siendo un usuario autorizado que puede escribir en un mensaje algo as\u00ed\u2026 En realidad no es posible, porque de todos modos se validar\u00e1. Hay una posibilidad de desactivar esta autenticaci\u00f3n para los usuarios que no lo desean; ese es entonces su problema; ellos, en t\u00e9rminos generales, han destruido las paredes por s\u00ed mismos y se puede meter un elefante ah\u00ed que lo aplaste\u2026 En general, uno podr\u00eda disfrazarse de reparador, venir y sacar todo.<\/p>\n<p><b>Q:<\/b> \u2013 Gracias por el informe. Sergey (\"Yandex\"). En \"Mongo\", hay una constante que limita el n\u00famero de miembros votantes en el Replica Set, y esta constante es 7 (siete). \u00bfPor qu\u00e9 es una constante? \u00bfPor qu\u00e9 no es alg\u00fan par\u00e1metro?<\/p>\n<p><b>MT:<\/b> \u2013 En Replica Set a veces tenemos hasta 40 nodos. Siempre hay mayor\u00eda. No s\u00e9 qu\u00e9 versi\u00f3n es\u2026<\/p>\n<p><b>Q:<\/b> \u2013 En el Replica Set se pueden poner miembros no votantes, pero los votantes son un m\u00e1ximo de 7. \u00bfC\u00f3mo manejar esto en caso de que tengamos un Replica Set repartido en 3 centros de datos? Un centro de datos puede apagarse f\u00e1cilmente, y otra m\u00e1quina puede caer fuera.<\/p>\n<p><b>MT:<\/b> \u2013 Esto ya est\u00e1 un poco fuera del tema de la presentaci\u00f3n. Es una pregunta general. Tal vez luego pueda contarle.<\/p>\n<p><img decoding=\"async\" alt=\"HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica\" 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=\"Reproducir 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 poco de publicidad \ud83d\ude42<\/h3>\n<p>\nGracias por permanecer con nosotros. \u00bfTe gustan nuestros art\u00edculos? \u00bfQuieres ver m\u00e1s contenido interesante? Ap\u00f3yanos haciendo un pedido o recomendando a tus conocidos, <noindex><a rel=\"nofollow\" href=\"https:\/\/ua-hosting.company\/cloudvps\/nl\">VPS en la nube para desarrolladores desde $4.99<\/a><\/noindex>, <b>un an\u00e1logo \u00fanico de servidores entry-level que hemos dise\u00f1ado para Ti:<\/b> <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/ua-hosting\/blog\/347386\/\">Toda la verdad sobre VPS (KVM) E5-2697 v3 (6 n\u00facleos) 10GB DDR4 480GB SSD 1Gbps desde $19, o c\u00f3mo dividir correctamente un servidor?<\/a><\/noindex> (disponibles opciones con RAID1 y RAID10, hasta 24 n\u00facleos y hasta 40GB DDR4).<\/p>\n<p><b>\u00bfDell R730xd a mitad de precio en el centro de datos Equinix Tier IV en \u00c1msterdam?<\/b> Solo aqu\u00ed <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 desde $199<\/a><\/noindex> \u00a1en los Pa\u00edses Bajos! <b>Dell R420 \u2014 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB \u2014 \u00a1desde $99!<\/b><\/b> Lee sobre c\u00f3mo <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/ua-hosting\/blog\/329618\/\">Construir infraestructura de clase empresarial usando servidores Dell R730xd E5-2650 v4 que cuestan 9000 euros a un precio asequible?<\/a><\/noindex><br \/>\n<br \/>Fuente: <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.2 - 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\/es\/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.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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): Consistencia causal: de la teor\u00eda a la pr\u00e1ctica | ProHoster","description":"La pr\u00f3xima conferencia HighLoad++ se llevar\u00e1 a cabo del 6 al 7 de abril de 2020 en San Petersburgo. M\u00e1s detalles y entradas en el enlace.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/highload-mihail-tyulenev-mongodb-causal-consistency-ot-teorii-k-praktike","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/56365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=56365"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/56365\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=56365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=56365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=56365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}