HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

La próxima conferencia HighLoad++ se llevará a cabo los días 6 y 7 de abril de 2020 en San Petersburgo.
Detalles y entradas enlace. HighLoad++ Siberia 2019. Salón "Krasnoyarsk". 25 de junio, 12:00 horas. Tesis y presentación.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Sucede que los requisitos prácticos entran en conflicto con la teoría, donde no se tienen en cuenta aspectos importantes para un producto comercial. Esta charla presenta un proceso para seleccionar y combinar diferentes enfoques para crear componentes de consistencia causal basados ​​en investigaciones académicas basadas en los requisitos de un producto comercial. Los oyentes aprenderán sobre los enfoques teóricos existentes sobre relojes lógicos, seguimiento de dependencias, seguridad del sistema, sincronización de relojes y por qué MongoDB se decidió por ciertas soluciones.

Mikhail Tyulenev (en adelante, MT): – Hablaré sobre la coherencia causal: esta es una característica en la que trabajamos en MongoDB. Trabajo en un grupo de sistemas distribuidos, lo hicimos hace unos dos años.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

En el proceso, tuve que familiarizarme con mucha investigación académica, porque esta característica se ha estudiado bastante bien. Resultó que ni un solo artículo encaja en lo que se requiere en una base de datos de producción debido a requisitos muy específicos que probablemente estén presentes en cualquier aplicación de producción.

Hablaré sobre cómo nosotros, como consumidores de investigación académica, preparamos algo a partir de ella que luego podemos presentar a nuestros usuarios como un plato preparado que es conveniente y seguro de usar.

Consistencia causal. Definamos los conceptos.

Para empezar quiero decir en términos generales qué es la consistencia causal. Hay dos personajes: Leonard y Penny (serie de televisión "The Big Bang Theory"):

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Digamos que Penny está en Europa y Leonard quiere hacerle una fiesta sorpresa. Y no se le ocurre nada mejor que sacarla de su lista de amigos y enviarles a todos sus amigos una actualización en el feed: "¡Hagamos feliz a Penny!". (ella está en Europa, mientras duerme, no ve todo esto y no puede verlo, porque no está). Al final, borra esta publicación, la borra del Feed y restablece el acceso para que no se dé cuenta de nada y no haya ningún escándalo.
Todo esto está muy bien, pero supongamos que el sistema está distribuido y las cosas salieron un poco mal. Puede suceder, por ejemplo, que la restricción de acceso de Penny se haya producido después de que apareciera esta publicación, si los hechos no están relacionados por causa y efecto. En realidad, este es un ejemplo de cuándo se requiere coherencia causal para realizar una función empresarial (en este caso).

De hecho, estas no son propiedades triviales de la base de datos; muy pocas personas las apoyan. Pasemos a los modelos.

Modelos de consistencia

¿Qué es exactamente un modelo de coherencia en bases de datos? Estas son algunas de las garantías que da un sistema distribuido sobre qué datos puede recibir el cliente y en qué secuencia.

En principio, todos los modelos de coherencia se reducen a qué tan similar es un sistema distribuido a un sistema que se ejecuta, por ejemplo, en un nodo de una computadora portátil. Y así de similar es un sistema que se ejecuta en miles de "nodos" geodistribuidos a una computadora portátil, en la que todas estas propiedades se realizan en principio de forma automática.

Por tanto, los modelos de coherencia se aplican sólo a sistemas distribuidos. Todos los sistemas que existían anteriormente y operaban en la misma escala vertical no experimentaron tales problemas. Había un Buffer Cache y siempre se leía todo desde él.

Modelo fuerte

En realidad, el primer modelo es Fuerte (o la línea de capacidad de ascenso, como se la suele llamar). Se trata de un modelo de coherencia que garantiza que cada cambio, una vez confirmado que ha ocurrido, sea visible para todos los usuarios del sistema.

Esto crea un orden global de todos los eventos en la base de datos. Esta es una propiedad de consistencia muy fuerte y generalmente es muy costosa. Sin embargo, está muy bien respaldado. Es muy caro y lento; rara vez se utiliza. A esto se le llama capacidad de ascenso.

Hay otra propiedad más sólida compatible con Spanner: llamada coherencia externa. Hablaremos de ello un poco más tarde.

Causal

El siguiente es Causal, que es exactamente de lo que estaba hablando. Hay varios subniveles más entre Fuerte y Causal de los que no hablaré, pero todos se reducen a Causal. Este es un modelo importante porque es el más fuerte de todos los modelos, la consistencia más fuerte en presencia de una red o particiones.

Las causales son en realidad una situación en la que los eventos están conectados por una relación de causa y efecto. Muy a menudo se perciben como Lea sus derechos desde el punto de vista del cliente. Si el cliente ha observado algunos valores, no puede ver valores que existían en el pasado. Ya está empezando a ver lecturas de prefijos. Todo se reduce a lo mismo.
Las causas como modelo de coherencia son un ordenamiento parcial de eventos en el servidor, en el que los eventos de todos los clientes se observan en la misma secuencia. En este caso, Leonard y Penny.

eventual

