Problema y escenarios aplicables
Diseña una cola de mensajes distribuida compartida por múltiples equipos de producto. El ingreso constante es de 1 millón de mensajes por segundo con un promedio de 1 KB cada uno, y un pico de tráfico puede sostener 3 millones de mensajes por segundo durante 15 minutos. Los mensajes se retienen durante 24 horas por defecto. Los productores publican en lotes. Los consumidores extraen (pull) en grupos, confirman offsets y reproducen mensajes dentro del periodo de retención. Los mensajes con la misma clave de negocio requieren ordenamiento local, mientras que diferentes claves pueden ejecutarse en paralelo. Los mensajes ordinarios utilizan entrega de al menos una vez, y la confirmación de publicación tiene un objetivo p99 inferior a 50 milisegundos. Cada partición tiene tres réplicas en tres zonas de disponibilidad; perder una zona no debe causar la pérdida de mensajes confirmados.
La mayoría de los mensajes son pequeños, pero la API permite cargas útiles de negocio de hasta 100 MB. Una carga útil grande no debe pasar repetidamente a través de los registros del broker, transferencias de réplicas y búferes de consumidores. En este diseño, primero ingresa al almacenamiento de objetos, mientras que la cola almacena solo una referencia inmutable, el tamaño y la suma de verificación (checksum). El rendimiento, la latencia, la retención, los umbrales y el recuento de réplicas son supuestos de entrevista que requieren pruebas de rendimiento (benchmarking) en el hardware de destino. No son afirmaciones de producto.
Un artículo chino de diseño de sistemas publicado en mayo de 2026 analiza directamente una cola que procesa decenas de miles de millones de mensajes por día con picos de millones de QPS. Un ejercicio de PracHub actualizado en junio de 2026 pide a los candidatos que cubran API, grupos de consumidores, offsets, particiones, réplicas, cargas útiles grandes y aislamiento multiinquilino. Juntos establecen un planteamiento de diseño de sistemas actualmente verificable. Solo una página asegura una atribución de empresa, por lo que este artículo deja la empresa sin definir.
Qué evalúan los entrevistadores
Primero, ¿define el candidato el contrato de entrega? Una publicación exitosa, el almacenamiento duradero en el broker, la entrega del mensaje a un consumidor, la finalización de un efecto secundario del negocio y la confirmación de un offset son cinco límites independientes. Llamar a todos ellos “éxito del mensaje” oculta dos ventanas de falla: un productor puede repetir una publicación tras perder la confirmación, y un consumidor puede repetir el trabajo después de completar el efecto secundario pero fallar antes de confirmar el offset.
Segundo, ¿siguen el particionamiento, el ordenamiento y el escalado un mismo argumento? Enviar una clave a una partición preserva el orden de registro de esa clave. La misma partición limita tanto el rendimiento de escritura como el paralelismo del grupo de consumidores. Más particiones agregan ranuras paralelas, pero no dividen una clave caliente (hot key) continuamente sobrecargada ni crean un orden global.
Tercero, ¿sobrevive a las fallas la regla de confirmación de réplicas? Una respuesta sólida establece cuándo se puede confirmar al productor, qué réplicas son elegibles para convertirse en un nuevo líder y cómo una época (epoch) bloquea (fences) a un líder antiguo recuperado. Decir que “tres réplicas realizan conmutación por error automáticamente” no demuestra que los registros confirmados sobrevivan.
Cuarto, ¿están conectados los offsets de los consumidores con los resultados del negocio? Confirmar antes de procesar puede omitir un efecto del negocio. Procesar antes de confirmar puede reproducirlo tras una caída. La entrega de al menos una vez elige la segunda ventana y luego absorbe las repeticiones con un ID de mensaje estable, una clave de idempotencia del negocio, una restricción única o una condición de versión. Una transacción de broker cubre únicamente los recursos que participan en esa transacción; no otorga automáticamente efectos de exactamente una vez (exactly-once) a un servicio de pago externo, proveedor de correo electrónico o base de datos.
Finalmente, ¿puede la cola preservar estos límites bajo presión? El candidato debe calcular el almacenamiento para 24 horas y el retraso acumulado (backlog) en ráfagas, manejar mensajes grandes, particiones calientes, consumidores lentos, mensajes venenosos (poison messages), discos llenos e inquilinos ruidosos, y luego inyectar fallas para demostrar que los mensajes confirmados no se pierden, el trabajo no confirmado no se omite y los propietarios obsoletos no pueden avanzar los offsets.
Preguntas de clarificación antes de responder
- ¿Es este un registro retenido o una cola de trabajo de reclamo y eliminación (claim-and-delete)? Este diseño opta por un registro retenido porque se
requieren múltiples grupos de consumidores y reproducción. Si exactamente un trabajador reclama cada trabajo y la reproducción histórica es innecesaria, una cola con concesiones (leases) y tiempos de espera de visibilidad es más simple.
- ¿Cuál es el alcance del ordenamiento? El ordenamiento cubre el orden de adición dentro de una partición de tema, con una clave de negocio asignada
a una partición. No hay un orden global entre claves, particiones o temas. El orden global reduciría el rendimiento al de un único registro serial.
- ¿Qué significa la confirmación de publicación? Dos de tres réplicas han almacenado de forma duradera el registro y el plano de control
aún reconoce la época del líder actual. Un tema de alta durabilidad rechaza escrituras cuando hay menos de dos réplicas disponibles.
- ¿Cuál es la semántica de consumo? El valor predeterminado es al menos una vez: procesar con éxito y luego confirmar el siguiente offset.
Los efectos secundarios externos requieren idempotencia o conciliación. Solo una carga de trabajo de bajo valor que permita pérdidas pero prohíba duplicados debería confirmar primero.
- ¿Necesitan los consumidores reproducción arbitraria? Un grupo puede restablecerse por offset o marca de tiempo dentro de la ventana de retención de 24 horas.
Más allá de la retención, debe restaurar desde un archivo histórico o fallar explícitamente cuando no exista dicho archivo.
- ¿Se pueden omitir los mensajes venenosos? Los temas ordinarios pueden mover un mensaje a un tema de mensajes fallidos (dead-letter topic) tras reintentos limitados.
Un tema estrictamente ordenado por clave no puede omitirlo sin costo; se debe pausar la clave o partición y repararla, o los mensajes posteriores podrían adelantar a la falla.
- ¿Debe una carga útil de 100 MB ser en línea (inline)? No. Este diseño asume cargas útiles en línea de hasta 256 KiB y utiliza referencias a objetos
por encima de ese umbral. Las pruebas de rendimiento y los costos determinan el umbral; 100 MB es el límite de la carga útil del objeto.
- ¿Cuál es el requisito multirregión? El diseño principal es una región distribuida en tres zonas de disponibilidad.
La recuperación ante desastres asíncrona entre regiones no puede prometer a la vez cero pérdida de datos y latencia de escritura local. Un requisito de cero RPO entre regiones cambia la ruta de confirmación y el presupuesto de latencia.
- ¿Qué tan estricto es el aislamiento de inquilinos? Los brokers se comparten por defecto, con límites de ingreso, egreso, almacenamiento, particiones
y conexiones por inquilino. Los inquilinos muy grandes o regulados pueden utilizar un grupo de brokers dedicado bajo el mismo plano de control y protocolo.
Estructura de respuesta en 30 segundos
“Modelaría esto como un registro particionado, retenido y reproducible. El productor enruta por clave de negocio a un líder de partición, agrupa escrituras en lotes y recibe una confirmación solo después de que dos réplicas en diferentes zonas de disponibilidad persistan el lote. Eso proporciona orden por clave, no orden global. Un grupo de consumidores posee particiones de forma exclusiva, completa una escritura de negocio idempotente y luego confirma el siguiente offset, por lo que la entrega es de al menos una vez y los efectos externos se desduplican por ID de mensaje. El ingreso constante es de aproximadamente 1 GB/s y 86.4 TB por día de forma lógica, o 259.2 TB con tres réplicas. Un pico de tres veces durante 15 minutos crea cerca de 1.8 TB de retraso acumulado adicional si los consumidores sostienen la tasa constante. Las cargas útiles superiores a 256 KiB van al almacenamiento de objetos y la cola lleva una referencia y suma de verificación. Demostraría los límites con cuotas de inquilinos, programación justa, alertas de retraso, pruebas de caída del líder, pérdida de confirmación y fallas de consumidores.”
Análisis detallado paso a paso
Paso 1: Escribir las API y los invariantes antes que los componentes.
La superficie esencial cubre temas, publicación, obtención (fetch), confirmación y restablecimiento de offsets:
POST /v1/topics
POST /v1/topics/{topic}/messages:publish
POST /v1/groups/{group}/messages:fetch
POST /v1/groups/{group}/offsets:commit
POST /v1/groups/{group}/offsets:resetUna solicitud de publicación lleva un contexto de inquilino autenticado, tema, message_key opcional, message_id estable, carga útil o referencia de objeto, época del productor y secuencia por partición. La respuesta del lote devuelve la partición, el offset y el estado de confirmación de cada mensaje. La obtención lleva el grupo, la generación de propiedad de la partición, el offset inicial, los bytes máximos y la duración del sondeo largo (long poll). La confirmación escribe el offset del siguiente registro a leer.
El diseño preserva cuatro invariantes: un registro confirmado permanece legible tras la falla de una zona de disponibilidad; los consumidores ven solo un prefijo confirmado; los offsets aumentan monótonamente dentro de una época de líder; y un consumidor con una generación vencida no puede confirmar offsets ni continuar escribiendo resultados. El message_id a nivel de API admite la desduplicación del negocio. producer_id + epoch + sequence permite que el broker reconozca un reintento de la misma publicación.
Paso 2: Separar el plano de control del plano de datos.
Control plane: tenants and ACLs, topic configuration, partition placement,
replica membership, leader epochs, quotas
Data plane:
Producer -> metadata cache -> partition leader -> follower replicas
Consumer group -> group coordinator -> partition leaders -> business sinkUn pequeño clúster respaldado por consenso almacena los metadatos de temas y particiones y asigna una época que aumenta monótonamente a cada periodo de liderazgo. No transporta los cuerpos de los mensajes. Los brokers añaden, replican, leen y retienen registros. Los clientes almacenan en caché los líderes de partición y actualizan los metadatos tras una respuesta de época obsoleta o de no ser líder. El rendimiento de mensajes evita un proxy central, mientras que las particiones existentes pueden continuar durante una concesión limitada durante una interrupción del plano de control. La creación de temas y el movimiento de particiones pueden pausarse; los metadatos obsoletos nunca deben elegir un líder arbitrario.
Paso 3: Utilizar registros particionados para rendimiento, reproducción y ordenamiento local.
Cada partición es un conjunto de segmentos de solo adición (append-only) cuyos registros contienen:
MessageEnvelope {
tenant_id, topic, partition, offset
message_id, message_key, producer_id, producer_epoch, sequence
created_at, headers, payload_or_ref, payload_size, checksum
}El segmento activo recibe adiciones secuenciales. Un índice disperso de offsets localiza las lecturas, y los segmentos cerrados rotan por tiempo o tamaño. Los consumidores obtienen lotes por offset, lo que permite E/S secuencial, uso de page cache y transferencia de red por lotes. La retención elimina segmentos completos después de 24 horas. Un segmento bajo reproducción válida o carga a almacenamiento por niveles retiene una referencia para que la eliminación no compita con un lector.
El hash de enrutamiento incluye el inquilino de confianza, el tema y la clave de negocio. Los registros con la misma clave permanecen en una partición; los registros sin clave pueden usar asignación por turnos (round-robin) o por lotes fijos (sticky-batch). El enrutamiento exclusivo por inquilino sobrecarga a un inquilino grande, mientras que el enrutamiento completamente aleatorio pierde el orden de las claves. Agregar particiones afecta a los registros futuros. Un módulo modificado puede ubicar una clave tanto en la partición antigua como en la nueva. Cuando el orden estable es importante, asigna fragmentos virtuales a particiones físicas; pausa el fragmento virtual durante el movimiento, registra el offset de transición (cutover), vacía el propietario anterior y reanuda bajo una nueva época.
Paso 4: Dar a la replicación y la elección de líder una única definición de confirmación.
Cada partición tiene tres réplicas en tres zonas de disponibilidad. El líder asigna offsets, añade de forma duradera un lote y lo replica en paralelo. Una vez que dos réplicas cualesquiera han persistido el lote, commit_watermark avanza y se confirma al productor. Los consumidores leen solo offsets por debajo de esa marca de agua. Ante la falla del líder, el plano de control selecciona únicamente una réplica que contenga el prefijo confirmado e incrementa la época. Un líder antiguo recuperado trunca su cola no confirmada y se pone al día antes de servir tráfico; las solicitudes que lleven su época antigua son rechazadas.
Esta política tolera la falla de una zona de disponibilidad. Con dos réplicas restantes, ambas deben confirmar, por lo que la latencia y la capacidad se degradan. Si cualquiera de las réplicas restantes falla a continuación, un tema de alta durabilidad deja de confirmar escrituras hasta que se restaure la replicación. Elegir una réplica desactualizada para mejorar la disponibilidad violaría la promesa de cero pérdidas. Durante una partición de red, solo el lado con una mayoría de confirmación puede escribir; el otro lado es bloqueado.
Un productor reintenta cuando el registro se confirmó pero la respuesta de confirmación se perdió. El broker desduplica dentro de la partición utilizando la época del productor y la secuencia monótona, y devuelve el offset original. Se rechaza un productor zombi con una época antigua. Esto elimina duplicados en el registro causados por reintentos de publicación. No combina dos solicitudes de negocio distintas que utilizaron diferentes ID, ni desduplica el efecto secundario externo de un consumidor.
Paso 5: Conectar la propiedad del grupo y los offsets con el resultado del negocio.
Dentro de un grupo de consumidores, un miembro posee una partición a la vez. El coordinador del grupo mantiene los miembros, las concesiones, las generaciones y las asignaciones. Un tiempo de espera o un evento de escalado crea una nueva generación, y se rechaza la obtención o confirmación de un miembro antiguo. El reequilibrio incremental mueve solo las particiones necesarias y reduce las pausas en todo el grupo, pero un consumidor aún debe detener la obtención y confirmar el trabajo terminado antes de que se revoque la propiedad.
El orden predeterminado es obtener un lote, realizar una escritura de negocio idempotente y luego confirmar el siguiente offset. Si el consumidor falla tras la confirmación del negocio y antes de la confirmación del offset, el nuevo propietario reproduce los registros completados, lo que crea una entrega de al menos una vez. Un message_id estable puede respaldar una restricción única o un registro de mensajes procesados, o confirmarse en la misma transacción de base de datos que el estado del negocio. Si la salida regresa al mismo sistema de mensajería, los registros de salida y el offset de entrada pueden compartir una transacción de broker. Una base de datos externa, un proveedor de pagos o de correo electrónico aún necesitan idempotencia, consulta de estado o conciliación.
Los offsets se almacenan en un registro de metadatos replicado bajo (tenant, group, topic, partition) y llevan la generación. El monitoreo incluye tanto log_end_offset - committed_offset como la antigüedad del mensaje no procesado más antiguo. El recuento de mensajes por sí solo distorsiona el retraso acumulado con tamaños de registro variables, por lo que el sistema también informa los bytes de retraso y el tiempo de recuperación a la tasa neta de consumo actual.
Paso 6: Establecer el conflicto entre reintentos, mensajes fallidos y ordenamiento.
Las fallas transitorias de red y de límite de tasa (throttling) ingresan a un tema de reintento demorado con variación aleatoria (jitter). Las fallas deterministas de esquema, permisos o validación del negocio no deben reintentarse a ciegas. Un reintento preserva el message_id original, el tema de origen, la partición, el offset, la hora en que se vio por primera vez, el recuento de intentos y la clase de error. Tras el límite de intentos o del plazo del negocio, se mueve a un tema de mensajes fallidos, genera una alerta y permite un reenvío (redrive) controlado. El reenvío mantiene el ID original para que no pueda eludir la idempotencia.
Mover a un lado un registro fallido permite que los registros posteriores terminen primero, lo que entra en conflicto con el orden estricto por clave. Si el estado del orden debe evolucionar estrictamente, pausa esa clave y almacena en búfer sus registros posteriores en un carril ordenado independiente, luego reanuda desde el offset fallido tras la reparación. Pausar toda la partición es más simple pero tiene un radio de impacto mayor. Si el negocio acepta la convergencia por versión, los registros posteriores pueden continuar y el destino rechaza las versiones obsoletas. El contrato del tema debe elegir; no puede prometer a la vez “los mensajes venenosos nunca bloquean” y “los mensajes nunca se adelantan entre sí”.
Paso 7: Colocar mensajes grandes detrás de referencias de objetos y cerrar las condiciones de carrera de recolección de basura.
Este diseño establece 256 KiB como el umbral en línea. Una carga útil más grande utiliza credenciales de carga de corta duración para escribir un objeto inmutable con su tamaño, hash de contenido y metadatos de cifrado. Solo después de que la carga tiene éxito, el productor publica la referencia. Un consumidor lee el objeto y verifica el hash. Las réplicas del broker copian solo el pequeño envoltorio, por lo que un registro de 100 MB no puede monopolizar los búferes de red, los lotes de replicación o la memoria del consumidor.
Una carga exitosa cuya referencia nunca se publicó es un huérfano y expira con el TTL de la sesión de carga. Una vez que la referencia se confirma, la retención del objeto debe cubrir la retención del mensaje, la reproducción válida, los mensajes fallidos y un margen de seguridad. Un trabajo de eliminación primero verifica las referencias protegidas y elimina tras un período de gracia. Cuando fallan las lecturas de objetos, el consumo permanece sin confirmar y se reintenta; confirmar primero podría dejar un cuerpo permanentemente perdido. Las cargas útiles grandes reciben cuotas independientes de tasa de bytes, descargas simultáneas y almacenamiento por inquilino, porque la limitación basada en recuento de mensajes las valora erróneamente.
Paso 8: Derivar particiones, disco y margen de recuperación a partir de la capacidad.
Usando 1 KB decimal, el ingreso lógico constante es:
1,000,000 messages/s × 1,000 bytes = 1 GB/s
1 GB/s × 86,400 s = 86.4 TB/day
Lower bound for three replica writes = 86.4 × 3 = 259.2 TB/dayEl ingreso total durante el pico de 15 minutos es 3 GB/s × 900 = 2.7 TB. Si los consumidores sostienen solo el 1 GB/s constante, el retraso acumulado adicional es:
(3 GB/s - 1 GB/s) × 900 s = 1.8 TBDespués del pico, supongamos que los consumidores sostienen 1.5 GB/s mientras el nuevo ingreso permanece en 1 GB/s. La tasa neta de recuperación es de 0.5 GB/s, por lo que 1.8 TB toma 3,600 segundos, o aproximadamente una hora, para vaciarse en teoría. La recuperación de réplicas, la sobrecarga de lotes, la compresión, los índices, la reserva del sistema de archivos y el almacenamiento de objetos de mensajes grandes agregan capacidad, por lo que estos son límites inferiores.
El recuento de particiones está limitado tanto por bytes como por mensajes. Supongamos que una prueba de rendimiento con tres réplicas y el p99 objetivo determina que una partición sostiene 40 MB/s y 40,000 mensajes por segundo. Ambas dimensiones pico requieren al menos 75 particiones. Agregar un 50% de margen para fallas y reequilibrios arroja cerca de 113, por lo que 128 es una elección práctica. Ese resultado por partición es un supuesto de referencia para entrevistas. Diferentes hardware, lotes, confirmaciones o tamaños de registro requieren una nueva prueba; 128 no es una respuesta universal.
Paso 9: Implementar control de flujo, aislamiento de inquilinos y operaciones verificables.
Los consumidores utilizan sondeo largo y controlan su tasa con max_bytes y límites de lotes en tránsito. A medida que suben las marcas de agua de disco del broker, el sistema primero detiene la creación de nuevas particiones, reduce las concesiones de ráfaga para inquilinos de baja prioridad y luego rechaza publicaciones que excedan la cuota con una señal reintentable. Las colas de memoria no acotadas y los reintentos convierten la congestión en una falla del proceso. Los productores usan búferes de lotes acotados, plazos de espera (deadlines) y retroceso exponencial con variación aleatoria para que una caída del broker no genere tormentas de reintentos sincronizadas.
La identidad del inquilino proviene de las credenciales, nunca del cuerpo del mensaje. El ingreso está limitado por tasa de mensajes y bytes. El egreso se programa equitativamente según los bytes de obtención y la CPU de la solicitud. El almacenamiento, las particiones, los grupos de consumidores, las conexiones, las solicitudes en tránsito y los objetos grandes también tienen límites. La ubicación evita concentrar las réplicas o particiones calientes de un inquilino en unos pocos brokers. Los inquilinos muy grandes se trasladan a grupos dedicados, mientras que los grupos compartidos continúan midiendo y reportando rechazos por inquilino.
Las métricas clave incluyen el p50/p95/p99 de confirmación de publicación, errores y resultados desconocidos; bytes de ingreso por partición, retraso de líder y seguidor, commit_watermark, marca de agua de disco y claves calientes; offsets confirmados del grupo de consumidores, retraso del consumidor, antigüedad más antigua, reequilibrios, reintentos y mensajes fallidos; objetos huérfanos y fallas de lectura; y limitación de tasa y equidad por inquilino. Una prueba canario de extremo a extremo publica un ID estable, confirma un resultado de negocio idempotente, luego confirma su offset y concilia los estados del broker, el grupo y el negocio.
La matriz de fallas incluye la caída del líder antes de la replicación, tras la confirmación y antes de devolver la confirmación; la pérdida de una zona de disponibilidad; partición de red; disco lleno; recuperación de un líder obsoleto; clave caliente; un pico de tres veces durante 15 minutos; caídas del consumidor antes y después de su confirmación de negocio; confirmaciones obsoletas durante el reequilibrio; mensajes venenosos; carga exitosa seguida de falla de publicación; falla de lectura de objetos; y reenvío de mensajes fallidos. La aceptación valida que los registros confirmados sobrevivan, el trabajo no confirmado no se omita, el orden de claves siga el contrato del tema, las generaciones obsoletas no puedan avanzar offsets y cada duplicado, rechazo o descarte cuente con una métrica atribuible.
Ejemplo de respuesta de alta calidad
“Primero confirmaría que este es un servicio de registro retenido que requiere múltiples grupos de consumidores y reproducción de 24 horas. Un tema se divide en particiones y la misma clave de negocio permanece en una partición. Por lo tanto, el ordenamiento cubre una clave y partición, mientras que diferentes particiones se ejecutan en paralelo. Los productores obtienen metadatos de líderes del plano de control y escriben lotes directamente. Cada partición tiene tres réplicas distribuidas en zonas de disponibilidad; solo dos réplicas duraderas avanzan commit_watermark y confirman al productor. Un nuevo líder debe contener el prefijo confirmado, y las épocas bloquean a líderes y productores antiguos.
El almacenamiento utiliza segmentos de solo adición y un índice disperso de offsets. Los consumidores de grupo poseen particiones de forma exclusiva y realizan sondeo largo. El consumidor confirma un resultado de negocio idempotente antes de confirmar el siguiente offset. Una caída puede reproducir trabajo pero no puede omitirlo silenciosamente. En el lado del productor, la época y la secuencia del productor eliminan reintentos causados por una confirmación perdida. En el lado del consumidor, un ID de mensaje estable, una restricción única o una condición de versión absorbe los efectos repetidos. Afirmaría una transacción de broker de extremo a extremo solo cuando tanto el offset de entrada como la salida residan en esa transacción de broker; los sistemas externos aún necesitan idempotencia o conciliación.
La capacidad constante es de 1 GB/s y 86.4 TB de datos lógicos por día, con un límite inferior de 259.2 TB para escrituras de tres réplicas. Un pico de tres veces durante 15 minutos crea 1.8 TB de retraso acumulado adicional cuando la capacidad del consumidor permanece en estado constante. Si la tasa neta de recuperación posterior al pico es de 0.5 GB/s, vaciarlo toma aproximadamente una hora en teoría. El recuento de particiones utiliza el mayor de los cálculos de tasa de mensajes y tasa de bytes, añade margen para fallas y se calibra en el hardware real.
Los cuerpos de carga útil superiores a 256 KiB ingresan primero al almacenamiento de objetos. La cola retiene una referencia inmutable, el tamaño y la suma de verificación. El TTL de la sesión de carga elimina huérfanos, mientras que una referencia confirmada protege su objeto durante las ventanas de retención, reproducción y mensajes fallidos. Los reintentos preservan el ID de mensaje original. Un tema estrictamente ordenado pausa una clave o partición ante un mensaje venenoso porque enviarlo inmediatamente a la cola de mensajes fallidos permitiría que los mensajes posteriores lo adelanten.
Finalmente, limitaría el ingreso, el egreso, el almacenamiento, las particiones y los objetos grandes por inquilino; aislaría a un inquilino sobrecargado en un grupo dedicado; y monitorearía la latencia de confirmación, publicaciones desconocidas, retraso de réplicas, marcas de agua de disco, antigüedad del consumidor más antigua, claves calientes y mensajes fallidos. Las pruebas de fallas cubren confirmaciones perdidas, caídas de líderes antes y después de la confirmación, pérdida de zona, confirmaciones de offset obsoletas, caídas de consumidores tras escrituras de negocio y fallas de almacenamiento de objetos. Cada prueba verifica el límite de confirmación específico.”
Errores comunes
- **Error: Dibujar solo Productor, Kafka y Consumidor → Falla: Los nombres de los componentes no definen los límites de confirmación, offset,
orden o falla → Solución: Establecer el contrato de entrega y cuatro invariantes, luego mapear cada componente a uno.**
- **Error: Prometer orden global mientras se escala horizontalmente → Falla: El orden global necesita un único punto de decisión serial,
mientras que el paralelismo de particiones elimina ese orden → Solución: Delimitar el orden a la clave de negocio y a la partición y establecer el límite de claves calientes.**
- **Error: Confirmar tras la escritura en el disco local del líder → Falla: Perder la zona de disponibilidad del líder puede eliminar
la única copia duradera → Solución: Confirmar tras una mayoría de confirmación entre zonas y elegir únicamente una réplica con el prefijo confirmado.**
- **Error: Confirmar el offset inmediatamente después de la obtención → Falla: Una caída tras esa confirmación omite permanentemente el resultado
del negocio → Solución: Confirmar primero el resultado de negocio idempotente, luego el siguiente offset, y aceptar la reproducción controlada.**
- **Error: Equiparar exactamente una vez del broker con efectos externos de exactamente una vez → Falla: El sistema externo no se une a
la transacción del broker, por lo que una pérdida de confirmación aún deja una ventana de duplicación → Solución: Utilizar una clave de idempotencia de negocio, restricción única, condición de versión o conciliación.**
- **Error: Enviar inmediatamente a la cola de mensajes fallidos cada mensaje que falla → Falla: Los registros posteriores para la misma clave pueden adelantarlo y romper
el orden del estado → Solución: Permitir que el contrato del tema elija una clave pausada, partición pausada o convergencia basada en versiones.**
- **Error: Escribir una carga útil de 100 MB directamente en el registro del broker → Falla: Unos pocos registros monopolizan la replicación,
los búferes y los lotes de obtención → Solución: Almacenar el cuerpo en el almacenamiento de objetos y registrar su referencia, tamaño y suma de verificación.**
- **Error: Planificar cuotas y capacidad únicamente por recuento de mensajes → Falla: Un registro de 1 KB y uno de 100 MB tienen costos de red,
disco y memoria radicalmente distintos → Solución: Medir recuento, bytes, lotes en tránsito y concurrencia de objetos.**
- **Error: Agregar consumidores para eliminar cualquier retraso → Falla: Un miembro del grupo posee una partición a la vez, y una clave caliente
sigue limitada por la ruta serial de la partición → Solución: Inspeccionar la distribución de particiones y claves antes de agregar particiones, dividir la clave de negocio o aplicar limitación de tasa.**
- **Error: Monitorear solo el tiempo de actividad del broker → Falla: Un clúster activo aún puede tener réplicas retrasadas, discos agotados,
offsets obsoletos y un aumento de mensajes fallidos → Solución: Monitorear latencia segmentada, prefijos confirmados, antigüedad del mensaje más antiguo, tiempo de recuperación y una prueba canario de extremo a extremo.**
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: ¿Cómo proporcionarías cero pérdida de datos entre regiones manteniendo el p99 de publicación por debajo de 50 milisegundos?
La confirmación síncrona entre regiones agrega tiempo de ida y vuelta de red de área amplia a la ruta de publicación. Que 50 milisegundos sea posible depende de la distancia entre regiones y la latencia de cola de la red. El negocio debe priorizar RPO cero frente a la latencia local. Cuando gana RPO cero, una escritura espera por una mayoría de confirmación remota y el SLO de latencia debe reajustarse. Cuando gana la latencia, la replicación es síncrona dentro de la región y asíncrona entre regiones, con un riesgo explícito para la cola no replicada. El esquema activo-activo también necesita un propietario para cada clave o una regla de conflictos; una sola región primaria por tema o rango de claves suele preservar el orden con mayor claridad.
Pregunta de seguimiento 2: Un inquilino tiene una única clave de negocio a 200,000 mensajes por segundo. ¿Por qué 128 particiones no ayudan?
La misma clave debe permanecer en una partición para preservar el orden, por lo que sigue limitada por la tasa evaluada de partición única de aproximadamente 40,000 mensajes por segundo. Las opciones son optimizar la ruta serial, limitar la tasa de ese inquilino o redefinir dominios de orden independientes, como subclaves de entidad que no se afecten entre sí. Si el negocio requiere orden total para esa clave, el servicio debe rechazar una promesa por encima de la capacidad serial. Distribuir aleatoriamente la clave simplemente cambia una falla de capacidad por una falla de ordenamiento.
Pregunta de seguimiento 3: Un consumidor cobró un pago y luego falló antes de confirmar su offset. ¿Cómo evitas un segundo cobro?
Utiliza message_id o un ID de operación de negocio como clave de idempotencia de pago. Si el proveedor de pagos admite una API idempotente, la reproducción utiliza la misma clave y consulta el resultado original. Si solo se controla la base de datos local, confirma el estado del negocio y un registro único de mensaje procesado en una sola transacción, y luego usa un patrón outbox para el paso externo. Cuando el sistema externo no tiene idempotencia ni consulta de estado, registra un estado DESCONOCIDO (UNKNOWN), concilia y compensa manualmente. Confirmar el offset prematuramente solo oculta la incertidumbre aceptando pérdidas.
Pregunta de seguimiento 4: ¿Cómo reenvías un mensaje venenoso de manera segura?
Repara primero el consumidor o los datos, congela el alcance del reenvío y preserva el ID de mensaje original, el offset de origen, la hora en que se vio por primera vez y el historial de intentos. Valida la nueva versión con consumo en la sombra (shadow consumption), luego reproduce a una tasa por inquilino y por partición mientras mantienes activa la idempotencia en el destino. Un tema estrictamente ordenado también pausa los registros posteriores para la clave y reanuda desde el offset fallido en orden. Si el contrato permite reordenamiento, el destino rechaza versiones de negocio antiguas. El reenvío no debe generar un nuevo ID para evitar la desduplicación ni saturar el tema principal durante su pico normal de tráfico.
Pregunta de seguimiento 5: ¿Qué cambia primero cuando la retención pasa de 24 horas a 30 días?
En estado constante, 30 días representan aproximadamente 86.4 × 30 = 2.592 PB de forma lógica. Mantener tres réplicas locales completas tiene un límite inferior cercano a 7.776 PB, haciendo que el costo y el tiempo de recuperación sean dominantes. Mantén los segmentos activos y recientes en los brokers, y carga los segmentos cerrados y verificados al almacenamiento de objetos. Los metadatos registran la ubicación del objeto y la suma de verificación; las extracciones históricas utilizan una caché o proxy de lectura. La eliminación, la reproducción, la compactación y el ciclo de vida de los objetos deben compartir una única máquina de estados de retención para que un segmento local nunca se elimine antes de que su objeto remoto sea legible.