Как Kafka стала Π±Ρ‹Π»ΡŒΡŽ

Как Kafka стала Π±Ρ‹Π»ΡŒΡŽ

ΠŸΡ€ΠΈΠ²Π΅Ρ‚, Π₯Π°Π±Ρ€!

Π― Ρ€Π°Π±ΠΎΡ‚Π°ΡŽ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Tinkoff, которая занимаСтся Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ собствСнного Ρ†Π΅Π½Ρ‚Ρ€Π° Π½ΠΎΡ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΉ. По большСй части я Ρ€Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽ Π½Π° Java с использованиСм Spring boot ΠΈ Ρ€Π΅ΡˆΠ°ΡŽ Ρ€Π°Π·Π½Ρ‹Π΅ тСхничСскиС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‰ΠΈΠ΅ Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅.

Π‘ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ Π½Π°ΡˆΠΈΡ… микросСрвисов асинхронно Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ Ρ‡Π΅Ρ€Π΅Π· Π±Ρ€ΠΎΠΊΠ΅Ρ€ сообщСний. Π Π°Π½Π΅Π΅ Π² качСствС Π±Ρ€ΠΎΠΊΠ΅Ρ€Π° ΠΌΡ‹ использовали IBM MQ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСстал ΡΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒΡΡ с Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ, Π½ΠΎ ΠΏΡ€ΠΈ этом ΠΎΠ±Π»Π°Π΄Π°Π» высокими гарантиями доставки.

Π’ качСствС Π·Π°ΠΌΠ΅Π½Ρ‹ Π½Π°ΠΌ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠΈΠ»ΠΈ Apache Kafka, которая ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ высоким ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΠΎΠΌ ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ, Π½ΠΎ, ΠΊ соТалСнию, Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ практичСски ΠΈΠ½Π΄ΠΈΠ²ΠΈΠ΄ΡƒΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΠΊ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ для Ρ€Π°Π·Π½Ρ‹Ρ… сцСнариСв. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ at least once delivery, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΠΈΠΉ Π² Kafka ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π½Π΅ позволял ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΉ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ консистСнтности ΠΈΠ· ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΈ. Π”Π°Π»Π΅Π΅ я подСлюсь нашим ΠΎΠΏΡ‹Ρ‚ΠΎΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ Kafka, Π² частности расскаТу, ΠΊΠ°ΠΊ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΈ ΠΆΠΈΡ‚ΡŒ с exactly once delivery.

Гарантированная доставка ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹, ΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΏΠΎΠΉΠ΄Π΅Ρ‚ Ρ€Π΅Ρ‡ΡŒ Π΄Π°Π»Π΅Π΅, ΠΏΠΎΠΌΠΎΠ³ΡƒΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ ряд ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с настройками ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Но сначала хочСтся ΡƒΠ΄Π΅Π»ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠΌΡƒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρƒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠ±Π»Π΅Π³Ρ‡ΠΈΡ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹ΠΉ Π΄Π΅Π±Π°Π³.

Π’ этом ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ client.id для Producer ΠΈ Consumer. На ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ взгляд, Π² качСствС значСния ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ имя прилоТСния, ΠΈ Π² Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ случаСв это Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ. Π₯отя ситуация, ΠΊΠΎΠ³Π΄Π° Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ нСсколько Consumer’ов ΠΈ Π²Ρ‹ Π·Π°Π΄Π°Π΅Ρ‚Π΅ ΠΈΠΌ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΉ client.id, ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌΡƒ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΡŽ:

org.apache.kafka.common.utils.AppInfoParser β€” Error registering AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0

Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ JMX Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ с Kafka, Ρ‚ΠΎ это ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ. Для этого случая Π»ΡƒΡ‡ΡˆΠ΅ всСго ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² качСствС значСния client.id ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΡŽ ΠΈΠ· ΠΈΠΌΠ΅Π½ΠΈ прилоТСния ΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΈΠΌΠ΅Π½ΠΈ Ρ‚ΠΎΠΏΠΈΠΊΠ°. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ нашСй ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π² Π²Ρ‹Π²ΠΎΠ΄Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ kafka-consumer-groups ΠΈΠ· ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ ΠΎΡ‚ Confluent:

