Backends y UX consistentes: ¿Cómo ayudan los nuevos algoritmos?
Serie de artículos
- ¿Por qué debería importarte?
- ¿Qué puede ser malo?
- ¿Cuáles son las barreras para la adopción?
- ¿Cómo ayudan los nuevos algoritmos?
En artículos anteriores, explicamos qué es la coherencia, la diferencia entre coherencia “fuerte” y “eventual” y por qué esta distinción es más importante que nunca para los desarrolladores de aplicaciones modernas. También introdujimos la noción de “impuesto de coherencia”: el tiempo y el esfuerzo extra que un equipo de desarrollo necesita invertir si elige un sistema con una coherencia eventual o garantías de coherencia limitadas.
Varias bases de datos modernos utilizan algoritmos de última generación para eliminar el equilibrio entre coherencia y rendimiento. Por supuesto, no queremos que confíe en nuestra palabra sin una explicación adecuada. Por lo tanto, en este artículo final, profundizamos en los detalles técnicos detrás de algunas de estas bases de datos. Normalmente, la única fuente de información para estos detalles técnicos son los artículos de investigación, por lo que el objetivo de este artículo es explicar estos sistemas en términos más simples. Debido a que estos sistemas son mucho más complejos en la realidad, proporcionaremos los enlaces en el texto en caso de que desee saber más y le guste leer artículos de investigación.
Introducción
En las partes 1 y 2 de esta serie de artículos, explicamos cómo las bases de datos distribuidas utilizan diferentes réplicas para distribuir la carga y/o atender a los usuarios en diferentes regiones. Para resumir aquí, para los nuevos lectores, una réplica es solo una duplicación de sus datos. Y esta duplicación puede residir en la misma ubicación por motivos de redundancia o en otra ubicación para ofrecer latencias más bajas a los usuarios en esas ubicaciones. Tener múltiples réplicas que puedan manejar lecturas y escrituras tiene una gran ventaja, porque la base de datos se vuelve escalable y puede ofrecer una latencia más baja a todos sus usuarios, sin importar dónde se encuentren. Sin embargo, no desea que cada una de las réplicas tenga su propia interpretación de los datos. En lugar de pequeñas diferencias de datos entre cada réplica, lo que desea es una interpretación única de los datos, a lo que a menudo se hace referencia como una única fuente de verdad. Para lograrlo, es necesario tener algún tipo de acuerdo sobre los cambios de datos. Necesitamos un consenso.
Esperando consenso
Cada base de datos distribuida que pretende ser coherente tiene múltiples réplicas que deben coincidir en el resultado de las transacciones. Si se producen actualizaciones de datos contradictorias, estas réplicas deben acordar qué actualización se realiza y cuál no. Esto se llama “consenso”.
Volvamos a nuestro juego para ejemplificar por qué necesitamos consenso. Imagina que al jugador de nuestro juego solo le quedan 3 piezas de oro, pero intenta comprar simultáneamente dos artículos diferentes en dos tiendas diferentes con un presupuesto total mayor que las 3 piezas de oro restantes. Esto implica dos transacciones, una para cada artículo/tienda, que denotamos como t1 y t2. Y supongamos que los propietarios de las tiendas están al otro lado del mundo, por lo que las transacciones se realizan en dos réplicas diferentes. Si se aceptan ambas transacciones, el usuario podrá comprar más de lo que puede pagar. ¿Cómo evitamos que el usuario gaste de más?
Sabemos que estas réplicas necesitan comunicarse para llegar a un acuerdo sobre el resultado final de las dos transacciones. Lo que no sabemos es cuánta comunicación necesitamos. ¿Cuántos mensajes tienen que ir y venir entre la réplica 1 y la réplica 2 para acordar qué transacción tiene prioridad y cuál se cancela?
Como las réplicas en una base de datos distribuida están destinadas a servir a usuarios de diferentes regiones del mundo con baja latencia, están muy separadas por naturaleza. Al colocar duplicados de los datos más cerca de los usuarios finales, estos usuarios pueden leer con latencias más bajas. Sin embargo, cuando se producen escrituras, las réplicas deben enviarse mensajes entre sí para actualizar todos los datos duplicados de manera uniforme, y estos mensajes pueden tardar varias decenas de milisegundos porque están frenados por la velocidad de la luz mientras viajan por el mundo. Está claro que debemos mantener el número de mensajes entre centros de datos lo más pequeño posible para que el usuario final no tenga que esperar a que estas réplicas en todo el mundo lleguen a un consenso.
Durante mucho tiempo se pensó que esto era imposible o poco práctico. Pero hoy en día existen varias tecnologías para mantener bajo el número de viajes de ida y vuelta y llevar la latencia dentro de los límites normales.
La distancia entre Nueva York y París es de 5.839 km. Para que la luz viaje de Nueva York a París y luego regrese tomaría 40 milisegundos.
— Velocidad teórica versus velocidad real
La pregunta más importante que queda por resolver es: “¿Cuántos viajes de ida y vuelta necesitamos para ejecutar transacciones?” La respuesta a esta pregunta depende en gran medida de los algoritmos que se utilicen.
¿Cómo llegar a un acuerdo?
Parece que para lograr un consenso sobre algo, se necesitan al menos cuatro saltos (o dos rondas de comunicación): una ronda para que cada réplica sepa que está a punto de hacer algo, luego una segunda ronda para ejecutar la acción una vez. Todos están de acuerdo en que esta acción se puede ejecutar. Esto es algo llamado confirmación distribuida de dos fases que utiliza casi cualquier base de datos distribuida. Veamos una analogía. Imagina que tienes que acordar con un grupo de personas una buena cita para una fiesta. Podría ser así:
Primero, Polly les pregunta a todos si pueden asistir a una fiesta el lunes; ahora sabe que todos pueden venir a la fiesta. A continuación, debe hacerles saber a todos que la fiesta será el lunes y que la gente reconozca que estará allí.
Son muy similares a las dos fases del compromiso de dos fases. Por supuesto, las bases de datos no coinciden por lo que las fases tienen funciones diferentes. En el caso de un sistema distribuido, las fases se denominan:
- Prepare o solicite comprometerse : asegúrese de que todos conozcan la transacción. En esta fase, las réplicas en una base de datos distribuida almacenan la consulta en algún tipo de lista de tareas pendientes (un registro de transacciones) en el disco para asegurarse de que aún sepan qué hacer si el servidor falla.
- Comprometerse: calcular realmente los resultados y almacenarlos
Por supuesto, como siempre, nunca es tan sencillo. Hay muchos tipos de algoritmos de este tipo. Por ejemplo, hay mejoras de commits de dos fases llamadas Paxos y Raft e incluso muchas variantes de estos ( multi paxos / fast paxos /…). Estas alternativas tienen como objetivo mejorar los problemas de disponibilidad o rendimiento. Para comprender los problemas de disponibilidad, simplemente imagine que Polly está enferma o que el teléfono de Amber se apaga. En el primer caso, no podría continuar su trabajo como coordinadora del partido y en el segundo, a Polly le resultaría temporalmente imposible saber si Amber está de acuerdo con la fecha de la fiesta. Raft y Paxos mejoran esto al exigir que solo la mayoría responda y/o seleccione un nuevo coordinador automáticamente cuando el líder o coordinador caiga. Puede encontrar una buena animación que muestra cómo funciona Raft aquí.
¿De acuerdo en qué?
¿Podemos concluir que cada base de datos distribuida requiere 2 viajes de ida y vuelta para escribir/leer datos? No, la realidad es más compleja que eso. Por un lado, hay muchas optimizaciones posibles y, por el otro, puede haber varias cosas en las que debemos estar de acuerdo.
- Acordar el momento de una transacción
- Acordar si se pueden ejecutar lecturas
El ejemplo más simple que tiene múltiples rondas de confirmación de dos fases son probablemente las transacciones livianas de Cassandra. Primero requieren acuerdos de consenso sobre lecturas y luego consenso sobre escrituras. Si cada mensaje tarda 40 ms en viajar, esto significa que toda la transacción requiere 320 ms o más, dependiendo de los "bloqueos" requeridos, como explicaremos más adelante.
Esto es bastante fácil de entender, pero existen algunos problemas con la implementación ya que Cassandra nunca fue diseñada para ser fuertemente consistente. ¿Eso significa que las bases de datos fuertemente consistentes son aún más lentas? ¡De nada! Las bases de datos distribuidas modernas utilizan una combinación de características interesantes para lograr un mejor rendimiento.
esperando cerraduras
No sólo debemos esperar a que los mensajes lleguen a un acuerdo, sino que casi todas las bases de datos distribuidas también utilizarán "bloqueos". Los bloqueos garantizan que los datos que una transacción va a modificar no sean alterados simultáneamente por otra transacción. Cuando los datos están bloqueados, otras transacciones no pueden modificarlos, lo que significa que estas transacciones tienen que esperar. Por lo tanto, la duración de dicho bloqueo tiene un gran impacto en el rendimiento. Nuevamente, este impacto en el rendimiento depende del algoritmo y las optimizaciones implementadas por la base de datos. Algunas bases de datos mantienen bloqueos por más tiempo que otras y algunas bases de datos no utilizan ningún bloqueo.
Ahora que conocemos suficientes conceptos básicos, profundicemos en los algoritmos.
Algoritmos modernos para el consenso
Ahora sabemos que el consenso y los bloqueos son los principales obstáculos que debemos optimizar. Así que volvamos a la pregunta principal de este artículo: "¿Cómo pueden las nuevas tecnologías reducir estas latencias dentro de límites aceptables?" Comencemos con el primero de estos algoritmos modernos, que generó ideas interesantes para el resto del mundo de las bases de datos.
2010 – Percolador
Percolator es un sistema interno construido sobre BigTable (una de las primeras bases de datos NoSQL creadas por Google) que Google utilizó para realizar actualizaciones incrementales en la velocidad de rastreo de páginas de su índice de búsqueda. El primer artículo sobre Percolator se publicó en 2010, inspirando la primera base de datos distribuida inspirada en él: FoundationDB en 2013. Luego, Apple adquirió FoundationDB para finalmente lanzar una versión estable en 2019, junto con el lanzamiento de un artículo de FoundationDB.
Aunque Percolator permitió a Google acelerar significativamente el rastreo de páginas, no se creó originalmente como una base de datos de propósito general. Más bien pretendía ser un motor de procesamiento incremental rápido y escalable para respaldar el índice de búsqueda de Google. Dado que el índice de búsqueda tenía que ser escalable, muchos cálculos debían realizarse en muchas máquinas al mismo tiempo, lo que requería una base de datos distribuida. Como aprendimos en artículos anteriores, la programación en sistemas distribuidos que almacenan datos puede ser muy compleja y tradicionalmente requería que los desarrolladores pagaran un "impuesto de coherencia" para programar en torno al comportamiento impredecible de la base de datos. Para evitar pagar un impuesto de coherencia tan alto, Google adoptó un modelo de coherencia sólido cuando creó Percolator.
El modelo de coherencia de Percolator no podría existir sin dos ingredientes clave: el control de versiones y Timestamp Oracle.
Ingrediente 1: Versionado
Como mencionamos en artículos anteriores, una fuerte coherencia requiere que acuerdemos un orden global para nuestras transacciones. El control de versiones es uno de los elementos que será crucial para muchos de estos algoritmos, ya que se puede utilizar para la recuperación de fallas, para ayudar a replicar datos y para respaldar un modelo de coherencia llamado "aislamiento de instantáneas".
El control de versiones ayuda en la recuperación de fallas cuando un nodo falla o se desconecta. Cuando el nodo vuelve a estar en línea, gracias a las versiones, puede restaurar fácilmente su estado comenzando en la última instantánea que pudo guardar y luego reproduciendo las transacciones según las versiones en otro nodo. Todo lo que tiene que hacer es preguntar a otro nodo: "Oye, ¿qué ha cambiado desde que me fui?" Sin control de versiones, tendría que copiar todos los datos, lo que habría supuesto una enorme carga para el sistema.
La recuperación de fallas es excelente, pero la mayor ventaja radica en el hecho de que dicho sistema de versiones se puede utilizar para implementar un modelo de coherencia sólido. Si el sistema de versiones mantiene versiones para cada cambio de datos, podemos retroceder en el tiempo y realizar consultas sobre una versión anterior de nuestros datos.
Algunas mentes brillantes descubrieron que esta capacidad de consulta histórica podría usarse para proporcionar un modelo de coherencia llamado "consistencia de instantáneas". La idea de la coherencia de las instantáneas es elegir una versión de los datos al comienzo de la consulta, trabajar con esa versión de los datos durante el resto de la consulta y luego escribir una nueva versión al final de la consulta.
Aquí existe un posible error: durante la ejecución de dicha consulta, otra consulta podría estar escribiendo datos que entren en conflicto con la primera consulta. Por ejemplo, si dos consultas de escritura comienzan con la misma instantánea de una cuenta bancaria con $1000, ambos podrían gastar el dinero ya que no ven las escrituras de la otra consulta. Para evitarlo, se realizará una transacción adicional para ver si los valores de la instantánea cambiaron antes de que cualquiera de las consultas escriba un resultado. Si sucedió algo conflictivo que cambió el valor de la instantánea, la transacción se revierte y debe reiniciarse.
Sin embargo, todavía hay un problema que Percolator debe resolver. Los relojes de diferentes máquinas pueden separarse fácilmente unos cientos de milisegundos. Si los datos de una consulta se dividen en varias máquinas, como en nuestro ejemplo inicial, no puede simplemente pedirles a ambas máquinas que le proporcionen datos en una marca de tiempo determinada, ya que tienen una idea ligeramente diferente de cuál es la hora actual. Es cuestión de milisegundos, pero cuando hay que procesar muchas transacciones, bastan unos pocos milisegundos para pasar de datos correctos a datos defectuosos.
La sincronización horaria nos lleva al segundo ingrediente de Percolator.
Ingrediente 2: El oráculo de la marca de tiempo
La solución de Percolator al problema de sincronización horaria es algo llamado Timestamp Oracle. En lugar de dejar que cada nodo dicte su propio tiempo (lo cual no era lo suficientemente preciso), Percolator utiliza un sistema central que expone una API que le proporciona una marca de tiempo. El nodo en el que vive este sistema es Timestamp Oracle. Cuando conservamos varias versiones de nuestros datos, necesitamos al menos dos marcas de tiempo para cada consulta. Primero, necesitamos una marca de tiempo para consultar una instantánea, que usaremos para leer datos. Luego, al final de la transacción, cuando estemos listos para escribir, necesitamos una segunda marca de tiempo para etiquetar la nueva versión de los datos. Como resultado, Percolator tiene la desventaja de que necesita al menos dos llamadas al Timestamp Oracle, lo que introduce aún más latencia si el Oracle está en otra región de los nodos donde se originaron las llamadas. Cuando a Google se le ocurrió su Distributed Database Spanner, resolvieron este problema.
2012 – llave inglesa
Spanner fue la primera base de datos distribuida globalmente que ofreció una gran coherencia, lo que esencialmente significa que obtienes lecturas de baja latencia sin tener que preocuparte más por posibles errores de la base de datos. Los desarrolladores ya no necesitan invertir trabajo adicional para evitar posibles errores causados por una eventual coherencia. El documento se publicó en 2012 y se lanzó al público en general en 2017 como Spanner Cloud.
Ingrediente 1: Versionado
Google creó Spanner después de su experiencia con Percolator. Dado que el sistema de versiones de Percolator demostró funcionar, lo mantuvieron en el diseño de Spanner. Este sistema de control de versiones brindaba la posibilidad de realizar lecturas muy rápidas (lecturas instantáneas) si estaba dispuesto a renunciar a la coherencia. En ese caso, podría ejecutar consultas y darle a Spanner una antigüedad máxima de los resultados. Por ejemplo: "Por favor, devuelva mi inventario actual lo más rápido posible, pero los datos solo pueden tener 15 segundos de antigüedad". Básicamente, en lugar de abandonar la coherencia, ahora puede elegir para cada consulta qué nivel de coherencia se adapta a su caso de uso.
Ingrediente 2: Tiempo verdadero
Para eliminar la sobrecarga adicional para sincronizar el tiempo entre máquinas, Spanner abandonó Timestamp Oracle en favor de un nuevo concepto llamado TrueTime. En lugar de tener un sistema central que proporcione una vista unificada del tiempo, TrueTime intenta reducir la desviación del reloj entre las propias máquinas. Los ingenieros de Google lograron limitar la desviación del reloj local implementando un protocolo de sincronización horaria basado en GPS y relojes atómicos. Este algoritmo de sincronización les permitió limitar la deriva del reloj dentro de un límite de 7 ms, pero requirió hardware específico que consistía en una combinación de GPS y tecnología de reloj atómico.
Por supuesto, todavía existe una posible desviación del reloj de 7 ms, lo que significa que dos servidores aún podrían interpretar una marca de tiempo como dos instantáneas diferentes. Esto se resuelve con el tercer ingrediente de Spanner: confirmar-esperar.
Ingrediente 3: confirmar-esperar
De hecho, la API TrueTime no devuelve una marca de tiempo, sino un intervalo n en el que es seguro que debe estar la marca de tiempo actual. Una vez que esté listo para comprometerse, simplemente esperará unos milisegundos para hacer frente a la posible deriva que se denomina "espera de confirmación". Esto garantiza que la marca de tiempo que se asignará a la escritura sea una marca de tiempo que haya pasado a todos los nodos. También es la razón por la que ejecutar Spanner en hardware básico no puede ofrecer la misma garantía, ya que el período de espera tendría que ser de unos cientos de milisegundos.
2012 – Calvino
El primer artículo sobre el algoritmo de Calvin se publicó en 2012, a partir de una investigación en Yale. Al igual que los enfoques anteriores, Calvin consta de varios ingredientes. Aunque el control de versiones también forma parte de esto, el resto del enfoque es radicalmente diferente y requiere algunos ingredientes adicionales para funcionar: cálculos deterministas y la separación del ordenamiento del bloqueo. Estos son ingredientes que normalmente no se encuentran en las bases de datos con arquitectura tradicional. Al cambiar la arquitectura y aceptar que las consultas tienen que ser deterministas, Calvin puede reducir a dos el peor número de mensajes entre centros de datos . Esto reduce significativamente la latencia del peor de los casos de las transacciones globales y la sitúa por debajo de 200 ms o, en teoría, incluso por debajo de 100 ms. Por supuesto, para creer que esto es posible, es posible que primero desee saber cómo funciona, así que echemos un vistazo al algoritmo.
Ingrediente 1: Versionado
Al igual que Percolator y Spanner, Calvin se basa en datos versionados. Estas instantáneas en Calvin se utilizan principalmente para garantizar la tolerancia a fallas. Cada nodo almacena diferentes instantáneas que pueden considerarse puntos de control. Un nodo desconectado que vuelve a estar en línea solo necesita tomar la marca de tiempo del último punto de control que ha presenciado y luego pedirle a otro nodo que le informe de todas las transacciones que se produjeron después de ese punto de control.
Ingrediente 2: Cálculos deterministas
Muchos desarrolladores front-end habrán oído hablar del marco frontend Elm que implementa un flujo de trabajo similar a React Redux. Elm tiene una curva de aprendizaje más pronunciada que marcos similares basados en JavaScript porque requiere que aprendas un nuevo idioma. Sin embargo, debido a que el lenguaje es funcional (sin efectos secundarios), Elm permite algunas optimizaciones impresionantes. La clave es que las funciones en Elm abandonan las manipulaciones destructivas para ser deterministas. Puede ejecutar la misma función con la misma entrada dos veces y siempre arrojará el mismo resultado. Debido a que son deterministas, las consultas de Elm ahora pueden decidir de manera más eficiente cómo actualizar las vistas.
Al igual que Elm, Calvin ha renunciado a algo para acelerar los cálculos. En el caso de Calvin, básicamente podemos decir que el resultado de una transacción será el mismo, ya sea que se ejecute en la máquina A o en la Máquina B. Esto puede parecer evidente, pero normalmente las bases de datos no lo garantizan. Recuerde que SQL le permite usar la hora actual o permite algo llamado transacciones interactivas donde la entrada del usuario se puede insertar en medio de una transacción, lo cual podría violar las garantías proporcionadas por Calvin.
Para lograr cálculos deterministas, Calvin (1) necesita sacar cálculos como la hora actual y calcularlos previamente, y (2) no permite transacciones interactivas. Las transacciones interactivas son transacciones en las que un usuario inicia una transacción, lee algunos datos, proporciona información adicional del usuario en el medio y finalmente realiza algunos cálculos adicionales y posiblemente algunas escrituras. Dado que el usuario no es predecible, dicha transacción no es determinista. En esencia, Calvin cambia una comodidad menor (transacciones interactivas) por un gran rendimiento.
Ingrediente 3: Separar el problema del pedido.
Las bases de datos dedican mucho tiempo a negociar bloqueos para que parezca que el sistema se está ejecutando en un orden específico”. Si todo lo que necesita es un pedido, tal vez podamos separar el problema del bloqueo del problema del pedido. Sin embargo, esto significa que sus transacciones deben ser puras.
—Kyle Kingsbury
Separar la preocupación de ordenar transacciones de la ejecución real se ha considerado muchas veces en el mundo de las bases de datos, pero sin mucho éxito. Sin embargo, cuando sus transacciones son deterministas, separar el ordenamiento de los cálculos resulta factible. De hecho, la combinación de cálculos deterministas y la separación del ordenamiento del resto del algoritmo es extremadamente poderosa ya que ayuda a reducir la duración del bloqueo y disminuye en gran medida la comunicación más lenta entre nodos distantes (comunicación entre centros de datos).
Duración de bloqueo más corta
Siempre que se mantienen bloqueos en un dato, significa que otras consultas que utilizan esos datos tienen que esperar. Por lo tanto, un bloqueo más corto da como resultado un mejor rendimiento. A continuación se muestra una imagen que muestra una descripción general del procedimiento de bloqueo en Calvin en comparación con cómo podría hacerlo una base de datos distribuida tradicional. La mayoría de las bases de datos mantendrían un bloqueo de datos hasta que hubiera al menos un consenso sobre qué escribir, mientras que Calvin solo mantendría el bloqueo hasta que todos los nodos estuvieran de acuerdo en el orden. Debido a que los cálculos son deterministas y todos estuvieron de acuerdo en el orden, cada nodo calculará por separado y llegará al mismo resultado final.
Menos comunicación entre nodos distantes.
Además de las ventajas en cuanto a la duración del bloqueo, separar los pedidos del resto del algoritmo también requiere menos comunicación. Como se explicó anteriormente con el ejemplo de Cassandra, una base de datos distribuida generalmente requiere comunicación entre centros de datos en muchas fases de su algoritmo. En el caso de Calvino, el único momento en el que necesitamos estar de acuerdo en algo es en el momento en que determinamos el orden. Con el protocolo Raft, esto se podría hacer en dos saltos, lo que permite lograr latencias inferiores a 100 ms para consultas de lectura y escritura.
Junto con el tiempo de bloqueo reducido, esto también aporta un rendimiento excelente. El artículo original de Calvin también realizó experimentos que muestran que este enfoque supera significativamente los diseños de bases de datos distribuidas tradicionales bajo cargas de trabajo de alta contención. Sus resultados de medio millón de transacciones por segundo en un grupo de máquinas básicas son competitivos con los resultados récord mundiales actuales obtenidos con hardware de gama mucho más alta.
Ejecutar en cualquier hardware
Además de eso, Calvin tiene otra ventaja: ya no requiere hardware específico para obtener tales resultados. Dado que Calvin puede ejecutarse en máquinas básicas, puede ejecutarse en cualquier proveedor de nube.
2014 – El sabor del consenso de FaunaDB
Ingrediente 1: Versionado
FaunaDB tiene su propio protocolo de transacciones distribuidas con algunas similitudes con Calvin. Al igual que los enfoques anteriores, los datos de FaunaDB también están versionados. Dado que el control de versiones no solo es útil para el modelo de coherencia sino que también puede tener valor comercial, FaunaDB ha actualizado este mecanismo a un ciudadano de primera clase que puede ser utilizado por los usuarios finales. Esta característica esencialmente permite consultas que viajan en el tiempo. Los usuarios finales pueden ejecutar una consulta sobre datos históricos para responder preguntas como: "¿Cuál habría sido el resultado de esta consulta hace 20 días?". Esto es útil para recuperar datos que se sobrescribieron accidentalmente, auditar cambios en los datos o simplemente incorporar viajes en el tiempo en las funciones de su aplicación.
Ingrediente 2 y 3: Cálculos deterministas y Separación
Al igual que Calvin, FaunaDB también tiene cálculos deterministas y separa el problema de ordenamiento del resto del algoritmo. Aunque existen similitudes, el cálculo de transacciones en FaunaDB ocurre en una fase diferente a la de Calvin. Cuando Calvin aprovecha la naturaleza determinista para ejecutar la misma transacción varias veces una vez que se establece el orden, FaunaDB calculará solo una vez antes de llegar a un consenso sobre el orden de las transacciones. Lo que nos lleva al cuarto ingrediente.
Ingrediente 4: Cálculo optimista
FaunaDB agrega un cuarto ingrediente que ya hemos visto cuando hablamos sobre el aislamiento de instantáneas: cálculos optimistas en lugar de bloqueo.
FaunaDB no se bloqueará, sino que calculará de manera optimista el resultado de la transacción una vez en el nodo donde se recibió la transacción y luego agregará el resultado y los valores de entrada originales al registro. Donde Calvin habría guardado la consulta que debe ejecutarse en el registro de transacciones, FaunaDB guardará tanto el resultado del cálculo como los valores de entrada originales en el registro. Una vez que haya consenso sobre el orden en el que se deben aplicar los resultados, FaunaDB verificará si los datos de entrada para ese cálculo han cambiado o no (gracias al versionado). Si los valores de entrada han cambiado, la transacción se cancela y se reinicia; si permanecen iguales, los resultados se aplican en todos los nodos sin ningún cálculo adicional.
El algoritmo de FaunaDB tiene ventajas similares a las de Calvin, pero reduce la cantidad de cálculos necesarios en el clúster.
Conclusión
En esta serie, hemos explicado cómo una coherencia sólida puede ayudarle a crear aplicaciones sin errores de forma más eficiente. En este último artículo, explicamos con más detalle cómo las ideas revolucionarias pueden impulsar una nueva generación de bases de datos distribuidas que sean consistentes y eficientes. La conclusión de los artículos anteriores fue: "La coherencia importa". En este artículo final, la conclusión se incluye en lo siguiente:
En un futuro próximo, si lees una frase como:
“Muchas bases de datos NoSQL no ofrecen escrituras atómicas para múltiples documentos y, a cambio, ofrecen un mejor rendimiento. Y si bien la coherencia es otra gran característica de las bases de datos SQL, impide la capacidad de escalar una base de datos en múltiples nodos, por lo que muchas bases de datos NoSQL pierden la coherencia”. – los mayores desafíos de pasar a NoSQL
Tenga en cuenta que los algoritmos modernos permiten que las bases de datos ofrezcan coherencia sin centralización. En este artículo, hemos visto algunos ejemplos de algoritmos y bases de datos que hacen esto. Las bases de datos que se basan en estos algoritmos son una próxima generación de bases de datos que ya no pueden describirse mediante categorías simples como NoSQL, SQL o incluso NewSQL.
Con bases de datos distribuidas en la nube basadas en el protocolo de transacciones de Percolator, Spanner, Calvin y FaunaDB, puede tener bases de datos distribuidas de alto rendimiento que ofrecen modelos de coherencia más sólidos. Esto significa que puede crear aplicaciones con uso intensivo de datos que ofrecen baja latencia sin tener que preocuparse por errores de datos, rendimiento o aprovisionamiento de servicios. En tales sistemas, la coherencia es transparente y usted no tiene que pensar en ello como desarrollador. La próxima vez que elija una base de datos, elija una que sea coherente de forma predeterminada.
Serie de artículos
- ¿Por qué debería importarte?
- ¿Qué puede ser malo?
- ¿Cuáles son las barreras para la adopción?
- ¿Cómo ayudan los nuevos algoritmos?
Deja un comentario