El tercer modelo es la coherencia eventual. Esto es lo que soportan absolutamente todos los sistemas distribuidos, el modelo mínimo que tiene algún sentido. Significa lo siguiente: cuando tenemos algunos cambios en los datos, en algún momento se vuelven consistentes.

En ese momento ella no dice nada, de lo contrario se convertiría en Consistencia Externa; sería una historia completamente diferente. Sin embargo, este es un modelo muy popular, el más común. De forma predeterminada, todos los usuarios de sistemas distribuidos utilizan la coherencia eventual.

Quiero dar algunos ejemplos comparativos:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

¿Qué significan estas flechas?

  • Latencia. A medida que aumenta la fuerza de la coherencia, se hace mayor por razones obvias: es necesario crear más registros, obtener confirmación de todos los hosts y nodos que participan en el clúster de que los datos ya están allí. En consecuencia, Eventual Consistency tiene la respuesta más rápida, porque allí, por regla general, incluso puedes memorizarlo y esto, en principio, será suficiente.
  • Disponibilidad. Si entendemos esto como la capacidad del sistema para responder ante la presencia de roturas de red, particiones o algún tipo de fallo, la tolerancia a fallos aumenta a medida que disminuye el modelo de consistencia, ya que nos basta con que un host viva y al mismo tiempo el tiempo produce algunos datos. Eventual Consistency no garantiza nada sobre los datos: puede ser cualquier cosa.
  • Anomalías. Al mismo tiempo, por supuesto, aumenta el número de anomalías. En Consistencia Fuerte casi no deberían existir en absoluto, pero en Consistencia Eventual pueden ser cualquier cosa. Surge la pregunta: ¿por qué la gente elige la Consistencia Eventual si contiene anomalías? La respuesta es que los modelos de Consistencia Eventual son aplicables y existen anomalías, por ejemplo, en un corto período de tiempo; es posible utilizar el asistente para leer y leer datos más o menos consistentes; A menudo es posible utilizar modelos de coherencia sólida. En la práctica esto funciona y, a menudo, el número de anomalías está limitado en el tiempo.

teorema de la PAC

Cuando ves las palabras coherencia, disponibilidad, ¿qué te viene a la mente? Así es: ¡teorema CAP! Ahora quiero disipar el mito... No soy yo, es Martin Kleppmann, que escribió un artículo maravilloso, un libro maravilloso.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

El teorema CAP es un principio formulado en la década de 2000 que dice: Consistencia, Disponibilidad, Particiones: toma dos y no podrás elegir tres. Era un cierto principio. Gilbert y Lynch lo demostraron como teorema unos años más tarde. Luego, esto comenzó a usarse como un mantra: los sistemas comenzaron a dividirse en CA, CP, AP, etc.

En realidad, este teorema se demostró en los siguientes casos... En primer lugar, la disponibilidad no se consideró como un valor continuo de cero a cientos (0 - el sistema está "muerto", 100 - responde rápidamente; estamos acostumbrados a considerarlo de esa manera) , sino como una propiedad del algoritmo, que garantiza que para todas sus ejecuciones devuelva datos.

¡No hay ni una palabra sobre el tiempo de respuesta! Existe un algoritmo que devuelve datos después de 100 años: un algoritmo disponible absolutamente maravilloso, que forma parte del teorema CAP.
Segundo: el teorema se demostró para cambios en los valores de la misma clave, a pesar de que estos cambios son redimensionables. Esto significa que en realidad prácticamente no se utilizan, porque los modelos son diferentes: Consistencia Eventual, Consistencia Fuerte (tal vez).

¿Para qué es todo esto? Además, el teorema CAP exactamente en la forma en que fue demostrado prácticamente no es aplicable y rara vez se utiliza. En forma teórica, de alguna manera lo limita todo. Resulta cierto principio que es intuitivamente correcto, pero que en general no ha sido probado.

La consistencia causal es el modelo más fuerte.

Lo que está sucediendo ahora es que puede obtener las tres cosas: coherencia y disponibilidad mediante particiones. En particular, la coherencia causal es el modelo de coherencia más sólido, que todavía funciona en presencia de particiones (interrupciones en la red). Por eso es de tanto interés y por eso lo adoptamos.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

En primer lugar, simplifica el trabajo de los desarrolladores de aplicaciones. En particular, la presencia de un gran soporte por parte del servidor: cuando se garantiza que todos los registros que ocurren dentro de un cliente llegarán en la misma secuencia a otro cliente. En segundo lugar, resiste las particiones.

Cocina interna MongoDB

Recordando que es el almuerzo, nos trasladamos a la cocina. Les contaré sobre el modelo del sistema, es decir, qué es MongoDB para aquellos que oyen hablar de una base de datos de este tipo por primera vez.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

MongoDB (en lo sucesivo, "MongoDB") es un sistema distribuido que admite escalamiento horizontal, es decir, fragmentación; y dentro de cada fragmento también admite redundancia de datos, es decir, replicación.

La fragmentación en MongoDB (no en una base de datos relacional) realiza un equilibrio automático, es decir, cada colección de documentos (o "tabla" en términos de datos relacionales) se divide en partes y el servidor las mueve automáticamente entre fragmentos.