Как Kafka стала Π±Ρ‹Π»ΡŒΡŽ

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ сцСнарий Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ доставки сообщСния. Π£ Kafka Producer Π΅ΡΡ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ acks, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒ, послС ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… acknowledge Π»ΠΈΠ΄Π΅Ρ€Ρƒ кластСра Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ сообщСниС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ записанным. Π­Ρ‚ΠΎΡ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ значСния:

  • 0 β€” acknowledge Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒΡΡ.
  • 1 β€” ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ acknowledge Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΡ‚ 1 Ρ€Π΅ΠΏΠ»ΠΈΠΊΠΈ.
  • βˆ’1 β€” Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ acknowledge ΠΎΡ‚ всСх синхронизированных Ρ€Π΅ΠΏΠ»ΠΈΠΊ (настройка кластСра min.insync.replicas).

Из пСрСчислСнных Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ acks Ρ€Π°Π²Π½Ρ‹ΠΉ βˆ’1 Π΄Π°Π΅Ρ‚ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΡΠΈΠ»ΡŒΠ½Ρ‹Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ, Ρ‡Ρ‚ΠΎ сообщСниС Π½Π΅ потСряСтся.

Как ΠΌΡ‹ всС Π·Π½Π°Π΅ΠΌ, распрСдСлСнныС систСмы Π½Π΅Π½Π°Π΄Π΅ΠΆΠ½Ρ‹. Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎΡ‚ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… нСисправностСй, Kafka Producer прСдоставляСт ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ retries, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ количСство ΠΏΠΎΠΏΡ‹Ρ‚ΠΎΠΊ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ delivery.timeout.ms. Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ retries ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Integer.MAX_VALUE (2147483647), количСство ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½Ρ‹Ρ… ΠΎΡ‚ΠΏΡ€Π°Π²ΠΎΠΊ сообщСния ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π³ΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, мСняя Ρ‚ΠΎΠ»ΡŒΠΊΠΎ delivery.timeout.ms.

ДвиТСмся ΠΊ exactly once delivery

ΠŸΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»Π΅Π½Π½Ρ‹Π΅ настройки ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π½Π°ΡˆΠ΅ΠΌΡƒ Producer’у Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ сообщСния с высокой Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠ΅ΠΉ. Π”Π°Π²Π°ΠΉΡ‚Π΅ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ запись Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠΎΠΏΠΈΠΈ сообщСния Π² Kafka-Ρ‚ΠΎΠΏΠΈΠΊ? Π’ самом простом случаС для этого Π½Π° Producer Π½ΡƒΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ enable.idempotence Π² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ true. Π˜Π΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ запись Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄Π½ΠΎΠ³ΠΎ сообщСния Π² ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΡŽ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΎΠΏΠΈΠΊΠ°. ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ условиСм для Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ идСмпотСнтности ΡΠ²Π»ΡΡŽΡ‚ΡΡ значСния acks = all, retry > 0, max.in.flight.requests.per.connection ≀ 5. Если эти ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π½Π΅ Π·Π°Π΄Π°Π½Ρ‹ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠΌ, Ρ‚ΠΎ автоматичСски Π±ΡƒΠ΄ΡƒΡ‚ выставлСны ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Π΅ Π²Ρ‹ΡˆΠ΅ значСния.

