Tema representativo de entrevista

Entrevista de diseño de sistemas: ¿Cómo diseñarías un servicio seguro de elección de líder?

Diseño de sistemasDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Varios workers sin estado deben tener exactamente una instancia ejecutando un trabajo de liquidación programado a la vez. Diseña un servicio de elección de líder que cubra leases, renovación, fencing tokens, failover, particiones y observabilidad.

Planteamiento y contexto

Varios workers sin estado deben tener exactamente una instancia ejecutando un trabajo de liquidación programado a la vez. Los workers pueden fallar, reiniciarse, pausarse o quedar particionados, y el sistema no debe permitir que dos workers escriban durante un período prolongado. Diseña una elección de líder con un coordinador, lease, renovación, fencing, failover y límites operativos. El núcleo es la coordinación segura de un único escritor, no simplemente un mutex.

Qué está evaluando el entrevistador

Definir seguridad (safety) y vivacidad (liveness)

Safety significa que el recurso acepta como máximo a un líder por término (term); liveness significa que un candidato en buen estado finalmente toma el control después de confirmarse que el lease anterior ha expirado. Una partición minoritaria no puede anunciar un nuevo líder solo para preservar la disponibilidad.

Elegir un coordinador con semántica de consenso

El registro de líder necesita compare-and-set linealizable, leases y semántica de watch, como etcd. Un TTL de Redis o un reloj local por sí solos no pueden demostrar que un líder obsoleto es incapaz de escribir.

Evitar escrituras obsoletas (stale writes)

Después de que expira un lease, el proceso antiguo puede recuperarse y continuar. Cada escritura posterior (downstream) debe llevar un fencing token monótonamente creciente, y el recurso debe rechazar tokens más antiguos para evitar daños por split-brain.

Preguntas para aclarar primero

  • ¿Puede el trabajo ejecutarse dos veces, o el downstream debe aceptar estrictamente una única ejecución serializada?
  • ¿La elección es global, por tenant, por shard o por trabajo?
  • ¿Qué tiempo de failover y qué ventana de pausa son aceptables?
  • ¿Cuántos dominios de falla del coordinador y qué quorum/copias de seguridad están disponibles?
  • ¿Pueden los recursos downstream validar un fencing token y recuperarse de forma idempotente?
  • ¿Se requieren eventos de watch, historial de auditoría, alertas y transferencia manual?

Una respuesta de 30 segundos

“Primero definiría el alcance de la elección y el presupuesto de fallas, luego almacenaría un registro de líder con lease en un coordinador linealizable respaldado por consenso. Los candidatos compiten con una actualización transaccional create-or-compare; el ganador obtiene un término de fencing más alto y renueva dentro del TTL. El fallo de renovación detiene el nuevo trabajo y las escrituras. Cada escritura downstream valida el término, por lo que un líder obsoleto recuperado no puede escribir. Los watches solo aceleran un nuevo intento de CAS. Monitorearía el término, la latencia de renovación, el tiempo de failover, los rechazos de fencing, los duplicados y la salud del quorum”.

Respuesta detallada paso a paso

Definir el registro de término

Almacena election_name, leader_id, lease_id, term, metadatos del candidato y marcas de tiempo. El término o fencing token debe incrementarse monótonamente y ser asignado atómicamente por el coordinador, no generado a partir del reloj de un cliente.

Elegir el coordinador y la condición de escritura

Un candidato crea un registro efímero respaldado por un lease; una transacción linealizable puede escribir solo cuando la clave está ausente. Si existe un líder, los candidatos observan (watch) la clave y reintentan. La API de elección de etcd permite a los participantes competir en un único nombre de elección con un solo líder exitoso a la vez.

Renovar y fallar de forma segura (fail closed)

El líder renueva mediante un bucle de keepalive independiente. El tiempo de espera de renovación agotado, la pérdida de conexión, la pausa del proceso o una anomalía en el reloj local lo mueven a suspect, donde deja de aceptar nuevo trabajo y escrituras downstream. No debe seguir trabajando confiadamente mientras esté desconectado del coordinador.

Gestionar la conmutación por error (failover)

Un candidato no puede decidir que el líder anterior está muerto a partir de su TTL local. Debe observar la expiración o eliminación del lease confirmada por el coordinador y luego competir con un CAS. El tiempo de failover es la suma del TTL, la detección y los retrasos de programación, por lo que se debe establecer un límite con margen para el jitter.

Agregar un fencing token

El nuevo líder obtiene un término más alto y lo adjunta a actualizaciones de bases de datos, mensajes o solicitudes a APIs externas. Un recurso almacena el token aceptado más alto y rechaza uno inferior. Esto bloquea escrituras peligrosas incluso cuando un proceso antiguo no se ha detenido.

Gestionar particiones y split brain

Una partición minoritaria no puede emitir nuevos términos. Un candidato que no pueda alcanzar el quorum del coordinador debe detenerse o permanecer en modo de solo lectura. Después de reconectarse, un líder antiguo debe volver a leer el término actual y competir nuevamente en lugar de confiar en el estado en caché.

Pseudocódigo