El Query Router, que distribuye solicitudes para un cliente, es un cliente a través del cual trabaja. Ya sabe dónde y qué datos se encuentran y dirige todas las solicitudes al fragmento correcto.

Otro punto importante: MongoDB es un maestro único. Hay uno primario: puede aceptar registros que admitan las claves que contiene. No se puede realizar escritura multimaestro.

Hicimos la versión 4.2: allí aparecieron nuevas cosas interesantes. En particular, insertaron Lucene (búsqueda), es decir, el ejecutable Java directamente en Mongo, y allí fue posible realizar búsquedas a través de Lucene, al igual que en Elastica.

Y crearon un nuevo producto: Charts, que también está disponible en Atlas (la propia nube de Mongo). Tienen un nivel gratuito; puedes jugar con él. Me gustaron mucho los gráficos: visualización de datos, muy intuitiva.

Ingredientes Consistencia causal

Conté alrededor de 230 artículos publicados sobre este tema, de Leslie Lampert. Ahora desde mi memoria les transmitiré algunas partes de estos materiales.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Todo comenzó con un artículo de Leslie Lampert, escrito en la década de 1970. Como puede ver, todavía se están realizando algunas investigaciones sobre este tema. Ahora la coherencia causal está despertando interés en relación con el desarrollo de sistemas distribuidos.

restricciones

¿Qué restricciones hay? En realidad, este es uno de los puntos principales, porque las restricciones que impone un sistema de producción son muy diferentes a las restricciones que existen en los artículos académicos. A menudo son bastante artificiales.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

  • En primer lugar, "MongoDB" es un maestro único, como ya dije (esto simplifica enormemente).
  • Creemos que el sistema debería admitir alrededor de 10 mil fragmentos. No podemos tomar ninguna decisión arquitectónica que limite explícitamente este valor.
  • Tenemos una nube, pero asumimos que una persona aún debería tener la oportunidad cuando descarga el binario, lo ejecuta en su computadora portátil y todo funciona muy bien.
  • Asumimos algo que la investigación rara vez asume: los clientes externos pueden hacer lo que quieran. MongoDB es de código abierto. En consecuencia, los clientes pueden ser tan inteligentes y enojados que pueden querer romperlo todo. Especulamos que pueden originarse Feilors bizantinos.
  • Para los clientes externos que están fuera del perímetro, existe una limitación importante: si esta característica está deshabilitada, no se debería observar ninguna degradación del rendimiento.
  • Otro punto es generalmente antiacadémico: la compatibilidad de versiones anteriores y futuras. Los controladores antiguos deben admitir nuevas actualizaciones y la base de datos debe admitir controladores antiguos.

En general, todo esto impone restricciones.

Componentes de consistencia causal

Ahora hablaré de algunos de los componentes. Si consideramos la consistencia causal en general, podemos seleccionar bloques. Elegimos entre trabajos que pertenecen a un determinado bloque: seguimiento de dependencias, elección de relojes, cómo se pueden sincronizar estos relojes entre sí y cómo garantizamos la seguridad; este es un resumen aproximado de lo que hablaré:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Seguimiento total de dependencia

¿Por qué es necesario? De modo que cuando se replican los datos, cada registro, cada cambio de datos contiene información sobre de qué cambios depende. El primer e ingenuo cambio es cuando cada mensaje que contiene un registro contiene información sobre mensajes anteriores:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

En este ejemplo, el número entre llaves son los números de registro. A veces estos registros con valores incluso se transfieren en su totalidad, a veces se transfieren algunas versiones. La conclusión es que cada cambio contiene información sobre el anterior (obviamente lleva todo esto dentro de sí).

¿Por qué decidimos no utilizar este enfoque (seguimiento completo)? Obviamente, porque este enfoque no es práctico: cualquier cambio en una red social depende de todos los cambios anteriores en esa red social, transfiriendo, digamos, Facebook o VKontakte en cada actualización. Sin embargo, hay mucha investigación sobre el seguimiento de la dependencia total: se trata de redes presociales; en algunas situaciones realmente funciona.

Seguimiento explícito de dependencia

El siguiente es más limitado. Aquí también se considera la transferencia de información, pero sólo aquella que es claramente dependiente. Lo que depende de lo que, por regla general, lo determina la Solicitud. Cuando se replican los datos, la consulta solo devuelve respuestas cuando se han satisfecho las dependencias anteriores, es decir, se muestran. Ésta es la esencia de cómo funciona la coherencia causal.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Ve que el registro 5 depende de los registros 1, 2, 3, 4; en consecuencia, espera hasta que el cliente tenga acceso a los cambios realizados por la decisión de acceso de Penny, cuando todos los cambios anteriores ya hayan pasado por la base de datos.

Esto tampoco nos conviene, porque todavía hay demasiada información y esto ralentizará las cosas. Hay otro enfoque...

Reloj Lamport

Ellos son muy antiguos. Lamport Clock significa que estas dependencias se integran en una función escalar, que se llama Lamport Clock.

