Tema representativo de entrevista

Entrevista de Backend: ¿Cómo diseñarías un request hedging seguro?

BackendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Una API de lectura idempotente tiene una latencia p99 alta mientras que la p50 es saludable. Diseña request hedging: explica el umbral de activación, la elección de réplica, la cancelación, la protección de carga, la observabilidad y cuándo deshabilitarlo.

Planteamiento y contexto

Una API de lectura idempotente tiene un p99 alto mientras que el p50 es saludable; las llamadas lentas parecen deberse a encolamientos ocasionales o problemas temporales en los hosts. Diseña request hedging: envía una solicitud principal, emite una copia a otra réplica tras un retraso, retorna el primer resultado aceptable y cancela la otra. Explica los límites de costo y amplificación de fallos.

Qué está evaluando el entrevistador

Comprender el objetivo

El hedging apunta a la cola; no acelera todas las solicitudes. Se adapta a lecturas seguramente repetibles y no debe duplicar ciegamente escrituras con efectos secundarios.

Controlar el costo

Duplicar cada solicitud puede casi duplicar la carga del backend. Un diseño sólido utiliza activadores con retraso, un conteo máximo de intentos, limitación (throttling), cancelación y métricas basadas en la solicitud original.

Manejar fallos correlacionados

Enviar ambos intentos a un mismo host sobrecargado tiene poco valor. El enrutamiento entre instancias, zonas o dominios de fallo, sumado a la protección de colas y errores, determina si el hedging es seguro.

Preguntas para clarificar primero

  • ¿Es la API idempotente y se pueden aceptar múltiples lecturas concurrentes?
  • ¿Cuáles son las líneas base de p50, p95, p99, p99.9 y el SLO?
  • ¿Son las llamadas lentas casos aislados rezagados o un problema de encolamiento compartido por todas las réplicas?
  • ¿Cómo se seleccionan las réplicas entre instancias, zonas y versiones?
  • ¿La cancelación realmente libera hilos, conexiones y cómputo aguas abajo?
  • ¿Qué tasa de error, profundidad de cola o tasa de disparo de hedge deshabilita la política?

Una respuesta de 30 segundos

“Habilitaría el hedging únicamente para lecturas idempotentes. Enviaría la principal primero; usaría un umbral dinámico estilo p95 por clase de solicitud y luego enviaría un hedge a una réplica saludable en otro dominio de fallo solo cuando el umbral expire y un presupuesto lo permita. Compartirían un único deadline, se retornaría el primer éxito y se cancelaría la perdedora. Limitaría los intentos, usaría throttling y guardas de cola/error, y monitorearía p99, tasa de disparo, solicitudes extra, éxito de cancelación y latencia original. Deshabilitaría la política cuando amplifique la carga.”

Respuesta detallada paso a paso

Definir la máquina de estados de la solicitud

Los estados son primary_sent, hedge_waiting, hedge_sent, winner_selected y deadline_exceeded. Envía la principal primero; termina si retorna dentro del umbral; de lo contrario, crea un hedge. La primera respuesta exitosa gana y todos los demás intentos reciben cancelación.

Elegir el umbral y el alcance

Mantén histogramas de latencia agrupados por método, tenant, tamaño de solicitud o longitud del prompt. Utiliza un umbral dinámico estilo p95 con límites y un fallback para arranque en frío. No uses únicamente una media global ni dupliques inmediatamente cada solicitud.

Enrutar a una réplica independiente

Evita el host, la zona o el dominio de fallo de la principal. Prefiere un nodo saludable con una cola corta. Si todos los candidatos están sobrecargados, el hedging añade congestión; en su lugar, espera, degrada o falla rápido.

Manejar la cancelación y el deadline

Los clientes y proxies deben propagar un token de cancelación. El trabajo aguas abajo debe detenerse y liberar conexiones, hilos, GPUs o cachés. Ambos intentos comparten el deadline total para que la duplicación no extienda la espera visible para el usuario.

Proteger la capacidad aguas abajo

Establece maxAttempts, un retraso mínimo de hedge, un presupuesto en vuelo y un token bucket por servicio. gRPC limita maxAttempts a 5 y ofrece throttling de reintentos; un diseño de producción aún necesita su propio presupuesto de capacidad y errores.

Manejar errores y llamadas no idempotentes

Continúa solo para casos idempotentes y reintentables. Retorna errores deterministas de validación o autenticación de inmediato. Las escrituras necesitan claves de idempotencia y deduplicación, o deberían usar una sola solicitud más compensación.

Pseudocódigo