Когда ΠΈΠ΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ настроСна, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ сообщСния ΠΏΠΎΠΏΠ°Π΄Π°Π»ΠΈ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· Π² ΠΎΠ΄Π½ΠΈ ΠΈ Ρ‚Π΅ ΠΆΠ΅ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, настраивая ΠΊΠ»ΡŽΡ‡ ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ partitioner.class Π½Π° Producer. Π”Π°Π²Π°ΠΉΡ‚Π΅ Π½Π°Ρ‡Π½Π΅ΠΌ с ΠΊΠ»ΡŽΡ‡Π°. Для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ. Π­Ρ‚ΠΎΠ³ΠΎ Π»Π΅Π³ΠΊΠΎ Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΊΠ°ΠΊΠΎΠΉ-Π»ΠΈΠ±ΠΎ бизнСс-ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΈΠ· ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ сообщСния. ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ partitioner.class ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ β€” DefaultPartitioner. ΠŸΡ€ΠΈ этой стратСгии партиционирования ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ дСйствуСм Ρ‚Π°ΠΊ:

  • Если партиция явно ΡƒΠΊΠ°Π·Π°Π½Π° ΠΏΡ€ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ΅ сообщСния, Ρ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π΅Π΅.
  • Если партиция Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Π°, Π½ΠΎ ΡƒΠΊΠ°Π·Π°Π½ ΠΊΠ»ΡŽΡ‡ β€” Π²Ρ‹Π±ΠΈΡ€Π°Π΅ΠΌ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΡŽ ΠΏΠΎ Ρ…ΡΡˆΡƒ ΠΎΡ‚ ΠΊΠ»ΡŽΡ‡Π°.
  • Если партиция ΠΈ ΠΊΠ»ΡŽΡ‡ Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ β€” Π²Ρ‹Π±ΠΈΡ€Π°Π΅ΠΌ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ ΠΏΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ (round-robin).

ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, использованиС ΠΊΠ»ΡŽΡ‡Π° ΠΈ ΠΈΠ΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ max.in.flight.requests.per.connection = 1 Π΄Π°Π΅Ρ‚ Π²Π°ΠΌ ΡƒΠΏΠΎΡ€ΡΠ΄ΠΎΡ‡Π΅Π½Π½ΡƒΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ сообщСний Π½Π° Consumer. ΠžΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ стоит ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ, Ссли Π½Π° вашСм кластСрС настроСно ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ доступом, Ρ‚ΠΎ Π²Π°ΠΌ понадобятся ΠΏΡ€Π°Π²Π° Π½Π° ΠΈΠ΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΡƒΡŽ запись Π² Ρ‚ΠΎΠΏΠΈΠΊ.

Если Π²Π΄Ρ€ΡƒΠ³ Π²Π°ΠΌ Π½Π΅ Ρ…Π²Π°Ρ‚Π°Π΅Ρ‚ возмоТностСй ΠΈΠ΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΏΠΎ ΠΊΠ»ΡŽΡ‡Ρƒ ΠΈΠ»ΠΈ Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π° сторонС Producer Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ сохранСния консистСнтности Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ партициями, Ρ‚ΠΎ Π½Π° ΠΏΠΎΠΌΠΎΡ‰ΡŒ ΠΏΡ€ΠΈΠ΄ΡƒΡ‚ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ†Π΅ΠΏΠ½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ условно ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ запись Π² Kafka, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, с записью Π² Π‘Π”. Для Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π½ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π½Π° Producer Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ ΠΎΠ±Π»Π°Π΄Π°Π» ΠΈΠ΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒΡŽ, ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ transactional.id. Если Π½Π° вашСм Kafka-кластСрС настроСно ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ доступом, Ρ‚ΠΎ для Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π½ΠΎΠΉ записи, ΠΊΠ°ΠΊ ΠΈ для ΠΈΠ΄Π΅ΠΌΠΏΠΎΡ‚Π΅Π½Ρ‚Π½ΠΎΠΉ, понадобятся ΠΏΡ€Π°Π²Π° Π½Π° запись, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ прСдоставлСны ΠΏΠΎ маскС с использованиСм значСния, хранящСгося Π² transactional.id.

Π€ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎ Π² качСствС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π»ΡŽΠ±ΡƒΡŽ строку, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ имя прилоТСния. Но Ссли Π²Ρ‹ запускаСтС нСсколько инстансов ΠΎΠ΄Π½ΠΎΠ³ΠΎ прилоТСния с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ transactional.id, Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹ΠΉ инстанс Π±ΡƒΠ΄Π΅Ρ‚ остановлСн с ошибкой, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Kafka Π±ΡƒΠ΄Π΅Ρ‚ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π΅Π³ΠΎ Π·ΠΎΠΌΠ±ΠΈ-процСссом.

org.apache.kafka.common.errors.ProducerFencedException: Producer attempted an operation with an old epoch. Either there is a newer producer with the same transactionalId, or the producer's transaction has been expired by the broker.

Π§Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, ΠΌΡ‹ добавляСм ΠΊ ΠΈΠΌΠ΅Π½ΠΈ прилоТСния суффикс Π² Π²ΠΈΠ΄Π΅ ΠΈΠΌΠ΅Π½ΠΈ хоста, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΈΠ· ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… окруТСния.

