Debo decir que todo desarrollador debe comprender la consistencia de la base de datos.

Imagínese asignar un valor a una variable y luego leerlo inmediatamente, sólo para descubrir que la escritura de ahora no funciona en absoluto. ¿Es una locura? 

x = 42assert(x == 42)  # 抛出异常

Esta situación se puede encontrar cuando se utiliza almacenamiento de datos distribuido con garantías de coherencia débiles. Puede preguntar: "Espere, ¿no debería la base de datos resolver el problema de consistencia por mí?" Después de la operación de actualización, los datos reales se actualizarán inmediatamente o tomará un tiempo, dependiendo de si la base de datos ofrece esta garantía.

Las garantías de coherencia proporcionadas por algunas bases de datos son un poco contradictorias, pero su propósito es proporcionar alta disponibilidad y alto rendimiento. También hay algunas bases de datos que le permiten elegir si desea un mejor rendimiento o garantías más sólidas, como Cosmos DB y Cassandra de Azure. Por lo tanto, debe comprender los pros y los contras.

 

Anatomía de una solicitud de base de datos

Echemos un vistazo a lo que sucede a continuación cuando envía la solicitud a la base de datos. En una situación ideal, su solicitud se ejecutará de inmediato:

Sin embargo, no vivimos en un mundo ideal, su solicitud debe ser enviada al almacén de datos, luego procesada y finalmente se le envía la respuesta. Todas estas operaciones requieren una cierta cantidad de tiempo y no se pueden completar en un instante:

La mejor garantía que puede proporcionar la base de datos es que la solicitud se ejecute en algún momento entre la llamada y la finalización. Puede pensar que esto no es un gran problema. Después de todo, está acostumbrado a esto cuando escribe una aplicación de un solo subproceso. Por ejemplo, si asigna 1 ax y luego lee el valor de x, definitivamente obtendrá 1, siempre que no haya otros subprocesos. Escribe la misma variable. Sin embargo, cuando utiliza el almacenamiento de datos para replicar el estado de los datos en varias computadoras con el fin de lograr una alta disponibilidad y escalabilidad, todo se vuelve desconocido. Para comprender por qué sucede esto, exploremos los pros y los contras que los diseñadores de sistemas deben sopesar al implementar lecturas en el modelo simplificado de bases de datos distribuidas.

Supongamos que tenemos un almacén de clave-valor distribuido, que consta de un conjunto de réplicas. Se selecciona un líder entre las réplicas, y este es el único nodo que puede aceptar escrituras. Una vez que el líder recibe la solicitud de escritura, escribirá datos en otras réplicas de forma asincrónica. Aunque todas las réplicas reciben las mismas actualizaciones en el mismo orden, se reciben en diferentes momentos.

Tu tarea es idear una estrategia para manejar las solicitudes de lectura, ¿qué debes hacer? Puede leer datos del líder u otras réplicas. Si todas las lecturas pasan por el líder, el rendimiento se convertirá en un cuello de botella y no podrá exceder la cantidad de datos que puede manejar un solo nodo. Si alguna réplica puede atender la solicitud de lectura, entonces el rendimiento se puede mejorar mucho, pero en este caso, el estado del sistema obtenido por los dos clientes (observadores) puede ser inconsistente, porque el líder y la réplica y entre Puede haber retrasos entre copias.

