Video Summary and Transcription
La charla de hoy discute estrategias de optimización de microservicios para sistemas distribuidos, centrándose específicamente en la implementación de consistencia casual para garantizar la sincronización de datos. Los relojes vectoriales se utilizan comúnmente para rastrear la relación casual entre eventos de escritura en sistemas distribuidos. La consistencia casual permite operaciones concurrentes e independientes sin sincronización, maximizando el paralelismo y la utilización de recursos del sistema. Permite una escalabilidad efectiva, mejor latencia y tolerancia a fallos en sistemas distribuidos a través de la coordinación, resiliencia, reconfiguración, recuperación y replicación de datos.
1. Microservices Optimization Strategies
Hola, espectadores. Hoy hablaré sobre las estrategias de optimización de microservicios para sistemas distribuidos. La consistencia casual es crucial para garantizar la sincronización de datos en múltiples servidores. La implementación de algoritmos de consistencia casual puede mejorar el rendimiento del sistema. Un ejemplo del mundo real es Google Docs, donde varios usuarios pueden editar simultáneamente un documento. Las ediciones de los usuarios se envían a los servidores correspondientes, asegurando la consistencia casual.
Hola, espectadores. Soy Santosh. Actualmente trabajo en PyTance como líder de ingeniería en el área de la Bahía de San Francisco. Hoy hablaré sobre las estrategias de optimización de microservicios para el alto rendimiento y la resistencia de estos sistemas distribuidos. Así que hoy daré algunos ejemplos e intentaré explicar con esos ejemplos que están muy relacionados con todos nosotros en nuestro uso diario. Entonces, ¿qué son estos sistemas distribuidos o sistemas a gran escala? Puedo dar algunos ejemplos como Google Docs o algunos sistemas de reserva como reservas de vuelos o películas, donde muchos de nosotros hacemos solicitudes concurrentes, intentamos editar los documentos y Google Docs en paralelo. ¿Y qué se debe considerar? ¿Qué estrategias de optimización se deben considerar cuando construimos tales sistemas? Entonces, primero y ante todo, entremos en esto. Así que, consistencia casual. Ahora, a menudo hablamos de consistencia en sistemas distribuidos, donde no tenemos solo un servidor backend en los sistemas distribuidos. Tienes múltiples sistemas coordinando entre sí, digamos, las escrituras van a un sistema y las lecturas van a otro sistema. Y quieres que los datos entre el servidor de escritura y el servidor de lectura estén sincronizados. O tienes múltiples nodos ubicados geográficamente, uno en EE. UU., otro en, digamos, India o Europa, y los usuarios realizan algunas solicitudes de reserva. Y en última instancia, acceden a la misma base de datos. Están tratando de reservar el último asiento de un avión y el avión, todos intentan acceder al mismo asiento, las solicitudes llegan a diferentes servidores. Pero estos servidores necesitan coordinarse de alguna manera. Nuestros datos deben ser consistentes en estos servidores de alguna manera, de modo que brinden servicios de manera perfecta a todos los usuarios.
Entonces, la consistencia es cuando tienes diferentes servidores atendiendo las solicitudes de varios usuarios, quieres que los datos sean los mismos o consistentes en todos estos servidores. Y ahora, en eso, hay algo llamado consistencia casual. Y si como arquitecto de software podemos abordar esto, realmente podemos incorporar la consistencia casual o implementar algoritmos de consistencia casual en tus sistemas distribuidos backend que realmente pueden mejorar el rendimiento de tu sistema. Ahora, hablemos de un caso de uso. Entonces, es un caso de uso muy común, como puedes ver aquí, un Google Doc, ¿verdad? Como ejemplo del mundo real, la consistencia casual se puede ver en una aplicación de edición colaborativa como esta. En Google Docs, varios usuarios pueden editar simultáneamente un documento. Las ediciones de cada usuario se envían a sus servidores respectivos. Como puedes ver aquí, solicitud de escritura, el usuario 1 intenta escribir una oración en el documento y el usuario 2 también hace lo mismo, realiza la escritura. Y hay varios usuarios que intentan leer como los usuarios 3 y 4. Entonces, aquí, lo importante a tener en cuenta es que la escritura realizada por el usuario 1 y las escrituras realizadas por el usuario 2 están relacionadas. ¿Cómo están relacionadas? Como el usuario 1 escribe una oración 1 en el documento y el usuario 2 está escribiendo la oración 2 después de leer el documento, como puedes ver los pasos 2 y 3 en morado. Entonces, la actividad de escritura del usuario 1 y del usuario 2 dependen entre sí, eso significa que la oración 2 escrita por el usuario 2 depende del usuario 1. Entonces, cuando eso significa que en el mundo distribuido lo llamamos casual, relacionado casualmente, relación casual. Entonces, ahora si el usuario 3 y 4, intentan solicitar o intentar leer los documentos que se comparten con ellos, como puedes ver el paso número 4 por leer.
2. Implementando Consistencia Casual
Primero, el orden de las ediciones en un documento colaborativo es crucial. La consistencia casual garantiza que las ediciones más recientes aparezcan después de las anteriores para una experiencia de edición fluida. Sin consistencia casual, los usuarios pueden ver diferentes versiones del documento en diferentes dispositivos. Incorporar consistencia casual asegura una vista consistente del historial del documento y preserva las relaciones entre las ediciones. Coordinar los nodos en un sistema distribuido es necesario para lograr consistencia casual.
del usuario 3 y 4, amarillo y azul, obtienen la respuesta. Primero obtienen la oración 1, porque esa es la que escribió el usuario 1. Y luego, cuando hacen una segunda lectura como paso número 5, obtienen la oración 2, porque esa es la oración escrita por el usuario 2 en esa secuencia. Entonces, primero, deben leer la oración 1 y luego deben leer la oración 2 en ese orden particular. Entonces, ¿por qué? Porque, como puedes pensar, cuando estás usando comúnmente el documento de Google y varias personas lo están editando, no quieres ver las ediciones más nuevas primero, sino que quieres ver las ediciones más antiguas primero. Entonces, porque estos son eventos dependientes. Esto significa que la oración del usuario b siempre aparecerá después de la oración del usuario a, independientemente del orden en que las ediciones sean recibidas por el servidor backend o por los otros dispositivos de los usuarios. Entonces, sin consistencia casual, ¿verdad? Eso significa que necesitamos identificar en el servidor backend que estos dos eventos o estas dos transacciones de escritura son dependientes entre sí y se mantienen de esa manera en el sistema distribuido, para que cada vez que se realicen operaciones de lectura por otros usuarios como los usuarios 3 y 4, se mantenga ese orden. Sin esa consistencia casual, los usuarios podrían ver diferentes versiones del documento con ediciones que aparecen en diferentes órdenes en diferentes dispositivos. Esto podría llevar a mucha confusión y dificultar la colaboración efectiva de los usuarios. Entonces, la consistencia casual es una estrategia crítica de optimización que debe incorporarse para garantizar que todos los usuarios tengan una vista consistente del historial del documento, preservando las relaciones casuales entre las ediciones y proporcionando una experiencia de edición fluida. Ahora, profundicemos un poco en esto. Como acabamos de discutir, hay operaciones de escritura que llegan a los nodos o servidores backend 1 y 2, y luego tienes los nodos 3 y 4 donde llegan las lecturas, y debe haber alguna forma en que todos estos nodos deben coordinarse, ¿verdad? Porque no puedes tener los datos de lectura en los nodos 3 y 4 sin
3. Logrando Consistencia Casual con Relojes Vectoriales
Esta replicación también puede ser asíncrona. En los sistemas distribuidos, se debe implementar lógica para definir y mantener la relación casual entre los eventos de escritura, incluso después de la replicación. Los relojes vectoriales se utilizan comúnmente para rastrear esta relación, con cada nodo manteniendo un vector de relojes lógicos.
los nodos 1 y 2 realizando algún tipo de replicación. Esta replicación también puede ser asíncrona, ¿verdad? Entonces, cuando las escrituras de los nodos 1 y 2 llegan y luego los data deben sincronizarse o coordinarse a través de algún mensaje o cualquier protocolo y la replicación puede ocurrir a través de muchas topologías, ¿verdad? Topología de malla asíncrona, anillo o hay muchas cosas y multi-líder, líder único, todos esos conceptos son nuevamente vastos y no queremos cubrir esto. Entonces, debe haber una forma en los sistemas distribuidos del backend entre todos los nodos donde la lógica debe ejecutarse de tal manera que la relación casual, la relación casual entre esos eventos de escritura esté definida y ese orden se mantenga incluso durante, incluso después de la replicación para que las lecturas, cuando lleguen a los nodos 3 y 4, aparezcan en la forma correcta. Entonces, ¿cómo se logra esta consistencia casual, verdad? Como dije debe haber algún programa o alguna lógica que se deba escribir en el servidor del backend. Entonces, esa lógica se llama relojes vectoriales. Esa es solo una forma de implementarlo. Los relojes vectoriales son una técnica comúnmente utilizada para rastrear la relación casual en los sistemas distribuidos. Cada nodo mantiene algo llamado reloj vectorial. Es como una clase con una estructura de datos como un mapa hash que contiene el vector de todos los relojes lógicos como una marca de tiempo. Ocurrió un evento de escritura.
4. Comprendiendo la Consistencia Casual y los Relojes Vectoriales
Cuando un nodo genera una operación de escritura, incrementa su reloj lógico e lo incluye con el mensaje o los datos enviados a otros nodos. Esto asegura que los eventos dependan entre sí y se mantenga la consistencia casual. La consistencia casual se logra al mantener la relación de orden entre los eventos, como se ilustra en el ejemplo de usuario 1 escribiendo el contenido A, usuario 2 escribiendo el contenido B después de leer A, y usuario 3 leyendo A seguido de B.
marca de tiempo 1. Ocurrió el evento de escritura 2, marca de tiempo 2. De esa manera. Entonces, cuando un nodo genera un evento como una operación de escritura, incrementa su propio reloj lógico que incrementa como un número único y luego lo coloca en el mapa. Y cuando un nodo envía un mensaje o replica data a otro nodo, incluye su reloj vectorial actual con un mensaje o data. Y al recibir un mensaje o data, un nodo actualiza su propio vector. Entonces, los dos nodos o múltiples nodos interactúan entre sí a través de una función llamada merge y los relojes vectoriales están sincronizados asegurando o diciendo que estos dos eventos dependen realmente de cada uno o que existe una relación casual, lo que significa que se debe mantener o debe ocurrir esta consistencia casual en este sistema distribuido. Entonces, lo que acabo de describir es esto. Entonces, la consistencia casual no es más que, como puedes ver, déjame explicar esta imagen aquí. Entonces, P1, P2, P3 y P4 puedes considerarlos como nodos o los nodos en el sistema distribuido del backend. Entonces, el usuario 1 ha escrito el contenido A. Luego, el usuario 2 usando el procesador 2 ha escrito el contenido B después de leer el contenido A. Y luego el usuario 3 intenta leer y sin embargo, el usuario 3 lee primero A y luego B, no B y A como acabamos de describir, debe haber esa relación de orden y es por eso que se mantiene la consistencia casual si el orden se mantiene.
5. Logrando un Alto Rendimiento con Consistencia Casual
Si los eventos no están relacionados casualmente, las escrituras concurrentes pueden ocurrir en cualquier orden. La consistencia casual permite que las operaciones concurrentes no relacionadas procedan sin coordinación, maximizando el paralelismo y la utilización de recursos del sistema. Solo las operaciones casualmente dependientes necesitan coordinación para mantener el orden casual, reduciendo la sobrecarga. La consistencia casual prioriza preservar las relaciones casuales entre eventos, en lugar de imponer un orden global estricto.
y se lee A primero y luego B. Entonces, y si los eventos no están relacionados casualmente como se muestra en el segundo diagrama aquí abajo, las dos escrituras concurrentes no están relacionadas casualmente. Es decir, el usuario 1 ha escrito A, el usuario 2 ha escrito B y cuando hay una lectura puede ser en cualquier orden, como usuario A, B si no están relacionados, entonces lo que como el contenido A, B cuando el procesador 3 lo lee, puede leer A primero o B primero. Aquí en P3 y P4 están leyendo A primero y luego B, y P4 está leyendo B primero y luego A. Esa es la diferencia entre la consistencia casual y la consistencia no casual en operaciones concurrentes. Ahora, profundizando en cómo se garantiza un alto rendimiento con esta consistencia casual, obviamente son estas cosas que mencioné aquí. Primero y ante todo está la concurrencia. Entonces, la consistencia casual permite que las operaciones concurrentes que no están relacionadas procedan sin coordinación ni sincronización. No todas las operaciones están relacionadas. Entonces, ¿qué sucede si no están relacionadas, como operaciones concurrentes que acabo de describir? Esto permite que múltiples procesos o nodos realicen operaciones independientes de manera concurrente, maximizando el paralelismo y utilizando los recursos del sistema de manera más efectiva. Como en el ejemplo anterior de un sistema con consistencia casual, en el segundo diagrama de abajo se puede ver que las escrituras de P1 y P2 son independientes. Entonces, en ese caso, se puede dejar que la concurrencia se encargue y reducir la sobrecarga de coordinación en la consistencia casual. Solo las operaciones casualmente dependientes necesitan ser coordinadas y sincronizadas para mantener un orden casual, mientras que las operaciones que son independientes o concurrentes entre sí pueden proceder sin coordinación, reduciendo la sobrecarga asociada con el bloqueo, la espera o la sincronización. Y luego, por supuesto, comunicación optimizada porque la consistencia casual se enfoca en preservar las relaciones casuales entre
6. Estrategias de Optimización de Sistemas Distribuidos
La escalabilidad se garantiza al permitir operaciones concurrentes e independientes sin sincronización. La consistencia casual permite una escalabilidad efectiva al agregar más nodos o recursos. Mejor latencia y tolerancia a fallos. Los algoritmos conscientes aseguran coordinación y resiliencia en sistemas distribuidos. Los nodos colaboran a través del envío de mensajes y acuerdan valores comunes. Se abordan los fallos de los nodos y los fallos bizantinos. La reconfiguración, recuperación y replicación de datos garantizan la tolerancia a fallos y la resiliencia.
En lugar de imponer un orden global estricto a los eventos, no hay ningún orden. Y luego, se garantiza la escalabilidad. Al permitir operaciones concurrentes e independientes para proceder sin sincronización, la consistencia casual permite que estos sistemas se escalen de manera más efectiva. ¿Cómo? Porque los sistemas pueden agregar más nodos o recursos para manejar una carga de trabajo creciente sin introducir cuellos de botella o puntos de contención asociados con cualquier coordinación centralizada. Es lo mismo que la falta de coordinación centralizada para cosas concurrentes que no están relacionadas casualmente también puede mejorar la escalabilidad. Luego, la latencia, por supuesto, la mejor latencia cuando ocurren cosas en paralelo. Y la tolerancia a fallos, cómo la consistencia casual proporciona un marco flexible y resistente para manejar fallos y mantener la disponibilidad del sistema. Las operaciones independientes pueden continuar ejecutándose incluso durante la presencia de fallos parciales o particiones de red, lo que permite que el sistema tolere fallos y se recupere sin sacrificar el rendimiento. Ahora eso es todo acerca de la consistencia casual y el segundo aspecto de la optimización de microservicios es algo llamado algoritmos conscientes. Entonces, ahora esto logra resiliencia. Ahora hablemos de qué son los algoritmos conscientes y qué es consciente en primer lugar. Entonces, si acabo de mencionar cómo los nodos del sistema distribuido interactúan entre sí, ya sea para replicar los datos entre los nodos o cuando los nodos necesitan interactuar entre sí. Antes, al comienzo de esta presentación, estaba hablando sobre los sistemas de reserva, donde, por ejemplo, la reserva de películas o de vuelos, las personas tienden a competir o reservar un punto común, como el mismo asiento. Entonces, en ese caso, debe haber coordinación entre todos los nodos en el backend y qué sucede si hay algunos fallos durante esa coordinación o el envío de mensajes entre los nodos. Entonces, durante esos fallos, incluso durante esos fallos, no queremos que el sistema, queremos que el sistema backend funcione de la misma manera que si no hubiera fallos. Eso se llama consciente, lo que significa que todos los nodos deben tener conciencia de cómo van a coordinar o, por ejemplo, si el líder está muerto o un nodo líder no está funcionando o ha ocurrido una falla de red, aún queremos que los resultados se recuperen, el procesamiento se realice y luego se proporcione al usuario para que el usuario no se vea afectado. Por ejemplo, si hay una falla de nodo y durante la coordinación entre los nodos y debe haber un acceso a una área crítica, como se necesita exclusión mutua o, por ejemplo, un mensaje debe ser transmitido a los otros nodos desde un nodo que falló. Entonces, en todos los casos de falla, no queremos que el sistema se vea afectado, eso está garantizado por los algoritmos conscientes porque si algo falla, los algoritmos conscientes aseguran que se elija un nuevo nodo como líder y las cosas como la exclusión mutua y la transmisión de mensajes se garantizan, y también el algoritmo en algunos algoritmos asegura que se realice la comunicación correcta entre los nodos. Entonces, sí, como dije, varios nodos están conectados entre sí y colaboran entre sí a través del envío de mensajes y durante la computación necesitan ponerse de acuerdo sobre una cosa común o un valor común para coordinar entre múltiples procesos. Esto se llama conciencia distribuida y ¿por qué se requiere, verdad? Como expliqué antes, en un sistema distribuido puede suceder que múltiples nodos estén procesando grandes cálculos de manera distribuida y necesiten conocer los resultados de cada uno de los otros nodos para mantenerlos actualizados sobre todo el sistema. En tal situación, los nodos deben ponerse de acuerdo sobre un valor común incluso en presencia de fallos o particiones de red. Ese es todo el punto aquí y mencioné dos tipos de fallos aquí, uno es el fallo de bloqueo cuando un nodo no responde a otros nodos del sistema debido a alguna falla de hardware o software. Este es un caso de uso muy común, un problema común en los sistemas distribuidos y se puede manejar fácilmente ignorando la existencia de los nodos, es decir, la lógica puede asumir que no existe tal nodo cuando existe ese problema. Es simple de manejar, pero el fallo bizantino es el fallo complicado, es como uno o más nodos no están bloqueados, pero el nodo se comporta anormalmente y envía un mensaje diferente a diferentes pares, como se puede ver en diferentes colores allí, debido a algún ataque interno o externo en ese nodo. Manejar esta situación es complicado, como el fallo bizantino se trata de un nodo defectuoso que envía diferentes mensajes a diferentes pares. Entonces, los algoritmos conscientes abordarían este tipo de problemas y esta es una de las mejores estrategias o consideraciones de optimización para el mundo de los microservicios. Ahora, tomemos un ejemplo de coordinación aquí y un caso de uso. Entonces, nuevamente, como mencioné anteriormente, booking.com o cuando se realiza una reserva de avión, a menudo hay varios algoritmos para lograr la conciencia y los sistemas distribuidos. Estaré demostrando este algoritmo llamado modelo basado en votación y cómo los nodos se coordinan entre sí en este modelo basado en votación. Y como dije, los algoritmos son como PACSOURCE, RAFT, ZAB, PBFT, que he dado en la siguiente diapositiva. Entonces, lo que sucede en esto es que un usuario, como se puede ver, 1, 2, 3, 4, está tratando de reservar el mismo asiento en un avión o un teatro y todas esas solicitudes respectivas van a sus nodos correspondientes, digamos nodo 1, 2, 3, 4, y cada nodo internamente tendrá un líder seguidor o algo así implementado internamente, pero no queremos entrar en esos detalles. Entonces, lo que sucede después del paso dos significa que debe haber una forma de que todos estos nodos se coordinen porque estos nodos están distribuidos geográficamente. Supongamos que los usuarios están tratando de reservar desde Estados Unidos, Europa y Argentina, y todos estos nodos deben coordinarse de tal manera que solo una persona se reserve y esa decisión generalmente la toman los algoritmos conscientes y lo que sucede es que en el paso número tres se selecciona el nodo líder, el algoritmo selecciona el nodo líder y luego el nodo líder envía un mensaje, como un nodo propone un valor, como el ID del cliente. Este cliente obtiene el asiento y otros nodos deben votar por ese valor, por lo que en este caso, el nodo líder, nodo 1, en el paso 3 envía el ID del cliente propuesto a los nodos 3, 4 y 2, y luego todos los demás nodos envían una respuesta diciendo que sí, votamos qué ID de cliente debe obtener la reserva y después de que se realicen las votaciones, el sistema toma la votación mayoritaria, el líder toma una votación mayoritaria y toma una decisión. Entonces, esto se llama enfoque determinista y una vez que se determina el paso número cinco, el nodo líder, nodo 1, se comunica con todos los demás nodos diciendo que este es el cliente que se ha seleccionado. Así es como funciona este modelo de votación y hay muchos otros algoritmos que ayudan a la coordinación y este es un concepto muy importante para tratar de tener la arquitectura de microservicios más optimizada en el backend cuando se diseñan los sistemas. Y ahora, cómo garantizan estos algoritmos la llamada resiliencia de la que estoy hablando, ¿verdad? Digamos, ¿qué es la resiliencia? Entonces, la resiliencia se puede categorizar en muchas cosas, como la tolerancia a fallos, por ejemplo, estos algoritmos están diseñados para tolerar fallos como fallas de nodo, pérdida de mensajes o particiones de red y todo eso. Por ejemplo, un algoritmo PACSOURCE o un algoritmo RAFT, siempre y cuando la mayoría de los nodos funcionen correctamente y puedan comunicarse entre sí, el sistema puede avanzar y alcanzar la conciencia sobre los valores propuestos. Y la segunda forma de garantizar la resiliencia es, por ejemplo, la elección del líder, como dije antes, los algoritmos como RAFT o el protocolo de transmisión atómica de los servidores de zoo, permiten mecanismos de elección del líder para asegurar que solo un nodo actúe como líder en cualquier momento dado, este líder es responsable de coordinar el proceso de acuerdo y garantizar que todos los nodos converjan en el mismo estado. Luego, está el acuerdo basado en quórum, por lo que estos algoritmos nuevamente típicamente requieren un quórum de nodos para ponerse de acuerdo sobre un valor, como la votación, antes de que se considere comprometido, asegurando que un número suficiente de nodos participe en el proceso de acuerdo. Estos algoritmos, algunos algoritmos, evitan que el sistema alcance un estado inconsistente o tome decisiones incorrectas, como nuevamente PACS también son algoritmos de tolerancia a fallas bizantinas prácticas, los valores se consideran comprometidos una vez que han sido aceptados por la mayoría de los nodos y esa garantía la hacen estos algoritmos. Luego, por supuesto, la replicación de datos, que mencioné anteriormente, muchos algoritmos conscientes implican copiar los datos de un sistema a otro o dentro de un nodo si tienes, por ejemplo, líder seguidor, la copia siempre se realiza de forma asíncrona como parte del algoritmo y también maneja este aspecto de replicación para garantizar la tolerancia a fallos y la resiliencia al mantener múltiples copias de datos, los sistemas distribuidos continúan funcionando correctamente incluso si algunos nodos fallan o no están disponibles. Y sí, por último, la reconfiguración y la recuperación, los algoritmos conscientes proporcionan mecanismos para, en caso de una falla de nodo y particiones de red, por ejemplo, los algoritmos PACS o RAFT admiten la reconfiguración dinámica, lo que permite que los nodos se unan o abandonen el sistema de manera dinámica sin interrumpir su funcionamiento en absoluto. De esta manera, estos algoritmos aseguran que el sistema pueda recuperarse de fallos o particiones al reelegir líderes, resincronizar datos y restaurar la consistencia entre los nodos. Entonces, sí, estos son los dos aspectos principales de los sistemas distribuidos o las estrategias de optimización de los microservicios en la arquitectura de los sistemas distribuidos para lograr un mayor rendimiento y resiliencia. Gracias, muchas gracias por ver, así que espero con ansias otra sesión para compartir más información. Gracias
Comments