¿La informática distribuida siempre sigue el modelo maestro esclavo?

No. Publicado originalmente en / dev / null: Weblog

Hay dos enfoques muy diferentes para el software distribuido, que puedo resumir como tradicional y orgánico. En un sistema distribuido tradicional, cada servidor, cada proceso es una unidad aislada, como un organismo unicelular. Existe como una unidad independiente que debe valerse por sí misma dentro de su entorno y siempre debe asumir lo peor, porque es la última, probablemente la única, línea de defensa para las responsabilidades que conlleva. Por ejemplo, debe suponer que la falta de comunicación con otra parte del sistema distribuido da como resultado condiciones indeterminables, como transacciones dudosas. Como resultado, debe consolidar esas condiciones indeterminadas en su propia condición, probablemente evitando que continúe el procesamiento. Uno esperaría esto en cualquier sistema de compromiso de dos fases responsable de los resultados deterministas, cuando el sistema experimenta un resultado desconocido en cualquier rama de transacción.

Los sistemas tradicionales utilizan la “recuperación” para lograr resultados deterministas incluso cuando los servidores fallan. La medición de la probabilidad de falla se conoce como MTBF, o tiempo medio (promedio) entre fallas. Sin embargo, lo más importante es el MTTR, o el tiempo medio de recuperación. En un sistema tradicional, el resultado de una rama de transacción en duda no está disponible hasta que el servidor en el que existía la rama se recupere por completo.

El agrupamiento es un enfoque comprobado para resolver tales dilemas al reducir significativamente, casi hasta el punto de eliminar, el tiempo de recuperación. El enfoque de agrupación se hizo popular primero en las arquitecturas de mainframe, y finalmente se expandió a los sistemas UNIX de rango medio. La redundancia del servidor con “interconexiones de agrupamiento” dedicadas permitió que un segundo servidor en espera permaneciera en el paso de bloqueo con el servidor primario, lo que permitió que el segundo servidor asumiera de inmediato las responsabilidades del servidor primario en caso de que el servidor primario fallara.

Hoy, lo que llamamos “agrupamiento” es significativamente diferente, aunque está destinado a lograr el mismo resultado. Por ejemplo, en arquitecturas modernas como los servidores de aplicaciones Java EE, la agrupación se refiere a interconexiones de muy alto nivel, como los sockets TCP / IP, que permiten que los servidores permanezcan en el paso de bloqueo virtual y que un servidor detecte la falla de otro servidor . Conceptualmente, la agrupación permite manejar las fallas sin recuperación, al tener copias redundantes del estado (como un registro de transacciones) que de otro modo tendrían que recuperarse.

Los grupos de hardware de dos servidores y las implementaciones de agrupación de software más modernas son el origen de lo que yo llamo “sistemas orgánicos”, que representan organismos multicelulares diseñados para sobrevivir a la pérdida de células individuales. En otras palabras, un sistema distribuido ya no es una colección de organismos independientes, sino que es un organismo compuesto por cualquier número de servidores que pueden continuar procesando, sin pérdida de datos o transacciones, incluso cuando se produce un fallo del servidor.

Esto requiere un ajuste fundamental en los supuestos detrás de los sistemas distribuidos. En particular, en un sistema distribuido tradicional, la pérdida de comunicación con un servidor en particular haría que todos los demás servidores que se comunicaban con ese servidor esperaran la recuperación de las responsabilidades de ese servidor, ya sea por migración del servidor, conmutación por error del servicio o reparación real ( por ejemplo, reiniciar) de ese servidor.

Por otro lado, en el caso de un sistema orgánico, el organismo siempre está preparado para la muerte de cualquier célula, y nunca depende de la supervivencia de ninguna célula en particular. En dicho sistema, si un servidor en particular muere, todas sus responsabilidades pueden ser manejadas por otros servidores similares, y todas las transacciones en vuelo pueden ser redirigidas desde el servidor muerto a esos otros servidores. Para lograr esto, cada cambio de estado y cada transacción en vuelo debe realizarse en al menos dos servidores, tal como sucede en las implementaciones de hardware en clúster bien conocidas. Sin embargo, la diferencia es que un sistema orgánico no se limita a solo dos servidores, y puede organizarse como una malla de servidores cada vez más resistente, donde la falla de cualquier servidor tiene un efecto cada vez más pequeño en cada servidor como el número de servidores aumenta.

La “recuperación” ya no es el mecanismo principal para restablecer la disponibilidad del sistema cuando falla un servidor. En cambio, los desafíos técnicos son la detección rápida de fallas del servidor y la necesidad de aislar el servidor fallido del sistema distribuido general. Intentaré explicar estos dos desafíos en detalle y por qué son tan fundamentales para el funcionamiento correcto y continuo de un sistema orgánico.

Primero, cuando un servidor falla, es bastante improbable que haya predicho su propia desaparición, y como servidor fallido, también es poco probable que pueda comunicar su propia condición fallida. Por lo tanto, la responsabilidad de la detección de fallas del servidor recae en el organismo mismo, que está compuesto por todos los servidores sobrevivientes. Los algoritmos para determinar la falla del servidor se conocen como “algoritmos de detección de muerte”, y generalmente usan una combinación de indicaciones de error y estadísticas para determinar la falla del servidor más allá de una duda razonable. Cuando se determina que un servidor ha fallado, los otros servidores asumen las responsabilidades que tenía el servidor fallido y el procesamiento de esas responsabilidades continúa sin pérdida de datos o transacciones en vuelo.

