Tema representativo de entrevista

Entrevista de diseño de sistemas: Diseñar un servicio de bloqueo distribuido

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

Pregunta

Diseñe un servicio de bloqueo distribuido desplegado en tres zonas de disponibilidad dentro de una región. Gestiona 100,000 recursos, mantiene 20,000 bloqueos activos y procesa 2,000 adquisiciones por segundo en el pico de carga. El arrendamiento predeterminado es de 30 segundos, los clientes renuevan cada 10 segundos y el objetivo de p99 para una adquisición sin contención es de 200 milisegundos. Explique la API, el modelo de consistencia, los arrendamientos y fencing tokens, la capacidad, las fallas, la equidad (fairness) y la validación.

Problema y alcance

Diseñe un servicio de bloqueo distribuido desplegado en tres zonas de disponibilidad dentro de una región. Gestiona 100,000 recursos bloqueables, normalmente mantiene 20,000 bloqueos activos y maneja 2,000 adquisiciones por segundo en el pico. El arrendamiento predeterminado es de 30 segundos, los clientes renuevan cada 10 segundos y el objetivo de p99 para una adquisición sin contención es de 200 milisegundos. El almacenamiento o servicio protegido puede comparar atómicamente fencing tokens y rechazar solicitudes provenientes de un titular anterior.

La escala, la duración del arrendamiento y la latencia son datos del enunciado para la entrevista, no afirmaciones de rendimiento para etcd, ZooKeeper u otro producto. El alcance incluye bloqueos exclusivos, espera, renovación, liberación, conmutación por error (failover) y observabilidad. Los bloqueos granulares a nivel de fila de base de datos, un coordinador de transacciones completo, la implementación de consenso desde cero y el bloqueo activo-activo entre regiones quedan fuera del diseño principal.

Esta es una pregunta representativa para roles senior de backend, infraestructura y diseño de sistemas. La guía actual de entrevistas para SDE II de Amazon incluye explícitamente el diseño de sistemas y evalúa la practicidad, precisión, eficiencia, confiabilidad, optimización y escalabilidad. El modo de falla central abarca todos estos aspectos: el servicio debe recuperar un bloqueo después de que un cliente falla sin permitir que un cliente antiguo que se reanude más tarde corrompa los datos del nuevo titular.

Qué evalúa el entrevistador

Primero, ¿puede el candidato separar la seguridad de exclusión mutua de la limpieza tras una falla? Un arrendamiento responde cuándo otro titular puede tomar el control después de que el titular actual desaparece. No impide que un cliente que se pausó durante mucho tiempo se reanude y escriba. Un diseño estricto también necesita un fencing token y validación en el recurso protegido.

Segundo, ¿es explícito el límite de consistencia? La adquisición, la renovación y la liberación deben pasar por una única máquina de estados fuertemente consistente. Una partición minoritaria no puede continuar emitiendo bloqueos. Si tres zonas de disponibilidad deciden de forma independiente, una partición de red puede generar dos titulares para el mismo recurso.

Tercero, ¿la planificación de capacidad incluye el tráfico de renovación? Con 20,000 bloqueos activos renovados cada 10 segundos, las renovaciones por sí solas producen unas 2,000 operaciones por segundo. Si el pico también tiene 2,000 adquisiciones por segundo y un número similar de liberaciones, la máquina de estados necesita aproximadamente 6,000 confirmaciones (commits) por segundo, no simplemente la tasa de adquisiciones.

Cuarto, ¿la semántica de fallas llega al nivel de la solicitud? La respuesta debe cubrir una adquisición que se confirma pero cuya respuesta se pierde, un cliente pausado más allá del arrendamiento, un cliente antiguo que libera el bloqueo de un nuevo titular, la pérdida de quórum y tokens monótonos a través de cambios de líder.

Finalmente, ¿sabe el candidato cuándo no usar este servicio? Google Chubby fue concebido para la coordinación de grano grueso. Si una restricción única de base de datos, una actualización condicional, una cola de consumidor único o una clave de idempotencia de negocio ya resuelven el problema, un bloqueo remoto añade otro punto de falla síncrono.

Preguntas de clarificación antes de responder

  • ¿Necesitamos bloqueos exclusivos o de lectura/escritura (reader-writer)? Este diseño comienza con bloqueos exclusivos. Los