En pocas palabras, necesitamos sopesar los pros y los contras entre la consistencia del sistema tal como lo ve el observador y el rendimiento y la alta disponibilidad del sistema. Para comprender esta relación, necesitamos definir con precisión la coherencia. Podemos referirnos al modelo de consistencia (https://jepsen.io/consistency), que define la vista del estado del sistema que puede experimentar el observador del estado del sistema.

 

Consistencia fuerte

Si las operaciones de escritura y lectura del cliente solo se pueden enviar al líder, parece que cada solicitud se realiza de forma atómica en un momento específico, como si solo hubiera una copia de los datos. No importa cuántas réplicas haya, y no importa cuán retrasada esté cada réplica, siempre que el cliente consulte directamente al líder, desde su punto de vista, solo hay una copia de datos. 

Dado que la solicitud no se atenderá de inmediato y solo un nodo proporciona el servicio, la solicitud debe ejecutarse durante la llamada y el período de finalización. Otra forma de pensar es que una vez completada la solicitud, todos los observadores pueden ver sus efectos secundarios:

Dado que otros participantes pueden ver la solicitud entre la invocación y la finalización de la solicitud, se debe garantizar el rendimiento en tiempo real. Esta garantía tiene un modelo de consistencia teórica llamado consistencia lineal, también conocido como consistencia fuerte. La consistencia lineal es la consistencia más fuerte que el sistema puede proporcionar para una solicitud de un solo objeto.

¿Qué pasa si el cliente envía una solicitud de lectura al líder, pero cuando llega la solicitud, el líder ha sido abolido, pero el servidor que recibió la solicitud cree que sigue siendo el líder, qué debo hacer? Si la solicitud es procesada por el líder anterior, no se puede garantizar la fuerte consistencia del sistema. Para evitar que esto suceda, el líder hipotético primero debe comunicarse con la mayoría de las réplicas para confirmar si sigue siendo el líder. Solo cuando todavía es el líder puede ejecutar la solicitud y enviar la respuesta al cliente. Este proceso aumenta considerablemente el tiempo necesario para la lectura.

 

Consistencia secuencial 

Hasta ahora, hemos discutido la práctica de procesar las lecturas en orden por parte del líder. Pero este enfoque crea un cuello de botella que limita el rendimiento del sistema. Lo más importante es que el líder también debe comunicarse con la mayoría de las réplicas para procesar las lecturas. Para mejorar el rendimiento de lectura, debemos permitir que las réplicas procesen las solicitudes.

Aunque la réplica se quedará atrás del líder, recibe actualizaciones en el mismo orden que el líder. Si el cliente A solo consulta la copia 1 y el cliente B solo consulta la copia 2, los dos clientes ven diferentes estados en diferentes momentos porque las copias no están completamente sincronizadas:

En este modelo de coherencia, para todos los observadores, las operaciones ocurren en el mismo orden, pero cuando los observadores ven los efectos secundarios de las operaciones, este modelo no puede proporcionar ninguna garantía en tiempo real. Este modelo se llama consistencia secuencial. La diferencia entre consistencia secuencial y consistencia lineal es que la primera carece de garantías en tiempo real.

Una aplicación simple de este modelo es un sistema productor / consumidor sincronizado con la cola: el nodo productor es responsable de escribir en la cola y el consumidor es responsable de leer. Los productores y los consumidores ven el mismo orden de artículos en la cola, pero los consumidores se quedan atrás de los productores.

 

Consistencia final

Aunque logramos mejorar el rendimiento de lectura, tuvimos que anclar el cliente a una copia. ¿Qué debemos hacer si falla la copia? Para mejorar la disponibilidad del almacenamiento, podemos permitir que los clientes consulten cualquier copia. Sin embargo, en términos de coherencia, este paso requiere un precio elevado. Suponga que hay dos copias 1 y 2, donde la copia 2 está detrás de la copia 1. Si el cliente consulta la copia 1 inmediatamente después de consultar la copia 2, verá el estado anterior, lo que puede resultar muy confuso. La única garantía que tiene el cliente es que si la escritura del sistema se detiene, todas las copias eventualmente convergerán al estado final. Este modelo de consistencia se llama consistencia eventual.

Es muy difícil construir aplicaciones sobre un almacenamiento de datos eventualmente consistente porque su comportamiento es diferente al que está acostumbrado a escribir aplicaciones de un solo subproceso. Cualquier pequeño error puede extenderse gradualmente y es difícil de depurar y reproducir. Sin embargo, no todas las aplicaciones requieren consistencia lineal, por lo que la consistencia eventual también tiene algún uso. Debe tomar decisiones acertadas y considerar cuidadosamente si las garantías proporcionadas por su almacenamiento de datos pueden satisfacer las necesidades de su aplicación. Si desea registrar el número de visitas al sitio web, la consistencia final será su primera opción, porque no importa si el número devuelto por la lectura está algo desactualizado. Pero para los sistemas de pago, una coherencia sólida es absolutamente indispensable.

 

Teorema de PACELC

Además de los modelos presentados en este artículo, existen muchos modelos relacionados con la coherencia. Pero la idea básica detrás de esto es inseparable: cuanto más fuerte sea la garantía de consistencia, mayor será el tiempo de espera para una sola operación y menor será la disponibilidad de almacenamiento en caso de falla. Esta relación también se conoce como el teorema PACELC: al realizar particiones de red (P) en un sistema informático distribuido, debemos realizar entre disponibilidad (Disponibilidad, A) y consistencia (Consistencia, C) Elija, de lo contrario (Else o E) incluso si el sistema no tiene particiones, debemos elegir entre latencia (Latencia o L) y consistencia (Consistencia o C).

Si cree que este artículo es útil para usted, le puede gustar y seguirlo para respaldarlo, o puede seguir mi cuenta pública. Hay más artículos técnicos sobre productos secos e información relacionada para compartir, ¡todos aprenden y progresan juntos!

 

Supongo que te gusta

Origin blog.csdn.net/weixin_50205273/article/details/108597609
Recomendado
Clasificación