Diferencia entre idempotencia y exactamente una vez en Kafka Stream

8

Estaba revisando el documento que entendí que podemos lograr exactamente una sola transacción con la habilitación idempotence=true

idempotencia: el productor idempotente habilita exactamente una vez para un productor contra un solo tema. Básicamente, cada mensaje enviado tiene garantías más fuertes y no se duplicará en caso de que haya un error

Entonces, si ya tenemos idempotencia, ¿por qué necesitamos otra propiedad exactamente, una vez en Kafka Stream? Qué es exactamente diferente entre la idempotencia frente a exactamente una vez

¿Por qué la propiedad de una sola vez no está disponible en Kafka Producer normal?

Sandeep
fuente
2
Esta publicación de blog también es una buena fuente para obtener más información: medium.com/@andy.bryant/…
Matthias J. Sax

Respuestas:

6

En un entorno distribuido, la falla es un escenario muy común que puede ocurrir en cualquier momento. En el entorno de Kafka, el agente puede fallar, fallas en la red, fallas en el procesamiento, fallas al publicar mensajes o fallas en el consumo de mensajes, etc. Este escenario diferente introdujo diferentes tipos de pérdida y duplicación de datos.

Escenarios de falla

A (Ack Failed): el mensaje publicado por el productor se realizó correctamente con el reintento> 1 pero no se pudo recibir el acuse de recibo debido a un error. En ese caso, el Productor volverá a intentar que el mismo mensaje podría introducir duplicados.

ingrese la descripción de la imagen aquí

B (El proceso del productor falló en los mensajes por lotes): el productor que envió el lote de mensajes falló con pocos resultados publicados. En ese caso, y una vez que el productor se reinicie, volverá a publicar todos los mensajes del lote que introducirá duplicados en Kafka. ingrese la descripción de la imagen aquí

C (Fire & Forget Failed) Mensaje publicado por el productor con reintento = 0 (disparar y olvidar). En caso de falla publicada, no se dará cuenta y enviará el siguiente mensaje, esto causará la pérdida del mensaje. ingrese la descripción de la imagen aquí

D (Error del consumidor en el mensaje por lotes) Un consumidor recibe un lote de mensajes de Kafka y confirma manualmente su desplazamiento (enable.auto.commit = false). Si el consumidor falló antes de comprometerse con Kafka, la próxima vez el Consumidor volverá a consumir los mismos registros que reproducen duplicados en el lado del consumidor.

ingrese la descripción de la imagen aquí

Semántica exactamente una vez

En este caso, incluso si un productor intenta reenviar un mensaje, esto lleva a que el mensaje sea publicado y consumido por el consumidor exactamente una vez.

Para lograr la semántica Exactamente una vez en Kafka, utiliza debajo de 3 propiedades

  1. enable.idempotence = true (dirección a, b & c)
  2. MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION = 5 (El productor siempre tendrá una solicitud en vuelo por conexión)
  3. isolated.level = read_committed (dirección d)

Habilitar idempotente (enable.idempotence = true)

La entrega idempotente permite al productor escribir mensajes a Kafka exactamente una vez a una partición particular de un tema durante la vida útil de un solo productor sin pérdida de datos y orden por partición.

"Tenga en cuenta que habilitar la idempotencia requiere que MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION sea menor o igual a 5, RETRIES_CONFIG sea mayor que 0 y ACKS_CONFIG sea 'todos'. Si el usuario no establece estos valores explícitamente, se elegirán valores adecuados. establecido, se lanzará una ConfigException "

Para lograr la idempotencia, Kafka usa una identificación única que se llama identificación del producto o PID y número de secuencia mientras produce mensajes. El productor sigue incrementando el número de secuencia en cada mensaje publicado que se asigna con un PID único. El intermediario siempre compara el número de secuencia actual con el anterior y rechaza si el nuevo no es +1 mayor que el anterior, lo que evita la duplicación y al mismo tiempo si se muestra una pérdida mayor en los mensajes ingrese la descripción de la imagen aquí

En caso de falla, el agente comparará el número de secuencia con el anterior y si la secuencia no aumenta +1 rechazará el mensaje. ingrese la descripción de la imagen aquí

Transacción (nivel de aislamiento)

Las transacciones nos dan la capacidad de actualizar atómicamente los datos en múltiples particiones de temas. Todos los registros incluidos en una transacción se guardarán con éxito, o ninguno de ellos lo será. Le permite confirmar las compensaciones de sus consumidores en la misma transacción junto con los datos que ha procesado, lo que permite una semántica de extremo a extremo exactamente una vez .

El productor no espera para escribir un mensaje en kafka donde el productor usa beginTransaction, commitTransaction y abortTransaction (en caso de falla) El consumidor usa aislamiento.nivel read_committed o read_uncommitted

  • read_committed: el consumidor siempre leerá solo los datos confirmados.
  • read_uncommitted: lee todos los mensajes en orden de desplazamiento sin esperar a que se confirmen las transacciones

Si un consumidor con aislamiento.level = read_committed llega a un mensaje de control para una transacción que no se ha completado, no entregará más mensajes desde esta partición hasta que el productor confirme o cancele la transacción o se produzca un tiempo de espera de transacción. El productor determina el tiempo de espera de la transacción utilizando la configuración transaction.timeout.ms (valor predeterminado de 1 minuto).

Exactamente una vez en productor y consumidor

En condiciones normales donde tenemos productores y consumidores separados. El productor tiene que administrar las transacciones de forma idempotente y al mismo tiempo para que el consumidor pueda usar el aislamiento. Esto garantiza que el productor siempre se sincronizará con el sistema fuente. Incluso el bloqueo del productor o la transacción cancelada, siempre será coherente y publicará el mensaje o lote de mensaje como unidad una vez.