Una función escalar es un número abstracto. A menudo se le llama tiempo lógico. Con cada evento, este contador aumenta. El contador, que el proceso conoce actualmente, envía cada mensaje. Está claro que los procesos pueden no estar sincronizados, pueden tener tiempos completamente diferentes. Sin embargo, el sistema de alguna manera equilibra el reloj con dichos mensajes. ¿Qué pasa en este caso?

Dividí ese gran fragmento en dos para que quede claro: los amigos pueden vivir en un nodo, que contiene una parte de la colección, y Feed puede vivir en otro nodo, que contiene una parte de esta colección. ¿Está claro cómo pueden salirse de la raya? El primer feed dirá: "Replicado" y luego Amigos. Si el sistema no ofrece algún tipo de garantía de que el Feed no se mostrará hasta que también se entreguen las dependencias de Amigos en la colección de Amigos, entonces tendremos exactamente la situación que mencioné.

Ves cómo el tiempo del contador en Feed aumenta lógicamente:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Entonces, la propiedad principal de este Reloj Lamport y la coherencia causal (explicada a través del Reloj Lamport) es esta: si tenemos los Eventos A y B, y el Evento B depende del Evento A*, entonces se deduce que el Tiempo Lógico del Evento A es menor que Tiempo lógico del evento B.

* A veces también dicen que A sucedió antes que B, es decir, A sucedió antes que B; esta es una determinada relación que ordena parcialmente todo el conjunto de eventos que sucedieron en general.

Lo contrario es incorrecto. En realidad, esta es una de las principales desventajas de Lamport Clock: el orden parcial. Existe un concepto sobre eventos simultáneos, es decir, eventos en los que ni (A sucedió antes de B) ni (A sucedió antes de B). Un ejemplo sería la incorporación paralela de Leonard de otra persona como amigo (ni siquiera Leonard, sino Sheldon, por ejemplo).
Esta es la propiedad que se utiliza a menudo cuando se trabaja con relojes Lamport: miran específicamente la función y de esto concluyen que tal vez estos eventos sean dependientes. Porque una forma es verdadera: si LogicalTime A es menor que LogicalTime B, entonces B no puede suceder antes de A; y si es más, entonces tal vez.

Reloj vectorial

El desarrollo lógico del reloj Lamport es el Reloj Vectorial. Se diferencian en que cada nodo que se encuentra aquí contiene su propio reloj independiente y se transmiten como un vector.
En este caso, verá que el índice cero del vector es responsable de Feed y el primer índice del vector es de Friends (cada uno de estos nodos). Y ahora aumentarán: el índice cero de “Feed” aumenta al escribir – 1, 2, 3:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

¿Por qué es mejor Vector Clock? Porque le permiten determinar qué eventos son simultáneos y cuándo ocurren en diferentes nodos. Esto es muy importante para un sistema de fragmentación como MongoDB. Sin embargo, no elegimos esto, aunque es algo maravilloso, funciona muy bien y probablemente nos convendría...

Si tenemos 10 mil fragmentos, no podemos transferir 10 mil componentes, incluso si los comprimimos o se nos ocurre otra cosa: la carga útil seguirá siendo varias veces menor que el volumen de todo este vector. Por lo tanto, apretando el corazón y los dientes, abandonamos este enfoque y pasamos a otro.

Llave inglesa TrueTime. reloj atómico

Dije que habría una historia sobre Spanner. Esto es algo genial, sacado directamente del siglo XXI: relojes atómicos, sincronización GPS.

¿Cuál es la idea? "Spanner" es un sistema de Google que recientemente incluso estuvo disponible para las personas (le agregaron SQL). Cada transacción allí tiene una marca de tiempo. Dado que el tiempo está sincronizado*, a cada evento se le puede asignar un tiempo específico: los relojes atómicos tienen un tiempo de espera, después del cual se garantiza que "sucederá" un tiempo diferente.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Por lo tanto, simplemente escribiendo en la base de datos y esperando un período de tiempo, se garantiza automáticamente la serialización del evento. Tienen el modelo de coherencia más sólido que se pueda imaginar en principio: la coherencia externa.

* Este es el principal problema de los relojes Lampart: nunca son síncronos en sistemas distribuidos. Pueden divergir; incluso con NTP, todavía no funcionan muy bien. "Spanner" tiene un reloj atómico y la sincronización, al parecer, es de microsegundos.

¿Por qué no elegimos? No asumimos que nuestros usuarios tengan un reloj atómico incorporado. Cuando aparezcan, integrados en cada computadora portátil, habrá algún tipo de sincronización GPS genial, entonces sí... Pero por ahora lo mejor que es posible es Amazon, estaciones base, para fanáticos... Así que usamos otros relojes. .

Reloj híbrido

En realidad, esto es lo que funciona en MongoDB cuando se garantiza la coherencia causal. ¿Cómo son híbridos? Híbrido es un valor escalar, pero tiene dos componentes:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

  • El primero es la época Unix (cuántos segundos han pasado desde el “comienzo del mundo de la informática”).
  • El segundo es un incremento, también un int sin signo de 32 bits.