Producer настроСн, Π½ΠΎ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ Π½Π° Kafka ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ видимости сообщСния. Π’Π½Π΅ зависимости ΠΎΡ‚ статуса Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, сообщСниС сразу ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² Ρ‚ΠΎΠΏΠΈΠΊ, Π½ΠΎ ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ систСмными Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌΠΈ.

Π§Ρ‚ΠΎΠ±Ρ‹ Ρ‚Π°ΠΊΠΈΠ΅ сообщСния Π½Π΅ ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Π»ΠΈΡΡŒ Consumer’ом Ρ€Π°Π½ΡŒΡˆΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Π΅ΠΌΡƒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ isolation.level Π² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ read_committed. Π’Π°ΠΊΠΎΠΉ Consumer смоТСт Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π½Π΅Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π½Ρ‹Π΅ сообщСния ΠΊΠ°ΠΊ ΠΈ Ρ€Π°Π½ΡŒΡˆΠ΅, Π° Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π½Ρ‹Π΅ β€” Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС ΠΊΠΎΠΌΠΌΠΈΡ‚Π°.
Если Π²Ρ‹ установили всС пСрСчислСнныС Ρ€Π°Π½Π΅Π΅ настройки, Ρ‚ΠΎ Π²Ρ‹ настроили exactly once delivery. ΠŸΠΎΠ·Π΄Ρ€Π°Π²Π»ΡΡŽ!

Но Π΅ΡΡ‚ΡŒ Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ нюанс. Transactional.id, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ настраивали Π²Ρ‹ΡˆΠ΅, Π½Π° самом Π΄Π΅Π»Π΅ являСтся прСфиксом Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ. На ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π΅ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ ΠΊ Π½Π΅ΠΌΡƒ дописываСтся порядковый Π½ΠΎΠΌΠ΅Ρ€. ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ выдаСтся Π½Π° transactional.id.expiration.ms, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ конфигурируСтся Π½Π° Kafka кластСрС ΠΈ ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Β«7 Π΄Π½Π΅ΠΉΒ». Если Π·Π° это врСмя ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π»ΠΎ Π½ΠΈΠΊΠ°ΠΊΠΈΡ… сообщСний, Ρ‚ΠΎ ΠΏΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π½ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ InvalidPidMappingException. ПослС этого ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΎΡ€ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ выдаст Π½ΠΎΠ²Ρ‹ΠΉ порядковый Π½ΠΎΠΌΠ΅Ρ€ для ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ. ΠŸΡ€ΠΈ этом сообщСниС ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ потСряно, Ссли InvalidPidMappingException Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½.

ВмСсто ΠΈΡ‚ΠΎΠ³ΠΎΠ²

Как ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, нСдостаточно просто ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ сообщСния Π² Kafka. НуТно Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΡŽ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΈ Π±Ρ‹Ρ‚ΡŒ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΌ ΠΊ внСсСнию быстрых ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ. Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ я постарался Π² дСталях ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ настройку exactly once delivery ΠΈ описал нСсколько ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΉ client.id ΠΈ transactional.id, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ ΠΌΡ‹ ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΠ»ΠΈΡΡŒ. НиТС Π² ΠΊΡ€Π°Ρ‚ΠΊΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Ρ‹ настройки Producer ΠΈ Consumer.

Producer:

  1. acks = all
  2. retries > 0
  3. enable.idempotence = true
  4. max.in.flight.requests.per.connection ≀ 5 (1 β€” для упорядочСнной ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ)
  5. transactional.id = ${application-name}-${hostname}

Consumer:

  1. isolation.level = read_committed

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ошибки Π² Π±ΡƒΠ΄ΡƒΡ‰ΠΈΡ… прилоТСниях, ΠΌΡ‹ сдСлали свою ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΡƒ Π½Π°Π΄ spring-ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠ΅ΠΉ, Π³Π΄Π΅ ΡƒΠΆΠ΅ Π·Π°Π΄Π°Π½Ρ‹ значСния для Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΈΠ· пСрСчислСнных ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ².

А Π²ΠΎΡ‚ ΠΏΠ°Ρ€Π° ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² для ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ изучСния:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