Sistemas distribuidos: replicación (IV)

Edu Salguero
4 min readMar 24, 2018

--

Cuarto artículo de la serie de cinco publicaciones breves relacionadas con los sistemas distribuidos.

Photo by Sharon McCutcheon

Replicación

La replicación es la clave para proporcionar alta disponibilidad y tolerancia a fallos en sistemas distribuidos. La replicación proporciona una mejora en los servicios mediante:

  • Mejora de rendimiento.
  • Incremento en la disponibilidad.
  • Tolerancia a fallos.

Podemos definir replicación como el conjunto de técnicas que tratan de proporcionar mayor rendimiento, disponibilidad y escalabilidad mediante el mantenimiento de copias de un recurso.

Existen varios criterios de corrección para objetos replicados. Los sistemas más estrictamente correctos son linealizables y esta propiedad se denomina linealizabilidad (linearizability). Un servicio de objetos compartidos replicados es linealizable si para cualquier ejecución existe algún entrelazamiento de las series de operaciones emprendidas por cada cliente que satisfaga:

  • La secuencia entrelazada de operaciones cumple la especificación de una (única) copia correcta de los objetos.
  • El orden de las operaciones del entrelazamiento es consistente con los tiempos reales en los cuales ocurrieron las operaciones en la ejecución real.

Existen varios modelos o técnicas de replicación:

Replicación pasiva (primary-backup)

En el modelo de replicación pasiva para la tolerancia a fallos nos encontramos con un nodo primario y un conjunto de nodos secundarios. En este caso el cliente envía la petición al nodo primario el cual eventualmente actualiza su copia y envía la actualización de manera síncrona a los secundarios. Estos, a su vez, envían un mensaje de ACK al primario cuando han actualizado su copia. En este modelo los nodos secundarios no deben manejar la concurrencia ya que esta es gestionada por el primario.

En este caso es necesario gestionar las altas y bajas de manera consistente, también recuperar el estado de un servidor cuando se sume al grupo al recuperarse de un fallo. Si tiene lugar un fallo en el nodo primario se debe promover a un secundario mediante un algoritmo de elección.

Existen variantes de replicación pasiva en la cual se relaja la consistencia para reducir la carga del nodo primario, permitiendo que los secundarios puedan recibir de los clientes las operaciones de solo lectura.

Replicación activa

En contraposición con la replicación pasiva o replicación primario-backup en la replicación activa la petición de un cliente se envía a todas las réplicas las cuales la tratan de forma concurrente. En este caso el cliente se sincroniza con la primera respuesta que obtiene y desecha las posteriores.

Por una parte la replicación activa permite reducir la latencia al permitir el acceso a varias réplicas, por otra hay que tener en cuenta el alto coste de soportar orden total y el hecho de que las actualizaciones se procesen en todas las réplicas. La replicación activa permite tolerar los fallos Bizantinos y logra una consistencia secuencial pero por el contrario no alcanza la linealizabilidad (linearizability).

A mayores de las técnicas indicadas existen otros modos de replicación para servicios de alta disponibilidad. Un ejemplo es el “protocolo gossip”.

Protocolo gossip

Este framework se fundamenta en la replicación de datos cerca de los puntos en donde los grupos de clientes los necesitan. Un servicio gossip provee dos tipos de operaciones:

  • queries: operaciones de solo lectura.
  • updates: modifican (pero no leen) el estado.

En la arquitectura gossip los font-end (FE) envían “queries” y “updates” a un “replica manager” (RM) seleccionado, el cual está disponible y proporciona un tiempo de respuesta razonable. El framework también garantiza que cada cliente obtiene un servicio con integridad en el tiempo y relaja la misma entre las réplicas.

La arquitectura gossip gestiona la replicación mediante el intercambio de mensajes “gossip” de forma periódica para transmitir las actualizaciones que han tenido desde los clientes.

Para resolver la consistencia, conflictos de versiones y propagar estados u operaciones entre réplicas (en sistemas en el que ha tenido lugar una partición) el protocolo utiliza relojes vectoriales (vectores de marcas de tiempo). De forma más concreta el proceso para la detección y resolución de conflictos es el siguiente:

  1. Un front end envía una solicitud de actualización a uno o más RM.
  2. Cada solicitud de actualización contiene una especificación de la actualización, una marca de tiempo y un identificador único generado por el front end.
  3. Finalmente, cuando un RM recibe una solicitud de actualización comprueba que esa solicitud no haya sido ya procesada mirando el identificador de la operación.

Un servicio basado en gossip mejora la escalabilidad convirtiendo a la mayor parte de las réplicas a réplicas de solo lectura, sobretodo cuando el ratio de actualizaciones/lecturas es pequeño. En estas circunstancias las réplicas de solo lectura deben estar situadas cerca de los grupos de clientes y las actualizaciones deben ser recibidas por un grupo relativamente pequeño de RMs. Bajo estas circunstancias el tráfico se reduce ya que las réplicas de solo lectura no propagan mensajes “gossip” y los vectores de tiempo solo necesitan contener entradas para las réplicas actualizables.

Una aclaración, con solo lectura lo que se quiere decir es que las replicas se hacen actualizables por otras réplicas pero no directamente por los front ends.

Fuentes

--

--