Eso es todo, en realidad. Existe este enfoque: la parte responsable del tiempo está sincronizada con el reloj todo el tiempo; cada vez que ocurre una actualización, esta parte se sincroniza con el reloj y resulta que la hora siempre es más o menos correcta, y el incremento permite distinguir entre eventos que ocurrieron en el mismo momento.

¿Por qué es esto importante para MongoDB? Porque te permite hacer una especie de respaldo de restaurantes en un momento determinado, es decir, el evento está indexado por tiempo. Esto es importante cuando se necesitan ciertos eventos; Para una base de datos, los eventos son cambios en la base de datos que ocurrieron en ciertos intervalos de tiempo.

¡Te diré la razón más importante solo a ti (por favor, no se la cuentes a nadie)! Hicimos esto porque así es como se ven los datos indexados y organizados en MongoDB OpLog. OpLog es una estructura de datos que contiene absolutamente todos los cambios en la base de datos: primero van a OpLog y luego se aplican al propio Almacenamiento en el caso de que se trate de una fecha replicada o un fragmento.

Ésta fue la razón principal. Aún así, también existen requisitos prácticos para desarrollar una base de datos, lo que significa que debe ser simple: poco código, la menor cantidad posible de elementos rotos que deban reescribirse y probarse. El hecho de que nuestros registros de operaciones estuvieran indexados mediante relojes híbridos ayudó mucho y nos permitió tomar la decisión correcta. Realmente valió la pena y de alguna manera funcionó mágicamente en el primer prototipo. ¡Era muy intersante!

Sincronización del reloj

Existen varios métodos de sincronización descritos en la literatura científica. Me refiero a la sincronización cuando tenemos dos fragmentos diferentes. Si hay un conjunto de réplicas, no es necesaria ninguna sincronización: se trata de un “maestro único”; tenemos un OpLog, en el que caen todos los cambios; en este caso, todo ya está ordenado secuencialmente en el propio "Oplog". Pero si tenemos dos fragmentos diferentes, la sincronización horaria aquí es importante. ¡Aquí es donde el reloj vectorial ayudó más! Pero no los tenemos.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

El segundo es adecuado: "Heartbeats". Es posible intercambiar algunas señales que ocurren cada unidad de tiempo. Pero los latidos son demasiado lentos y no podemos proporcionar latencia a nuestro cliente.

El tiempo real es, por supuesto, algo maravilloso. Pero, repito, probablemente esto sea el futuro... Aunque ya se puede hacer en Atlas, ya existen rápidos sincronizadores de hora “Amazon”. Pero no estará disponible para todos.

Chismear es cuando todos los mensajes incluyen tiempo. Esto es aproximadamente lo que usamos. Cada mensaje entre nodos, un controlador, un enrutador de nodo de datos, absolutamente todo para MongoDB es algún tipo de elemento, un componente de base de datos que contiene un reloj que se ejecuta. Tienen el significado de tiempo híbrido en todas partes, se transmite. ¿64 bits? Esto permite, esto es posible.

¿Cómo funciona todo en conjunto?

Aquí estoy viendo un conjunto de réplicas para hacerlo un poco más fácil. Los hay de Primaria y Secundaria. El secundario realiza la replicación y no siempre está completamente sincronizado con el primario.

Se produce una inserción en el “Primary” con un valor de tiempo determinado. Este inserto aumenta el recuento interno en 11, si este es el máximo. O verificará los valores del reloj y se sincronizará con el reloj si los valores del reloj son mayores. Esto le permite organizar por tiempo.

Luego de realizar la grabación, ocurre un momento importante. El reloj está en "MongoDB" y se incrementa sólo en caso de escribir en "Oplog". Este es el evento que cambia el estado del sistema. En absolutamente todos los artículos clásicos se considera evento cuando un mensaje llega a un nodo: el mensaje ha llegado, lo que significa que el sistema ha cambiado de estado.

Esto se debe a que durante la investigación no queda del todo claro cómo se interpretará este mensaje. Sabemos con certeza que si no se refleja en el "Oplog", no se interpretará de ninguna manera, y un cambio en el estado del sistema es solo una entrada en el "Oplog". Esto nos simplifica todo: el modelo lo simplifica y nos permite organizarlo dentro de un conjunto de réplicas, y muchas otras cosas útiles.

Se devuelve el valor que ya está escrito en el "Oplog"; sabemos que el "Oplog" ya contiene este valor y su tiempo es 12. Ahora, digamos, la lectura comienza desde otro nodo (Secundario) y se transmite afterClusterTime en el mensaje. Él dice: "Necesito todo lo que pasó al menos después de las 12 o durante las doce" (ver imagen arriba).

Esto es lo que se llama Causal a consistente (CAT). En teoría existe el concepto de que se trata de un período de tiempo que es coherente en sí mismo. En este caso, podemos decir que este es el estado del sistema que se observó en el momento 12.

Ahora bien, todavía no hay nada aquí, porque esto simula la situación en la que necesita que el Secundario replique datos del Primario. El espera... Y ahora han llegado los datos: devuelve estos valores.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Así es como funciona todo. Casi.