bloqueos de lectura/escritura añaden semántica de estado, actualización y hambruna (starvation) que no deben prometerse a la ligera.

  • ¿Puede el recurso protegido validar fencing tokens? Esta consigna asume la comparación atómica y el almacenamiento del último

token. Sin esto, un arrendamiento solo reduce la ventana de conflicto y no puede excluir estrictamente a un cliente zombi.

  • ¿Qué tan equitativa (fair) debe ser la espera? El valor predeterminado es FIFO aproximado. La equidad absoluta reduce la

flexibilidad durante la recuperación y bajo cargas de trabajo variables.

  • ¿Cuánto tiempo puede esperar un cliente? waitTimeout está acotado y es cancelable para que el estado de espera

no crezca indefinidamente.

  • ¿Puede la duración del arrendamiento variar según la carga de trabajo? El valor predeterminado es de 30 segundos con renovación

cada 10 segundos. Los trabajos prolongados pueden solicitar una duración dentro de una política acotada, pero los arrendamientos no se pueden extender sin límite.

  • ¿Se puede reintentar la adquisición automáticamente? Solo un reintento que transporte el mismo requestId estable

es seguro. De lo contrario, una respuesta perdida deja un resultado desconocido.

  • ¿Qué sucede sin quórum? Gana la seguridad: rechazar nuevas adquisiciones y renovaciones. Ninguna partición aislada puede emitir bloqueos.
  • ¿La operación protegida aún debe ser idempotente? Sí. El cercado rechaza una época (epoch) anterior; los reintentos de negocio y los

envíos duplicados aún necesitan una clave de idempotencia de negocio o una transacción.

  • ¿Se requiere bloqueo interregional de baja latencia? El diseño principal es para una sola región entre zonas de disponibilidad. Un

bloqueo estricto entre regiones paga una mayor latencia o pierde disponibilidad durante una partición, y corresponde a una pregunta de seguimiento.

Estructura de respuesta en 30 segundos

“Almacenaría el estado de los bloqueos en una máquina de estados fuertemente consistente replicada en tres zonas de disponibilidad. Cada adquisición, renovación y liberación es confirmada por un quórum. Una adquisición exitosa devuelve un leaseId, una expiración de 30 segundos y un fencingToken monótonamente creciente. El cliente renueva cada 10 segundos y detiene el trabajo cuando la renovación es incierta. Cada operación protegida lleva el token; el recurso almacena la época más alta que ha aceptado y rechaza los tokens más antiguos. El arrendamiento permite un nuevo titular, mientras que el cercado rechaza a un titular antiguo que se reanude. Un requestId deduplicado maneja una adquisición confirmada cuya respuesta se perdió. Los clientes en espera ordenados observan únicamente a su predecesor para evitar estampidas (thundering herds). Veinte mil bloqueos generan unas 2,000 renovaciones por segundo; con la adquisición y liberación, probaría aproximadamente 6,000 confirmaciones de estado por segundo bajo persistencia y failover.”

Análisis detallado paso a paso

Comience con invariantes en lugar de un diagrama de componentes:

  1. Para un recurso, la máquina de estados consistente registra como máximo un leaseId válido a la vez.
  2. Cada bloqueo recién adquirido recibe un fencing token mayor.
  3. El recurso protegido rechaza un token inferior al token más alto que haya aceptado.
  4. Solo una solicitud que coincida con el leaseId actual puede renovar o liberar.
  5. El servicio no crea un bloqueo ni declara exitosa una renovación sin alcanzar el quórum.

Estos invariantes separan “a quién considera el servicio de bloqueo como el titular” de “el trabajo de quién aceptará todavía el recurso”. La máquina de estados decide lo primero; el cercado en el límite del efecto secundario decide lo segundo.

Paso 1: Definir la API y el estado.

text
Acquire(resource, requestId, leaseTtl, waitTimeout)
  -> { leaseId, fencingToken, expiresAt }

Renew(resource, leaseId)
  -> { expiresAt }

Release(resource, leaseId)
  -> { released }

resource es un identificador de negocio normalizado, no una entrada de usuario sin procesar y sin límites. leaseId es un identificador no adivinable para esta época de propiedad. fencingToken utiliza la revisión globalmente monótona de un registro de consenso confirmado, mientras que cada recurso protegido almacena el token más alto que ha aceptado. El resultado de deduplicación para requestId permanece al menos durante la ventana de reintento del llamador. La liberación es idempotente, pero una liberación con un leaseId antiguo no puede eliminar el bloqueo de un nuevo titular.