Un problema grave, conocido como el “síndrome del cerebro dividido”, ocurre cuando el servidor fallido puede no ser consciente de su propia caída, y puede intentar continuar el procesamiento después de que los otros servidores hayan determinado que falló. Esta es la función del aislamiento, lo que significa que el organismo es plenamente consciente de la falla del servidor y aísla ese servidor fallado del resto del organismo. Esto logra dos cosas: Primero, evita que el servidor fallido corrompa el estado del sistema, porque el sistema es el organismo y el organismo es el sistema. En segundo lugar, proporciona al servidor fallido un signo inequívoco de que (el servidor fallido) ha sido aislado del organismo. Dado que el organismo es dinámico, crece y se reduce según sea necesario, el servidor fallido puede volver a unirse al organismo, pero solo puede volver a unirse una vez que entiende que falló, y una vez que acepta unirse sin suposiciones preexistentes, solo como si fuera un nuevo servidor.

Cuando los recursos externos, como una base de datos, también se ven afectados por el procesamiento del organismo, el aislamiento también debe evitar que un servidor fallido afecte esos recursos. Para lograr esto, un servidor fallido debe respetar su estado aislado, y lo hace mediante el uso de un quórum. Un quórum es el tamaño mínimo definido para un organismo, que podría definirse como un número absoluto de servidores, como el número mínimo de servidores necesarios para proporcionar una calidad de servicio o capacidad particular, o como un porcentaje del tamaño reciente del organismo (antes de que el servidor estuviera aislado de él). Cuando un servidor está aislado del organismo, puede formar su propio organismo unicelular (compuesto solo de sí mismo), o incluso puede formar un pequeño organismo multicelular en algunos escenarios de cerebro dividido. En cualquier caso, su incapacidad para lograr el quórum hará que restrinja sus efectos sobre los recursos externos, asegurando así que los servidores fallidos no causen daños al estado del organismo sobreviviente ni a los recursos externos de los que depende y afecta el organismo sobreviviente.

(Se utiliza una lógica de quórum y continuación más compleja para la conmutación por error de centros de datos completos, en la que un cerebro dividido podría permitir que cualquier centro de datos proporcione su propio quórum, aunque solo un centro de datos debe continuar procesándose).

En resumen, la falla de un servidor ya no es una condición excepcional, y no afecta ni a la disponibilidad del sistema general ni al estado de los datos y las transacciones que administra el sistema general. Por lo tanto, una aplicación aún puede tener que lidiar con el potencial de falla, pero no con la falla de un servidor en particular. En cambio, una aplicación debe tratar con el fracaso para lograr el quórum; en otras palabras, una aplicación debe lidiar con el hecho de que está en el servidor que falló y, a cambio, ya no tiene que preocuparse por la falla de algún otro servidor.

Hay varias consideraciones adicionales que deben abordarse. En primer lugar, un sistema distribuido no puede mantener su disponibilidad en caso de una falla completa de la red; Esto se puede solucionar eliminando puntos únicos de falla en la infraestructura de la red. En segundo lugar, un sistema distribuido no puede mantener su disponibilidad si todos los servidores fallan a la vez, lo que puede suceder si los servidores pierden energía; Esto también puede abordarse mediante el uso de baterías de respaldo, generadores y sistemas de energía redundantes. Sin embargo, las aplicaciones deben construirse con una comprensión de ambos riesgos, y esto lleva al último objetivo de un sistema orgánico: la capacidad de recuperación.

En el caso de una falla del servidor en un sistema tradicional, cada servidor era su propio organismo unicelular, y cada servidor tenía que poder recuperarse, por ejemplo, utilizando un registro de transacciones. En el caso de un sistema orgánico, el organismo también debe poder recuperarse. Por lo general, logra la recuperación al confiar en el almacenamiento recuperable a largo plazo, como el que proporcionan los sistemas de bases de datos relacionales (RDBMS) para actuar como su sistema de registro. La capacidad de recuperación se logra volviendo a cargar el estado del sistema desde su almacenamiento recuperable, y utilizando la finalización de la recuperación como un requisito previo para que el organismo esté disponible para procesar nuevas solicitudes.

No. Trabajé en AFS en la década de 1980 y uno de los componentes distribuidos clave (la base de datos de volumen) usó una base de datos distribuida replicada llamada Ubik. Si tuviera instancias de N Ubik, siempre que tuviera la mayoría de las instancias disponibles, la base de datos avanzaría. No había “maestro” en el modelo. AFS no es único en este aspecto, ni siquiera es el primero en el que trabajé, pero su implementación fue elegante y lo suficientemente sólida como para resolver un problema real para un sistema distribuido real.

Es posible que desee leer más sobre Paxos, que es un enfoque general para resolver de manera confiable los problemas de sistemas distribuidos frente a fallas de un subconjunto arbitrario de participantes. No es el único enfoque del problema, pero es un enfoque bien entendido.

Esta es un área de actividad actual también. Por ejemplo, puede encontrar el trabajo de consenso en Cornell perspicaz.