¿Qué significa "casi"? Supongamos que hay alguna persona que ha leído y comprendido cómo funciona todo esto. Me di cuenta de que cada vez que ocurre ClusterTime, actualiza el reloj lógico interno y luego la siguiente entrada aumenta en uno. Esta función ocupa 20 líneas. Digamos que esta persona transmite el número más grande de 64 bits, menos uno.

¿Por qué "menos uno"? Debido a que el reloj interno se sustituirá en este valor (obviamente, este es el mayor posible y mayor que la hora actual), se producirá una entrada en "Oplog" y el reloj se incrementará en otra unidad, y ya habrá ser un valor máximo (simplemente hay todas las unidades, no hay ningún otro lugar adonde ir), unsaint ints).

Está claro que después de esto el sistema se vuelve absolutamente inaccesible para cualquier cosa. Sólo se puede descargar y limpiar: mucho trabajo manual. Disponibilidad completa:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Además, si esto se replica en otro lugar, entonces todo el grupo simplemente se derrumba. ¡Una situación absolutamente inaceptable que cualquiera puede organizar de forma muy rápida y sencilla! Por eso, consideramos este momento como uno de los más importantes. ¿Cómo prevenirlo?

Nuestra forma es firmar clusterTime

Así se transmite en el mensaje (antes del texto azul). Pero también empezamos a generar una firma (texto azul):

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

La firma se genera mediante una clave que se almacena dentro de la base de datos, dentro de un perímetro seguro; en sí se genera y actualiza (los usuarios no ven nada al respecto). Se genera un hash y cada mensaje se firma cuando se crea y se valida cuando se recibe.
Probablemente en la mente de la gente surge la pregunta: “¿En qué medida esto ralentiza las cosas?” Te dije que debería funcionar rápidamente, especialmente en ausencia de esta función.

¿Qué significa utilizar la coherencia causal en este caso? Esto es para mostrar el parámetro afterClusterTime. Sin esto, simplemente pasará valores de todos modos. Cotillear, a partir de la versión 3.6, siempre funciona.

Si dejamos la generación constante de firmas, el sistema se ralentizará incluso en ausencia de una característica que no cumpla con nuestros enfoques y requisitos. entonces, ¿qué hicimos?

¡Hazlo rápido!

Es algo bastante simple, pero el truco es interesante: lo compartiré, tal vez a alguien le interese.
Tenemos un hash que almacena los datos firmados. Todos los datos pasan por el caché. El caché no firma la hora específica, sino el Rango. Cuando llega algún valor, generamos un Rango, enmascaramos los últimos 16 bits y firmamos este valor:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Al recibir dicha firma, aceleramos el sistema (relativamente) 65 mil veces. Funciona muy bien: cuando realizamos experimentos, el tiempo en realidad disminuyó 10 mil veces cuando tuvimos una actualización secuencial. Está claro que cuando están enfrentados esto no funciona. Pero en la mayoría de los casos prácticos funciona. La combinación de la firma Range junto con la firma resolvió el problema de seguridad.

¿Qué hemos aprendido?

Lecciones que aprendimos de esto:

  • Necesitamos leer materiales, historias, artículos, porque tenemos muchas cosas interesantes. Cuando trabajamos en alguna característica (especialmente ahora, cuando hicimos transacciones, etc.), necesitamos leer y comprender. Lleva tiempo, pero en realidad es muy útil porque deja claro dónde estamos. No se nos ocurrió nada nuevo, simplemente tomamos los ingredientes.

    En general, hay una cierta diferencia en la forma de pensar cuando hay una conferencia académica (Sigmon, por ejemplo): todos se concentran en nuevas ideas. ¿Qué hay de nuevo en nuestro algoritmo? No hay nada particularmente nuevo aquí. La novedad radica más bien en la forma en que combinamos los enfoques existentes. Por eso, lo primero es leer los clásicos, empezando por Lampart.

  • En la producción, los requisitos son completamente diferentes. Estoy seguro de que muchos de ustedes no se enfrentan a bases de datos "esféricas" en un vacío abstracto, sino a cosas normales y reales que tienen problemas de disponibilidad, latencia y tolerancia a fallos.
  • Lo último es que tuvimos que analizar diferentes ideas y combinar varios artículos completamente diferentes en un solo enfoque. La idea de firmar, por ejemplo, surgió generalmente de un artículo que consideraba el protocolo Paxos, que para los fallos no bizantinos está dentro del protocolo de autorización, para los bizantinos, fuera del protocolo de autorización... En general, esto es exactamente lo que terminó haciendo.

    ¡No hay absolutamente nada nuevo aquí! Pero en cuanto lo mezclamos todo... Es lo mismo que decir que la receta de la ensalada Olivier es una tontería, porque los huevos, la mayonesa y los pepinos ya están inventados... Es más o menos la misma historia.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Terminaré con esto. ¡Gracias!

preguntas

Pregunta de la audiencia (en adelante B): – ¡Gracias, Mikhail, por el informe! Es interesante el tema del tiempo. Estás usando Chismes. Dijeron que cada uno tiene su propio tiempo, cada uno conoce su hora local. Según tengo entendido, tenemos un controlador: puede haber muchos clientes con controladores, también planificadores de consultas, fragmentos también... ¿Y a qué se reduce el sistema si de repente tenemos una discrepancia: alguien decide que es para un ¿Un minuto adelante, alguien un minuto atrás? ¿Dónde terminaremos?

