menuTicketing

Principio de funcionamiento


Adquisición y liberación del bloqueo

Cuando el cliente adquiere (A) una clave, el servidor responde de una de estas tres formas.

Estado de la claveAcción del servidorRespuesta
No registradaRegistro inmediato (expiración = ahora + lease), emisión de tokenA + token + key
Registrada + expiradaRenovación (ahora + lease), emisión de nuevo tokenA + token + key
Registrada + vigente (en uso)Se registra en la cola de espera, respuesta pendienteA al liberar/expirar, T si se supera wait
  • La liberación se procesa de forma justa mediante FIFO. Cuando el poseedor libera (R), el traspaso se hace directamente a quien está al frente de la cola — pasa de inmediato con un nuevo token, sin reconcursar.
  • lease es la red de seguridad. Aunque el cliente muera o se olvide de liberar, una vez transcurrido el tiempo de lease el servidor puede recuperar automáticamente la clave y entregarla al siguiente en espera. Por eso, independientemente del flujo normal de liberación, siempre conviene fijar el lease con margen suficiente, pero a un valor que no bloquee demasiado tiempo en caso de muerte del cliente.
  • wait es el límite de espera para la adquisición. Si es 0, la espera es infinita; en cualquier otro caso, si no se obtiene el bloqueo dentro de ese tiempo (en segundos), el servidor desiste y responde con T (timeout) — termina sin conceder el bloqueo, así que no hay fugas de bloqueo.

Token de fencing

El token incluido en la respuesta A es un u64 monótonamente creciente para ese grant. En cada adquisición se emite un valor mayor que cualquier token anterior. Incluso si ocurre un failover, el nodo que pasa a ser activo continúa desde un valor mayor que el token máximo replicado que recibió (sucesión) — de modo que el token sigue creciendo en todo el clúster.

Si el recurso que se quiere proteger (cuenta, archivo, pedido, etc.) valida únicamente si "el token que tengo ahora es mayor que el último token visto", puede rechazar el acceso de un cliente que se despierta tarde tras la expiración del lease con un token bajo ya invalidado. Gracias a esto, se puede mantener la seguridad aunque el servidor de bloqueo no sea perfectamente consistente en todo momento.

Comportamiento del cliente

Los clientes oficiales se comportan en común de la siguiente manera (para los detalles de la API por lenguaje, consulta Librerías).

  • Mantiene una conexión persistente por dirección gestionada en segundo plano. Si solo se indica una dirección, mantiene internamente dos conexiones con ese mismo nodo, de modo que aunque una de ellas se corte momentáneamente, el servicio no se interrumpe.
  • Elige la conexión por round-robin. Los nodos con la conexión caída se excluyen automáticamente, y se reintenta la reconexión en segundo plano cada 3 segundos.
  • Las solicitudes se procesan en pipeline. Se puede enviar la siguiente solicitud sin esperar la respuesta, y el orden de las respuestas puede diferir del orden de las solicitudes — el cliente distingue a qué solicitud corresponde cada respuesta mediante el par (op, key) que se devuelve como eco. Si hay varias solicitudes con el mismo par (op, key), se emparejan en el orden en que se enviaron.
  • Si la conexión se corta durante un intento de adquisición, se cambia automáticamente a la siguiente conexión. Solo se notifica un error si, tras intentarlo tantas veces como conexiones registradas hay, no queda ninguna conexión utilizable.
  • La liberación se reintenta durante 5 segundos con un intervalo de 200 ms — para que, aunque la conexión esté caída justo en el momento de liberar, el bloqueo no permanezca retenido en el servidor (al final lo recupera el lease, pero esto permite entregarlo antes a otro que esté esperando).

Clúster — sin interrupciones basado en prioridad

  • El orden de la lista peers es la prioridad de promoción (el primero tiene la mayor prioridad). Entre los nodos vivos, el de mayor prioridad se convierte en el activo, y el resto queda como standby recibiendo ese estado por replicación en tiempo real.
  • Las solicitudes del cliente solo las procesa el activo. El cliente que se conecta a un standby es redirigido (M) a la dirección del activo y se traslada allí.
  • Ante un fallo o reinicio del activo → el standby se promueve y toma el relevo.
  • En un cierre controlado (graceful) (Ctrl+C), el activo primero le pasa la promoción a su sucesor (handoff) y luego redirige a los clientes, minimizando el vacío sin activo.
  • Degradación automática: si por una partición de red u otra causa dos nodos llegan a ser activos al mismo tiempo, el de menor prioridad detecta al otro y se retira por sí mismo a standby (evitando un split-brain permanente).

Este método de promoción no se basa en quórum (voto mayoritario). Por eso no importa si el número de servidores es par o impar, y el servicio se mantiene mientras quede al menos uno vivo.

N.º de servidoresSin interrupcionesFallos simultáneos toleradosNotas
1El más rápido. Corte breve al reiniciar
21Configuración mínima sin interrupciones. Suficiente en la mayoría de los casos
32Se mantiene la redundancia incluso con un servidor en mantenimiento
4+N−1Solo aumenta el costo de propagación — no recomendado

Consideraciones sobre la consistencia

Como la promoción basada en prioridad no es un consenso, en el instante de una partición de red ambos lados pueden llegar a ser activos brevemente a la vez, y por la naturaleza de la replicación asíncrona, en el momento del failover se puede perder algún grant. Es decir, la exclusión mutua no está garantizada al 100 % durante los períodos de failover/partición. Si se necesita una garantía fuerte, implemente que el recurso protegido valide el token de fencing descrito antes — rechazando tokens antiguos (menores) se mantiene la seguridad aunque el servidor de bloqueo no sea perfectamente consistente.