El mismo consumidor recibirá un mensaje o lote de mensaje como unidad una vez.

En Exactamente una vez, el Productor semántico junto con el Consumidor aparecerán como una operación atómica que operará como una sola unidad. Publique y consuma una vez o sea abortado.

Exactamente una vez en Kafka Stream

Kafka Stream consume mensajes del tema A, procesa y publica mensajes en el Tema B y, una vez publicado, usa commit (el commit se ejecuta principalmente bajo cubierta) para vaciar todos los datos del almacén de estado en el disco.

Exactamente una vez en Kafka Stream hay un patrón de lectura-proceso-escritura que garantiza que estas operaciones se tratarán como operaciones atómicas. Dado que Kafka Stream atiende al productor, al consumidor y a la transacción, Kafka Stream viene con un procesamiento especial de parámetros. Garantía que podría exactamente una vez o al menos una vez, lo que hace que la vida sea fácil de manejar todos los parámetros por separado.

Kafka Streams actualiza atómicamente las compensaciones de los consumidores, las tiendas estatales locales, los temas del registro de cambios de la tienda estatal y los temas de producción para generar temas todos juntos. Si alguno de estos pasos falla, todos los cambios se revierten.

Processing.guarantee: exactamente_una vez que proporciona automáticamente los siguientes parámetros que no necesita establecer explícitamente

  1. isolated.level = read_committed
  2. enable.idempotence = true
  3. MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION = 5
sun007
fuente
12

Kafka stream ofrece la semántica exactamente una vez desde el punto de vista de extremo a extremo (consume de un tema, procesa ese mensaje y luego produce otro tema). Sin embargo, mencionó solo el atributo idempotente del productor . Esa es solo una pequeña parte de la imagen completa.

Deja que exprese esa pregunta de otra manera:

¿Por qué necesitamos la semántica de entrega exactamente una vez en el lado del consumidor mientras ya hemos garantizado la semántica de entrega exactamente una vez en el lado del productor?

Respuesta: Dado que la semántica de entrega de una sola vez no es solo en el paso de producción sino también el flujo completo de procesamiento. Para lograr la entrega semántica exactamente una vez, hay algunas condiciones que deben cumplirse con la producción y el consumo.

Este es el escenario genérico: el proceso A produce mensajes sobre el tema T. Al mismo tiempo, el proceso B intenta consumir mensajes del tema T. Queremos asegurarnos de que el proceso B nunca procese un mensaje dos veces.

Parte del productor: debemos asegurarnos de que los productores nunca produzcan un mensaje dos veces. Podemos usar Kafka Idempotent Producer

Parte del consumidor: aquí está el flujo de trabajo básico para el consumidor:

  • Paso 1: El consumidor extrae el mensaje M con éxito del tema de Kafka.
  • Paso 2: el consumidor intenta ejecutar el trabajo y el trabajo vuelve con éxito.
  • Paso 3: El consumidor confirma el desplazamiento del mensaje a los corredores de Kafka.

Los pasos anteriores son solo un camino feliz. Hay muchos problemas que surgen en la realidad.

  • Escenario 1: el trabajo en el paso 2 se ejecuta con éxito pero luego el consumidor se bloquea. Desde esta circunstancia inesperada, el consumidor aún no ha comprometido la compensación del mensaje. Cuando el consumidor se reinicia, el mensaje se consumirá dos veces.
  • Escenario 2: mientras el consumidor confirma el desplazamiento en el paso 3, se bloquea debido a fallas de hardware (por ejemplo: CPU, violación de la memoria, ...) Al reiniciar, el consumidor no tiene forma de saber que ha realizado el desplazamiento con éxito o no.

Debido a que pueden ocurrir muchos problemas, la ejecución del trabajo y la compensación de compromiso deben ser atómicas para garantizar exactamente una vez la entrega semántica en el lado del consumidor. No significa que no podamos, pero se necesita mucho esfuerzo para garantizar la entrega semántica de una vez. Kafka Stream defiende el trabajo para los ingenieros.

Señaló que: Kafka Stream ofrece "procesamiento de flujo exactamente una vez". Se refiere a consumir de un tema, materializar el estado intermedio en un tema de Kafka y producir uno. Si nuestra aplicación depende de algunos otros servicios externos (base de datos, servicios ...), debemos asegurarnos de que nuestras dependencias externas puedan garantizar exactamente una vez en esos casos.

TL, DR: exactamente una vez para el flujo completo necesita la cooperación entre productores y consumidores.

Referencias

hqt
fuente
No lo llamaría entrega , porque la entrega generalmente implica la frecuencia con la que se lee / envía un mensaje, y exactamente una vez en Kafka, obviamente, se retira internamente en caso de falla. No es posible entregar exactamente una vez (es decir, con qué frecuencia se envía realmente un mensaje a través de la red) (cf en.wikipedia.org/wiki/Byzantine_fault y en.wikipedia.org/wiki/Two_Generals%27_Problem )
Matthias J. Sax
Si. Como se menciona en la respuesta, es cierto que Kafka Stream no ofrece una entrega exactamente única en el término general. Sobre dos problemas generales, no podemos tener una sola vez general en el sistema distribuido, pero es factible cuando perdemos algunas condiciones o agregamos algunas más al sistema. Por ejemplo: tiempo de espera. Sin embargo, esta es la historia diferente.
hqt
Bueno, simplemente no usaría el término entrega , sino que seguiría con la semántica .
Matthias J. Sax