Un registro de bloqueo contiene el recurso, leaseId, la identidad del titular, el fencing token, la expiración y una referencia opcional de espera. Los registros de bloqueos inactivos se pueden eliminar, pero los tokens no pueden retroceder. Una revisión monótona global evita reiniciar la época de un recurso a 1 después de que se elimina su registro inactivo.

Paso 2: Elegir el límite de replicación fuertemente consistente.

Utilice un almacén de consenso probado o un sistema de coordinación para la máquina de estados; no reimplemente Raft o Paxos dentro del servicio de la aplicación. Coloque una réplica en cada una de las tres zonas de disponibilidad. El líder devuelve el éxito solo después de que al menos dos réplicas confirmen el comando. Las lecturas del estado del bloqueo deben ser linearizables o ser manejadas por el líder; una réplica retrasada no puede declarar libre un recurso.

La ruta de adquisición normal valida los parámetros y la clave de deduplicación, confirma que no existe ningún bloqueo o que la máquina de estados ha expirado su arrendamiento, asigna un nuevo leaseId y revisión, los confirma en un quórum y responde. Si el líder falla después de la confirmación pero antes de que llegue su respuesta, un reintento con el mismo requestId obtiene el resultado original del nuevo líder en lugar de crear un segundo arrendamiento.

Cuando solo una de las tres réplicas permanece accesible, el servicio rechaza adquisiciones y renovaciones. Esto reduce la disponibilidad pero preserva la exclusión mutua. Permitir que la minoría renueve parece útil, pero después de la reconexión no existe una forma segura de tratar a ambos titulares particionados como válidos.

Paso 3: Usar arrendamientos para recuperar titulares fallidos.

El arrendamiento predeterminado es de 30 segundos y el cliente renueva cada 10 segundos, dejando dos intervalos de renovación para fluctuaciones (jitter) y fallas transitorias. El tiempo de arrendamiento autoritativo es gestionado por la máquina de estados de coordinación del lado del servidor. El reloj local de un cliente puede decidir cuándo intentar la renovación, pero no puede probar la propiedad. Después de fallas repetidas de renovación o una respuesta incierta, el cliente entra en un estado de reposo, no inicia ningún trabajo nuevo y detiene el trabajo en vuelo interrumpible lo antes posible.

Un cambio de líder debe manejar el tiempo de arrendamiento restante de manera conservadora; un reloj rápido en el nuevo líder no puede entregar el bloqueo a otra persona demasiado pronto. Los sistemas de producción deben reutilizar una implementación de arrendamiento probada e incluir la desviación máxima del reloj (clock skew), el tiempo de elección y los reintentos de red en el presupuesto del arrendamiento. Reducir el arrendamiento a cientos de milisegundos mejora la velocidad de limpieza, pero convierte el jitter ordinario en pérdidas frecuentes de bloqueo.

Paso 4: Usar fencing tokens para detener clientes zombi.

Supongamos que el cliente A adquiere el token 41 y luego se pausa por una recolección de basura prolongada. Su arrendamiento de 30 segundos expira, el cliente B adquiere el token 42 y B comienza a trabajar. A se reanuda sin saber que perdió el bloqueo y envía una escritura retrasada. Si el almacén solo sabe que A adquirió una vez el bloqueo, la escritura obsoleta puede sobrescribir el resultado más reciente de B.

Por lo tanto, cada solicitud protegida lleva su token. El almacén recuerda atómicamente la época más alta vista para cada recurso. Después de aceptar el token 42, rechaza cada solicitud con el token 41. Múltiples operaciones con el mismo token aún pueden ser legítimas; su ordenamiento, idempotencia y conflictos de versiones pertenecen al protocolo de negocio. La comparación rechaza tokens inferiores a la última época en lugar de rechazar ciegamente tokens iguales.

La documentación de etcd hace explícito este mismo límite: un arrendamiento por sí solo no garantiza la exclusión mutua sobre un recurso externo; ese recurso debe validar una versión. Si el destino no puede almacenar o comparar un token, el diseño no puede prometer seguridad estricta. Las alternativas incluyen una actualización condicional en la base de datos, una restricción única, un bloqueo transaccional nativo, una cola de escritor único o un proxy de escritura que pueda hacer cumplir el token.

Paso 5: Gestionar la espera, la equidad y las estampidas.