MONTE: – ¡Gran pregunta en verdad! Sólo quería hablar de fragmentos. Si entiendo la pregunta correctamente, tenemos la siguiente situación: hay el fragmento 1 y el fragmento 2, la lectura se produce a partir de estos dos fragmentos; tienen una discrepancia, no interactúan entre sí, porque el tiempo que conocen es diferente. especialmente el tiempo que existen en oplogs.
Digamos que el fragmento 1 generó un millón de registros, el fragmento 2 no hizo nada en absoluto y la solicitud llegó a dos fragmentos. Y el primero tiene un afterClusterTime de más de un millón. En tal situación, como expliqué, el fragmento 2 nunca responderá en absoluto.

A: – ¿Quería saber cómo se sincronizan y eligen un tiempo lógico?

MONTE: - Muy fácil de sincronizar. Shard, cuando llega afterClusterTime y no encuentra tiempo en el “Oplog”, no inicia ninguna aprobación. Es decir, eleva su tiempo con las manos a este valor. Esto significa que no tiene eventos que coincidan con esta solicitud. Él crea este evento artificialmente y así se vuelve Causal Consistente.

A: – ¿Y si después de esto le llegan algunos otros hechos que se perdieron en algún lugar de la red?

MONTE: – Shard está diseñado de tal manera que no volverán a aparecer, ya que es un solo maestro. Si ya se ha registrado, entonces no vendrán, sino que vendrán más tarde. No puede suceder que algo se quede atascado en alguna parte, luego no escriba y luego lleguen estos eventos y se rompa la coherencia causal. Cuando no escriba, deberían venir todos a continuación (los esperará).

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

A: – Tengo varias preguntas sobre las colas. La coherencia causal supone que existe una cola específica de acciones que deben realizarse. ¿Qué pasa si uno de nuestros paquetes desaparece? Aquí viene el 10, el 11... el 12 ha desaparecido, y todos los demás están esperando que se haga realidad. Y de repente nuestro coche se apagó, no podemos hacer nada. ¿Existe una longitud máxima de la cola que se acumula antes de ser ejecutada? ¿Qué fracaso fatal ocurre cuando se pierde cualquier estado? Además, si escribimos que existe algún estado previo, ¿deberíamos partir de él de alguna manera? ¡Pero no lo rechazaron!

MONTE: – ¡También es una gran pregunta! ¿Que estamos haciendo? MongoDB tiene el concepto de escritura de quórum y lectura de quórum. ¿En qué casos se puede perder un mensaje? Cuando una escritura no es quórum o cuando una lectura no es quórum (también puede quedar algún tipo de basura).
Con respecto a la coherencia causal, se llevó a cabo una gran prueba experimental, cuyo resultado fue que en el caso de que las escrituras y lecturas no tengan quórum, se producen violaciones de la coherencia causal. ¡Exactamente lo que dices!

Nuestro consejo: utilice al menos lectura de quórum cuando utilice coherencia causal. En este caso, no se perderá nada, incluso si se pierde el registro de quórum... Esta es una situación ortogonal: si el usuario no quiere que se pierdan datos, necesita utilizar un registro de quórum. La consistencia causal no garantiza la durabilidad. La durabilidad está garantizada por la replicación y la maquinaria asociada a la replicación.

A: – Cuando creamos una instancia que realiza fragmentación por nosotros (no maestra, sino esclava, respectivamente), se basa en la hora Unix de su propia máquina o en la hora del “maestro”; ¿Se sincroniza por primera vez o periódicamente?

MONTE: – Lo aclararé ahora. Fragmento (es decir, partición horizontal): siempre hay un Primario allí. Y un fragmento puede tener un "maestro" y puede haber réplicas. Pero el fragmento siempre admite la grabación, porque debe admitir algún dominio (el fragmento tiene Primario).

A: – ¿Entonces todo depende exclusivamente del “maestro”? ¿Se utiliza siempre el tiempo maestro?

MONTE: - Sí. Se puede decir en sentido figurado: el tiempo corre cuando se produce una entrada en el "maestro", en el "Oplog".

A: – ¿Tenemos un cliente que se conecta y no necesita saber nada de la hora?

MONTE: – ¡No necesitas saber nada en absoluto! Si hablamos de cómo funciona en el cliente: cuando el cliente quiere utilizar la coherencia causal, necesita abrir una sesión. Ahora todo está ahí: transacciones en la sesión y recuperación de derechos... Una sesión es la ordenación de eventos lógicos que ocurren con el cliente.

Si abre esta sesión y dice que quiere coherencia causal (si la sesión admite coherencia causal de forma predeterminada), todo funciona automáticamente. El conductor recuerda este tiempo y lo aumenta cuando recibe un nuevo mensaje. Recuerda qué respuesta devolvió el anterior del servidor que devolvió los datos. La siguiente solicitud contendrá afterCluster ("tiempo mayor que este").

