En este módulo, exploraremos cómo gestionar fallos y realizar la recuperación en sistemas distribuidos. La capacidad de un sistema distribuido para manejar fallos y recuperarse de ellos es crucial para garantizar la disponibilidad y la fiabilidad del sistema. A continuación, desglosaremos los conceptos clave, ejemplos prácticos y ejercicios para reforzar el aprendizaje.

Conceptos Clave

  1. Tipos de Fallos en Sistemas Distribuidos

  • Fallos de Red: Pérdida de conectividad entre nodos.
  • Fallos de Hardware: Fallos en servidores, discos duros, etc.
  • Fallos de Software: Errores en el código, bugs, etc.
  • Fallos Humanos: Errores cometidos por los operadores del sistema.

  1. Tolerancia a Fallos

  • Redundancia: Uso de componentes duplicados para asegurar que el sistema siga funcionando en caso de fallo.
  • Replicación: Copiar datos o servicios en múltiples nodos para asegurar la disponibilidad.
  • Failover: Cambio automático a un sistema de respaldo cuando el sistema principal falla.

  1. Estrategias de Recuperación

  • Reinicio Automático: Reiniciar automáticamente los servicios fallidos.
  • Rollbacks: Revertir el sistema a un estado anterior conocido y estable.
  • Checkpoints: Guardar el estado del sistema en puntos específicos para facilitar la recuperación.

Ejemplo Práctico: Implementación de Failover

Descripción

Vamos a implementar un sencillo mecanismo de failover en un sistema distribuido utilizando un servicio de base de datos replicado.

Paso a Paso

  1. Configuración de la Base de Datos Principal y de Respaldo

    • Configura dos instancias de base de datos: una principal y una de respaldo.
    • Asegúrate de que la base de datos de respaldo esté replicando los datos de la principal.
  2. Detección de Fallos

    • Implementa un mecanismo para detectar si la base de datos principal ha fallado. Esto puede ser un simple ping o una consulta de estado.
  3. Conmutación por Error (Failover)

    • Si se detecta un fallo en la base de datos principal, redirige las consultas a la base de datos de respaldo.

Código de Ejemplo (Python)

import time
import requests

PRIMARY_DB_URL = "http://primary-db.example.com"
BACKUP_DB_URL = "http://backup-db.example.com"

def check_db_status(db_url):
    try:
        response = requests.get(f"{db_url}/status")
        return response.status_code == 200
    except requests.ConnectionError:
        return False

def get_db_connection():
    if check_db_status(PRIMARY_DB_URL):
        return PRIMARY_DB_URL
    else:
        return BACKUP_DB_URL

def main():
    while True:
        db_url = get_db_connection()
        print(f"Using database at: {db_url}")
        # Aquí iría el código para interactuar con la base de datos
        time.sleep(10)

if __name__ == "__main__":
    main()

Explicación del Código

  • check_db_status: Verifica si la base de datos está disponible.
  • get_db_connection: Devuelve la URL de la base de datos principal si está disponible, de lo contrario, devuelve la URL de la base de datos de respaldo.
  • main: Un bucle que continuamente verifica y utiliza la base de datos disponible.

Ejercicio Práctico

Ejercicio 1: Implementación de Checkpoints

  1. Objetivo: Implementar un sistema de checkpoints para una aplicación distribuida.
  2. Descripción: Cada 5 minutos, guarda el estado actual de la aplicación en un archivo. En caso de fallo, la aplicación debe poder restaurar el estado desde el último checkpoint.
  3. Pistas:
    • Usa la biblioteca pickle de Python para serializar y deserializar el estado de la aplicación.
    • Implementa una función para guardar el estado y otra para cargarlo.

Solución Propuesta

import pickle
import time

STATE_FILE = "checkpoint.pkl"

def save_state(state):
    with open(STATE_FILE, 'wb') as f:
        pickle.dump(state, f)

def load_state():
    try:
        with open(STATE_FILE, 'rb') as f:
            return pickle.load(f)
    except FileNotFoundError:
        return None

def main():
    state = load_state() or {"counter": 0}
    print(f"Starting with state: {state}")

    while True:
        state["counter"] += 1
        print(f"Current state: {state}")
        save_state(state)
        time.sleep(300)  # Espera 5 minutos

if __name__ == "__main__":
    main()

Explicación del Código

  • save_state: Guarda el estado de la aplicación en un archivo.
  • load_state: Carga el estado de la aplicación desde un archivo.
  • main: Incrementa un contador en el estado cada 5 minutos y guarda el estado actualizado.

Conclusión

En esta sección, hemos aprendido sobre los diferentes tipos de fallos en sistemas distribuidos y las estrategias para manejarlos y recuperarse de ellos. Implementamos un ejemplo práctico de failover y un ejercicio de checkpoints para reforzar los conceptos. La gestión de fallos y la recuperación son esenciales para mantener la disponibilidad y la fiabilidad en sistemas distribuidos. En el siguiente módulo, exploraremos la automatización y orquestación en sistemas distribuidos para mejorar aún más la resiliencia y eficiencia del sistema.

© Copyright 2024. Todos los derechos reservados