Para recursos de baja contención, los llamadores fallidos pueden reintentar con retroceso exponencial (exponential backoff) y jitter. Para un recurso muy concurrido que necesita espera, asigne números de secuencia crecientes y permita que cada cliente en espera observe únicamente a su predecesor inmediato. Cuando un predecesor libera o expira, solo se despierta el siguiente en espera en lugar de que todos los clientes compitan a la vez. La receta de bloqueo de ZooKeeper utiliza nodos secuenciales efímeros y observadores (watches) del predecesor por esta razón.

La cola proporciona FIFO aproximado, no equidad absoluta. La cancelación, el tiempo de espera (timeout) y la expiración de la sesión eliminan el nodo de espera. Si se pierde la respuesta a la creación del nodo, requestId encuentra el nodo original en lugar de añadir otro. Los límites de espera por recurso y por inquilino evitan que un bloqueo concurrido agote la memoria.

Paso 6: Estimar la capacidad y la partición.

Veinte mil bloqueos activos renovados cada 10 segundos crean unas 2,000 renovaciones por segundo. En un pico de 2,000 adquisiciones por segundo, y asumiendo que las liberaciones son aproximadamente iguales a las adquisiciones, la máquina de estados de consenso maneja alrededor de 2,000 + 2,000 + 2,000 = 6,000 confirmaciones de escritura por segundo. Los registros de encolamiento, cancelación, expiración y deduplicación añaden amplificación de escritura. Las pruebas de capacidad deben combinar el tráfico pico, la pérdida de una réplica y la compactación de registros (log compaction).

Si 100,000 recursos retienen alrededor de 500 bytes de estado lógico cada uno, el total lógico es de aproximadamente 50 MB. Las réplicas, los logs, los índices, los clientes en espera y la sobrecarga del motor de almacenamiento incrementan sustancialmente la huella real. La persistencia síncrona, los recursos concurridos y el volumen de renovación son cuellos de botella más probables aquí que el tamaño del registro estático.

Comience con un solo grupo de consenso para la escala indicada. Particione por un hash del recurso solo si las mediciones muestran que un grupo no alcanza el objetivo. El sharding aumenta el rendimiento agregado pero no puede dividir un recurso extremadamente concurrido y complica el bloqueo atómico entre recursos. Este diseño no promete bloqueos transaccionales multirrecurso. Si los llamadores deben bloquear varios recursos, utilizan un orden fijo y un timeout general, o el dominio se remodela como un único recurso de nivel superior.

Paso 7: Cerrar el ciclo operativo y de fallas.

  • Falla del líder: el nuevo líder recupera el estado confirmado; requestId resuelve de forma segura las solicitudes con respuestas desconocidas.
  • Partición de red: solo el quórum presta servicio; la minoría rechaza, y el cercado eventualmente rechaza la escritura de un titular antiguo.
  • Pausa del cliente: se puede emitir un nuevo bloqueo después de la expiración, mientras que el cliente reanudado falla la validación del token del lado del recurso.
  • Bloqueo concurrido: mida la longitud de espera, la latencia de adquisición y el tiempo de retención; limite la cola y considere una cola o un trabajo particionado.
  • Tormenta de renovaciones: aplique jitter a los cronogramas de los clientes y priorice los arrendamientos más cercanos a la expiración en lugar de renovar todos los bloqueos a la vez.
  • Recurso sin validación de token: degrade explícitamente a exclusión de mejor esfuerzo (best-effort) o prohíba escrituras estrictas de dinero e inventario.

Las métricas centrales incluyen p50/p95/p99 de adquisición, renovación y liberación; resultados exitosos, timeouts, conflictos y resultados desconocidos; bloqueos activos, clientes en espera, expiraciones, fallas de renovación, duración de la elección de líder, latencia de confirmación de consenso, rechazos de cercado y recursos concurridos. Los registros de auditoría capturan el recurso, leaseId, el token, el llamador y el resultado sin cargas útiles sensibles.

La validación va más allá de las pruebas unitarias. Las pruebas de modelos de máquinas de estados comprueban la propiedad única y los tokens monótonos. La inyección de fallas cubre una respuesta perdida después del commit, un cliente pausado más allá de 30 segundos, una escritura antigua retrasada, el aislamiento de una réplica, la pérdida de la mayoría, cambios de líder y cancelación de clientes en espera. La aserción crítica de extremo a extremo es: después de que el recurso acepta el token 42 de B, el token 41 de A nunca más puede modificar ese recurso.