~~~text campaign(): lease = coordinator.grant(ttl) result = coordinator.txn(key absent -> put(candidate, lease, next_term)) if result.succeeded: token = result.term keepalive(lease) runwithfencing(token) else: watch(key)

onkeepalivefailureorexpiry: stopnewwork() stopdownstreamwrites() ~~~

Complejidad, recuperación y observabilidad

Cada elección y renovación implica viajes de ida y vuelta (round trips) al coordinador; más candidatos agregan carga de watch y reintentos, por lo que se debe usar retroceso exponencial (exponential backoff) con jitter. Registra el líder actual, el término, el RTT de renovación, las expiraciones de lease, la duración de la elección, los rechazos de fencing, los trabajos duplicados y la salud del quorum para reconstruir las transiciones de términos.

MecanismoQué resuelveQué sigue siendo necesario
CAS linealizableEvita dos ganadoresQuorum del coordinador
Keepalive de leaseDetecta fallas en los procesosManejo de pausas y particiones
Fencing tokenRechaza escrituras obsoletasValidación downstream duradera
Watch y backoffAcelera el failover y reduce la cargaNo puede reemplazar la prueba de seguridad

Respuesta modelo

“Almacenaría un registro de líder con lease en un coordinador respaldado por consenso con transacciones linealizables. Los candidatos compiten creando el registro solo si está ausente; el ganador recibe un término monótonamente creciente y lo renueva dentro de un TTL. Si la renovación falla, detiene inmediatamente los nuevos trabajos y las escrituras downstream. Cada escritura en base de datos, mensaje o llamada externa lleva el fencing token, y el recurso rechaza un token inferior a su valor aceptado más alto, por lo que un líder antiguo pausado o particionado no puede continuar escribiendo. Una minoría no puede emitir un nuevo término, mientras que watch solo reduce el retraso de la elección. Monitorearía el RTT de renovación, los términos, la duración del failover, los rechazos de fencing, los trabajos duplicados y el quorum, con un interruptor de apagado manual (kill switch)”.

Errores comunes

Usar solo un TTL de Redis

La expiración de un lease y la observación de la expiración por parte de un cliente no son lo mismo. El retraso de la red y las pausas pueden hacer que dos clientes crean que pueden trabajar. Utiliza coordinación linealizable junto con fencing downstream.

Tratar un lease como protección de escritura

Un lease ayuda a detectar fallas, pero no puede detener un proceso antiguo de forma instantánea. Sin validación de tokens, el líder obsoleto puede sobrescribir el resultado del nuevo líder.

Generar términos a partir de la hora local

Los relojes pueden desviarse, saltar o pausarse. El coordinador debe asignar y persistir los términos de forma atómica.

Forzar la toma de posesión durante una partición

Una minoría no puede confirmar el estado del líder anterior. Forzar la toma de posesión genera split-brain; un diseño seguro acepta una breve pérdida de disponibilidad.

Permitir que los eventos de watch decidan la seguridad

Los watches pueden retrasarse, perderse o reconectarse. Deben activar una relectura y un CAS, no reemplazar las lecturas y escrituras linealizables.

Omitir la idempotencia del trabajo

Una elección correcta no evita duplicados tras caídas o reenvíos de mensajes. Los trabajos necesitan claves de idempotencia, registros de progreso o transacciones reejecutables.

Preguntas de seguimiento y respuestas

¿En qué se diferencia la elección de líder de un bloqueo distribuido (distributed lock)?

Un lock protege una sección crítica; la elección mantiene un rol de coordinador de larga duración con términos, renovación, watches, fencing y failover. Pueden compartir un coordinador, pero su superficie de seguridad es más amplia.

¿Cómo se debe elegir el TTL?

Debe cubrir el RTT de renovación normal, pausas de GC o del planificador, jitter de red y el SLO de failover. Un TTL corto causa inestabilidad (churn); un TTL largo retrasa la toma de posesión. Calibra con inyección de fallas.

¿Por qué el recurso debe verificar el fencing token?

El coordinador no puede detener instantáneamente cada proceso obsoleto. El rechazo del lado del recurso bloquea escrituras peligrosas mientras ese proceso sigue activo.

¿Qué sucede cuando un clúster de etcd pierde el quorum?

No puede confirmar un nuevo término o estado de lease; el líder actual debe detener las escrituras después de que no pueda renovar. Los candidatos compiten nuevamente después de que regrese el quorum.

¿Cómo se gestiona una pausa prolongada del líder?

La renovación falla durante la pausa y un nuevo candidato puede tomar el control. Cuando el proceso antiguo se reanuda, su token antiguo es rechazado y debe unirse nuevamente a la elección.

¿Cómo se realizan pruebas contra el split-brain?

Inyecta pausas en los procesos, particiones, saltos de reloj y fallas del coordinador. Verifica que solo se acepte un token por término para las escrituras, e inspecciona la duración del failover y los registros de rechazo.

Fuentes públicas

Preguntas relacionadas

Herramienta de entrevista relacionada

Usa Resolver para una respuesta de diseño de sistemas

Aclara primero los requisitos y luego avanza a través de la escala, la arquitectura, la elección de componentes y las compensaciones (trade-offs).

Ver la herramienta