Introducción

En los sistemas distribuidos, el consenso es un problema fundamental que implica llegar a un acuerdo común entre múltiples nodos o procesos. Este acuerdo es crucial para garantizar la consistencia y la coordinación en un entorno donde los nodos pueden fallar o comunicarse de manera imperfecta. Los algoritmos de consenso son esenciales para operaciones como la replicación de datos, la coordinación de transacciones y la gestión de configuraciones.

Conceptos Clave

  1. Consenso: Proceso mediante el cual un grupo de nodos en un sistema distribuido acuerda un valor común.
  2. Nodo: Cada una de las unidades de procesamiento en un sistema distribuido.
  3. Fallo Bizantino: Tipo de fallo en el que un nodo puede comportarse de manera arbitraria, incluyendo comportamientos maliciosos.
  4. Tolerancia a Fallos: Capacidad del sistema para continuar operando correctamente en presencia de fallos.

Algoritmos de Consenso Populares

  1. Paxos

Descripción

Paxos es uno de los algoritmos de consenso más conocidos y utilizados. Fue propuesto por Leslie Lamport y es conocido por su robustez y capacidad para tolerar fallos.

Componentes

  • Proposer: Propone valores.
  • Acceptor: Acepta o rechaza propuestas.
  • Learner: Aprende el valor acordado.

Fases

  1. Fase de Preparación: El proposer envía una solicitud de preparación a los acceptors.
  2. Fase de Promesa: Los acceptors responden con una promesa de no aceptar propuestas anteriores.
  3. Fase de Aceptación: El proposer envía una propuesta con un valor.
  4. Fase de Confirmación: Los acceptors aceptan la propuesta y notifican a los learners.

Ejemplo de Código

class Paxos:
    def __init__(self):
        self.promises = {}
        self.accepted = {}

    def prepare(self, proposer_id, proposal_id):
        if proposal_id not in self.promises or self.promises[proposal_id] < proposer_id:
            self.promises[proposal_id] = proposer_id
            return True
        return False

    def accept(self, proposer_id, proposal_id, value):
        if self.prepare(proposer_id, proposal_id):
            self.accepted[proposal_id] = value
            return True
        return False

  1. Raft

Descripción

Raft es un algoritmo de consenso diseñado para ser más comprensible que Paxos. Fue desarrollado por Diego Ongaro y John Ousterhout.

Componentes

  • Leader: Coordina el consenso.
  • Follower: Sigue las instrucciones del líder.
  • Candidate: Nodo que intenta convertirse en líder.

Fases

  1. Elección de Líder: Los nodos eligen un líder.
  2. Replicación de Log: El líder replica entradas de log a los followers.
  3. Compromiso de Entradas: Las entradas de log se comprometen una vez que la mayoría de los nodos las han replicado.

Ejemplo de Código

class Raft:
    def __init__(self):
        self.state = 'follower'
        self.votes = 0
        self.log = []

    def request_vote(self, candidate_id):
        if self.state == 'follower':
            self.state = 'candidate'
            self.votes += 1
            return True
        return False

    def append_entries(self, leader_id, entries):
        if self.state == 'follower':
            self.log.extend(entries)
            return True
        return False

  1. Algoritmo de Consenso Bizantino (PBFT)

Descripción

Practical Byzantine Fault Tolerance (PBFT) es un algoritmo diseñado para tolerar fallos bizantinos. Es utilizado en sistemas donde la seguridad es crítica, como en blockchains.

Componentes

  • Primary: Nodo principal que coordina el consenso.
  • Replica: Nodos que replican el estado.

Fases

  1. Pre-Preparación: El primary envía una solicitud de pre-preparación.
  2. Preparación: Las replicas envían mensajes de preparación.
  3. Compromiso: Las replicas envían mensajes de compromiso.

Ejemplo de Código

class PBFT:
    def __init__(self):
        self.prepared = {}
        self.committed = {}

    def pre_prepare(self, primary_id, request_id):
        self.prepared[request_id] = primary_id
        return True

    def prepare(self, replica_id, request_id):
        if request_id in self.prepared:
            self.committed[request_id] = replica_id
            return True
        return False

Ejercicios Prácticos

Ejercicio 1: Implementar Paxos Básico

Implementa un algoritmo Paxos básico que permita a un conjunto de nodos llegar a un consenso sobre un valor propuesto.

Solución

class PaxosNode:
    def __init__(self, node_id):
        self.node_id = node_id
        self.promises = {}
        self.accepted = {}

    def prepare(self, proposal_id):
        if proposal_id not in self.promises or self.promises[proposal_id] < self.node_id:
            self.promises[proposal_id] = self.node_id
            return True
        return False

    def accept(self, proposal_id, value):
        if self.prepare(proposal_id):
            self.accepted[proposal_id] = value
            return True
        return False

# Crear nodos
nodes = [PaxosNode(i) for i in range(5)]

# Proponer un valor
proposal_id = 1
value = "valor_acordado"

# Fase de preparación
for node in nodes:
    node.prepare(proposal_id)

# Fase de aceptación
for node in nodes:
    node.accept(proposal_id, value)

# Verificar consenso
consenso = all(node.accepted.get(proposal_id) == value for node in nodes)
print("Consenso alcanzado:", consenso)

Ejercicio 2: Simular Elección de Líder en Raft

Simula una elección de líder en un sistema Raft con 5 nodos.

Solución

class RaftNode:
    def __init__(self, node_id):
        self.node_id = node_id
        self.state = 'follower'
        self.votes = 0

    def request_vote(self):
        if self.state == 'follower':
            self.state = 'candidate'
            self.votes += 1
            return True
        return False

# Crear nodos
nodes = [RaftNode(i) for i in range(5)]

# Solicitar votos
for node in nodes:
    node.request_vote()

# Contar votos
votos_totales = sum(node.votes for node in nodes)
print("Votos totales:", votos_totales)

Conclusión

Los algoritmos de consenso son esenciales para garantizar la consistencia y la coordinación en sistemas distribuidos. Paxos, Raft y PBFT son algunos de los algoritmos más utilizados, cada uno con sus propias características y aplicaciones. Comprender estos algoritmos y su implementación es crucial para diseñar sistemas distribuidos robustos y eficientes.

En el siguiente módulo, exploraremos la replicación de datos, un concepto estrechamente relacionado con los algoritmos de consenso, ya que la replicación eficiente y consistente de datos depende en gran medida de la capacidad de los nodos para llegar a un consenso.

© Copyright 2024. Todos los derechos reservados