Respuesta de muestra de alta calidad

“Comenzaría con el objetivo de seguridad: un recurso tiene como máximo un arrendamiento válido en el estado de bloqueo fuertemente consistente, y el recurso protegido nunca acepta la escritura de un titular anterior. El servicio se ejecuta a través de tres zonas de disponibilidad sobre un almacén de consenso probado. La adquisición, renovación y liberación requieren un quórum. Con solo una minoría, el servicio rechaza el trabajo en lugar de sacrificar la exclusión mutua por la disponibilidad.

La API devuelve un leaseId, expiración y un fencingToken monótonamente creciente. El arrendamiento predeterminado es de 30 segundos y el cliente renueva cada 10 segundos. Su reloj local solo programa la renovación; si la renovación es incierta, el cliente detiene el trabajo. Un arrendamiento permite la toma de posesión tras una falla, pero el recurso es el límite de seguridad real: cada solicitud protegida lleva el token, y el recurso almacena la época más alta que ha aceptado y rechaza las más antiguas. Si el cliente con el token 41 se reanuda después de que el token 42 haya tomado el control, su escritura obsoleta no puede aplicarse.

Cada adquisición lleva un requestId. Si el servicio confirmó pero perdió su respuesta, el llamador reintenta con el mismo ID y recibe el arrendamiento original en lugar de crear otro. La renovación y la liberación deben coincidir con el leaseId actual, de modo que un cliente antiguo no pueda liberar al nuevo titular. Para un bloqueo con contención, los clientes en espera ordenados observan solo a su predecesor, proporcionando un FIFO aproximado sin estampidas.

En cuanto a la capacidad, 20,000 bloqueos renovados cada 10 segundos ya producen unas 2,000 escrituras por segundo. Añadir 2,000 adquisiciones y una tasa de liberación similar da aproximadamente 6,000 confirmaciones de consenso por segundo. Verificaría el p99 de 200 milisegundos mientras una réplica está caída y la compactación de registros se está ejecutando, en lugar de citar un benchmark de proveedor. Comenzaría con un grupo de consenso y aplicaría sharding por recurso solo si las pruebas de carga demuestran que es necesario.

Finalmente, las pruebas de modelos y la inyección de fallas cubren respuestas perdidas después del commit, pausas de clientes, paquetes retrasados, particiones, elecciones y cancelación de espera. Monitorearía la latencia de adquisición y renovación, conflictos, expiraciones, longitud de la cola, elecciones y rechazos de cercado. Si el sistema protegido no puede comparar atómicamente un token, indicaría que la exclusión mutua estricta no está disponible y preferiría una actualización condicional en la base de datos, una restricción única o una cola de escritor único.”

Errores comunes

  • Almacenar solo una clave con TTL → un cliente antiguo pausado puede reanudarse y escribir → emitir un token monótono para cada adquisición y validarlo en el recurso.
  • Permitir que cada zona de disponibilidad emita bloqueos → una partición crea múltiples titulares → pasar cada cambio de estado a través de una máquina de estados respaldada por quórum.
  • Tratar el reloj del cliente como la verdad del arrendamiento → el desfase del reloj y las pausas provocan una propiedad falsa → gestionar los arrendamientos del lado del servidor y hacer que los clientes con incertidumbre se detengan.
  • Reintentar la adquisición con un nuevo ID de solicitud → el original puede estar ya confirmado → usar un requestId estable para recuperar el primer resultado.
  • Permitir la liberación solo por el nombre del recurso → una solicitud antigua puede eliminar al nuevo titular → requerir el leaseId actual para renovar y liberar.
  • Dimensionar solo para 2,000 adquisiciones por segundo → faltan 2,000 renovaciones y liberaciones similares → probar una base de aproximadamente 6,000 confirmaciones de estado por segundo.
  • Hacer que cada cliente en espera observe la raíz del bloqueo → cada liberación despierta a toda la cola → hacer que cada cliente en espera observe únicamente a su predecesor inmediato.
  • Hacer sharding en muchos grupos de consenso inmediatamente → las operaciones y la semántica multirrecurso se vuelven complejas primero → medir un grupo y luego aplicar sharding a partir de evidencia.
  • Usar un bloqueo distribuido para cada fila → la coordinación se convierte en una ruta transaccional de alta frecuencia y un cuello de botella → preferir restricciones atómicas de base de datos para concurrencia de grano fino.
  • Afirmar seguridad estricta cuando el destino no puede validar tokens → un arrendamiento no puede detener una escritura obsoleta retrasada → degradar la garantía o cambiar el límite de escritura.