~~~text send(primary) timer = hedgeThreshold(request_class) if primary unfinished at timer and budget_allows(): send(hedge, differentfailuredomain) winner = firstsuccessbefore_deadline() cancel(allotherattempts) record(primarylatency, hedgefired, winner, cancel_result) ~~~

Complejidad, observabilidad y rollback

El peor conteo de intentos está acotado por maxAttempts; el volumen extra de solicitudes depende de la tasa de disparo y la latencia de cancelación. Rastrea p50/p95/p99, tasa de disparo de hedge, QPS extra, colas aguas abajo, errores, éxito de cancelación y latencia principal original. Desactiva la política por servicio, tenant o región cuando aumenten la congestión o los errores.

ControlPropósitoModo de fallo si está mal configurado
hedge delayDuplicar solo llamadas lentasDemasiado corto amplifica QPS
maxAttemptsAcotar copias concurrentesDemasiado alto crea una tormenta de solicitudes
cancellationLiberar recursos del perdedorSi falla, sigue consumiendo capacidad
throttle budgetRestringir durante congestiónMétricas faltantes ocultan la sobrecarga

Respuesta modelo

“Primero confirmaría que se trata de una lectura idempotente y construiría un histograma de latencia por clase de solicitud. Tras enviar la principal, enviaría un hedge solo después de que un umbral estilo p95, una réplica independiente y saludable, y un presupuesto de concurrencia lo permitan. Ambos intentos comparten un deadline; el primer éxito gana y el proxy propaga la cancelación mientras registra si los recursos realmente se liberaron. Los intentos máximos, el throttling de tokens, la profundidad de cola y la tasa de error protegen el backend, mientras que los errores deterministas nunca se duplican. Haría un despliegue canario de la política y compararía p99, tasa de disparo, QPS extra, latencia de cancelación y latencia principal sin hedging; una tormenta de hedges la deshabilita automáticamente.”

Errores comunes

Duplicar cada solicitud inmediatamente

Eso convierte el hedging en replicación incondicional, aumentando la carga normal y el costo sin demostrar que los rezagados causaron la cola.

Aplicar hedging a escrituras con efectos secundarios

Dos intentos pueden crear dos registros o cobrar dos veces. Sin claves de idempotencia, deduplicación y semántica de transacciones, no uses hedging.

Usar el mismo dominio de fallo

Un fallo compartido de host, rack o zona ralentiza ambos intentos y añade carga a la ubicación sobrecargada.

Mirar únicamente el p99 visible para el usuario

El hedging puede ocultar una ruta principal que empeora y retrasar las señales de escalado. Registra también la latencia principal sin hedging y la profundidad de la cola.

Ignorar la cancelación

Detener la espera no es detener el trabajo aguas abajo. Verifica la propagación, la liberación de recursos y la latencia de cancelación.

No tener un interruptor de emergencia (kill switch)

Altos errores, acumulación en cola o una tasa anormal de disparo de hedges requieren un interruptor de desactivación rápido a nivel de servicio, tenant o región.

Preguntas de seguimiento y respuestas

¿En qué se diferencia el hedging del retry?

El retry generalmente espera a un fallo antes de volver a enviar. El hedging envía una copia tras un umbral de latencia mientras el primer intento aún se está ejecutando. Ambos necesitan idempotencia, deadlines y throttling.

¿Por qué empezar con p95?

Deja la mayoría de las solicitudes normales intactas mientras cubre una pequeña porción de la cola. El umbral debe ajustarse por clase de solicitud, presupuesto y resultados experimentales.

¿Qué pasa si todas las réplicas están congestionadas?

Detén el hedging y usa límites de tasa, colas, degradación o fallo rápido. El hedging no puede reparar una capacidad insuficiente.

¿Cómo demuestras que la cancelación funciona?

Registra la cancelación aguas abajo, la finalización del trabajo, la ocupación de conexiones y la latencia de liberación. Inyecta un perdedor lento y confirma que se detiene después de seleccionar un ganador.

¿Cómo cambia el diseño con streaming?

Usa el tiempo hasta el primer byte o token como disparador, pero duplicar después de que la salida comienza puede crear datos duplicados. Define primero la fusión de streams, la cancelación y la visibilidad para el cliente.

¿Cuáles son los parámetros clave de gRPC?

maxAttempts, hedgingDelay y los códigos de estado no fatales controlan cuándo se envían las copias. gRPC limita los intentos a 5 y proporciona throttling de reintentos y pushback del servidor; el servicio aún necesita su propio presupuesto de capacidad.

Fuentes públicas

Preguntas relacionadas