¡El cliente no necesita saber absolutamente nada! Esto le resulta completamente opaco. Si la gente usa estas funciones, ¿qué pueden hacer? En primer lugar, puede leer secundarios de forma segura: puede escribir en el primario y leer desde secundarios replicados geográficamente y asegurarse de que funcione. Al mismo tiempo, las sesiones que se grabaron en Primaria se pueden incluso transferir a Secundaria, es decir, no se puede utilizar una sesión, sino varias.

A: – Una nueva capa de la informática (tipos de datos CRDT (tipos de datos replicados libres de conflictos)) está fuertemente relacionada con el tema de la coherencia eventual. ¿Has considerado integrar este tipo de datos en la base de datos y qué puedes decir al respecto?

MONTE: - ¡Buena pregunta! CRDT tiene sentido para conflictos de escritura: en MongoDB, maestro único.

A: – Tengo una pregunta de los devops. En el mundo real, ¿existen situaciones jesuíticas en las que ocurre el fracaso bizantino y las personas malvadas dentro del perímetro protegido comienzan a hurgar en el protocolo y a enviar paquetes artesanales de una manera especial?

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

MONTE: – ¡La gente malvada dentro del perímetro es como un caballo de Troya! La gente malvada dentro del perímetro puede hacer muchas cosas malas.

A: – Está claro que dejar, en términos generales, un agujero en el servidor a través del cual puedes poner un zoológico de elefantes y colapsar todo el grupo para siempre... Tomará tiempo para la recuperación manual... Esto, por decirlo suavemente, es equivocado. Por otro lado, esto es interesante: en la vida real, en la práctica, ¿hay situaciones en las que naturalmente ocurren ataques internos similares?

MONTE: – Dado que rara vez encuentro violaciones de seguridad en la vida real, no puedo decir si ocurren. Pero si hablamos de la filosofía de desarrollo, pensamos así: tenemos un perímetro que proporciona a los chicos que se ocupan de la seguridad: esto es un castillo, un muro; y dentro del perímetro puedes hacer lo que quieras. Está claro que hay usuarios con la capacidad de solo ver y hay usuarios con la capacidad de borrar el directorio.

Dependiendo de los derechos, el daño que pueden hacer los usuarios puede ser un ratón, o puede ser un elefante. Está claro que un usuario con todos los derechos puede hacer cualquier cosa. Un usuario con derechos limitados puede causar mucho menos daño. En particular, no puede romper el sistema.

A: – En el perímetro protegido, alguien intentó crear protocolos inesperados para el servidor con el fin de destruirlo por completo y, si tienes suerte, todo el clúster... ¿Alguna vez se vuelve tan “bueno”?

MONTE: "Nunca había oído hablar de esas cosas". El hecho de que puedas bloquear un servidor de esta manera no es ningún secreto. Fallar dentro, siendo del protocolo, siendo un usuario autorizado que puede escribir algo como esto en el mensaje... De hecho, es imposible, porque aún así se verificará. Es posible desactivar esta autenticación para los usuarios que no la quieran; entonces ese es su problema; ellos, en términos generales, destruyeron las paredes y puedes empujar un elefante allí, que pisoteará... Pero, en general, puedes disfrazarte de reparador, ¡ven y sácalo!

A: – Gracias por el informe. Serguéi (Yandex). Hay una constante en Mong que limita el número de miembros votantes en el conjunto de réplicas, y esta constante es 7 (siete). ¿Por qué es esto una constante? ¿Por qué no es esto algún tipo de parámetro?

MONTE: – Contamos con Conjuntos de Réplicas con 40 nodos. Siempre hay una mayoría. No se que versión...

A: – En el Conjunto de réplicas puedes ejecutar miembros sin derecho a voto, pero hay un máximo de 7 miembros con derecho a voto. ¿Cómo podemos sobrevivir al cierre en este caso si nuestro Conjunto de réplicas está distribuido en 3 centros de datos? Un centro de datos puede apagarse fácilmente y otra máquina puede caerse.

MONTE: – Esto ya está un poco más allá del alcance del informe. Esta es una pregunta general. Tal vez pueda contártelo más tarde.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: de la teoría a la práctica

Algunos anuncios 🙂

Gracias por estar con nosotros. ¿Te gustan nuestros artículos? ¿Quieres ver más contenido interesante? Apóyanos haciendo un pedido o recomendándonos a amigos, VPS en la nube para desarrolladores desde $4.99, un análogo único de servidores de nivel de entrada, que fue inventado por nosotros para usted: Toda la verdad sobre VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps desde $19 o como compartir servidor? (disponible con RAID1 y RAID10, hasta 24 núcleos y hasta 40GB DDR4).

Dell R730xd 2 veces más barato en el centro de datos Equinix Tier IV en Amsterdam? Solo aqui 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV desde $199 ¡en los Paises Bajos! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - ¡desde $99! Leer acerca de Cómo construir infraestructura corp. clase con el uso de servidores Dell R730xd E5-2650 v4 por valor de 9000 euros por un centavo?

Fuente: habr.com

Añadir un comentario