Preguntas de seguimiento y respuestas

Pregunta de seguimiento 1: ¿Por qué es necesario un fencing token si el bloqueo tiene un arrendamiento?

El arrendamiento solo permite que el servicio de bloqueo le otorgue a B un bloqueo después de 30 segundos. No puede eliminar una operación que A ya envió a un sistema externo pero que permanece en una cola de red o de procesos. A también puede reanudarse después de una larga pausa sin saber que su arrendamiento expiró. Una vez que el recurso acepta el token 42, rechazar el token 41 detiene el trabajo de la época antigua en el punto exacto donde ocurren los efectos secundarios. La regla reutilizable es: un arrendamiento decide cuándo se puede elegir un nuevo titular; el cercado decide si el trabajo del titular anterior sigue siendo aceptado.

Pregunta de seguimiento 2: ¿Qué sucede si la base de datos protegida no puede almacenar un fencing token?

Busque primero una condición de versión atómica equivalente como UPDATE ... WHERE version = expected, una restricción única, un bloqueo transaccional o un bloqueo consultivo (advisory lock) de base de datos. Las escrituras también pueden pasar a través de un proxy o una cola de consumidor único que valide el token. Si nada de esto es posible, la garantía es solo una exclusión de mejor esfuerzo; las pausas de procesos y los mensajes retrasados aún pueden romper la corrección. Los flujos de trabajo de dinero e inventario no deben aceptar una garantía ambigua.

Pregunta de seguimiento 3: ¿Cómo diseñaría un bloqueo global entre regiones?

El diseño directo le otorga a cada recurso una región de origen (home region) y hace que cada región use un quórum interregional. Eso añade latencia de escritura a larga distancia, y las regiones minoritarias no pueden realizar adquisiciones durante una partición. Los bloqueos regionales independientes no pueden fusionarse de forma asíncrona porque los conflictos de exclusión mutua no se pueden deshacer a posteriori. Si la disponibilidad regional importa más, particione la propiedad del recurso de modo que un recurso sea escribible en una región en lugar de inventar un bloqueo global activo-activo.

Pregunta de seguimiento 4: ¿Cómo elegiría el arrendamiento de 30 segundos y el intervalo de renovación de 10 segundos?

Son datos provistos en el enunciado. Los valores reales dependen de la pausa normal de procesos más larga, el p99 de la red, el tiempo de elección, el margen de error del reloj y el tiempo aceptable de recuperación ante fallas. Un arrendamiento demasiado corto trata el jitter normal como una pérdida de bloqueo; uno demasiado largo retrasa la recuperación de un titular fallido. Una renovación de 10 segundos brinda dos oportunidades adicionales dentro de un arrendamiento de 30 segundos. Añada jitter aleatorio para que 20,000 clientes no creen picos de renovación sincronizados.

Pregunta de seguimiento 5: ¿Cómo admitiría la adquisición de varios bloqueos a la vez?

El límite más simple es que este servicio no ofrece bloqueo atómico multirrecurso. Los llamadores adquieren nombres de recursos normalizados en un orden fijo con un timeout general corto, y liberan en orden inverso tras una falla. Esto reduce los interbloqueos (deadlocks) pero no constituye atomicidad transaccional. Si el dominio realmente necesita una adquisición de todo o nada, modele el conjunto como un único recurso de nivel superior o mantenga todas las claves en una transacción de consenso y asuma el costo de rendimiento y complejidad.

Pregunta de seguimiento 6: ¿Cómo demostraría que la implementación nunca crea dos titulares válidos?

Utilice un modelo de máquina de estados para generar secuencias de adquisición, renovación, liberación, expiración y reintento, verificando que cada posición del log tenga como máximo un leaseId válido y que los tokens aumenten monótonamente. Luego inyecte fallas: pierda la respuesta después del commit, pause a A más allá del arrendamiento, permita que B adquiera y escriba, y reanude a A con su escritura antigua; el recurso debe rechazar el token antiguo. Además, aísle la minoría y la mayoría, cambie de líderes repetidamente, cancele esperas y verifique cada historial concurrente contra los invariantes.

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