[Kafka] Message Processing guarantees
에러에 따른 시스템 동작에 의해 메세지가 한번에 하나씩 처리되지 않을수있으며, 유실될수도 있고 중복될수도있다.
그리고 에러상황은 다음과 같다
1. Producer failure
- 생산자 장애는 생산자가 메시지를 전송하는 도중에 발생하는 상황을 의미함.
- 예를 들어, 생산자가 네트워크 오류나 시스템 장애 등으로 인해 메시지를 정상적으로 전송하지 못하는 경우임.
→ 이러한 경우에는 메시지가 손실될 수 있으며, 장애가 복구되더라도 해당 메시지를 다시 전송해야 할 수 있음.
2. Consumer publish remote call failure
- 소비자의 원격 호출 실패는 소비자가 원격 시스템에 대한 호출을 수행하는 중에 발생하는 오류를 의미함.
- 예를 들어, 소비자가 데이터를 처리한 후 외부 시스템으로 결과를 전송하는 도중에 오류가 발생하는 경우임.
→ 이러한 실패는 데이터의 일관성과 정확성에 영향을 줄 수 있으며,
실패를 처리하고 재시도하여 데이터의 정확한 전달을 보장해야 합니다.
3. Messaging system failure
- 메시징 시스템 장애는 분산 메시징 시스템 자체에 장애가 발생하는 상황을 의미함.
- 이는 메시지의 전송, 저장, 복제, 라우팅 등과 관련된 문제로 인해 발생할 수 있습니다.
- 메시징 시스템 장애는 메시지의 손실, 지연 또는 중복 등을 야기할 수 있음
4. Consumer processing failure
- 소비자 처리 장애는 소비자가 메시지를 처리하는 도중에 발생하는 상황을 의미함.
- 이는 소비자 애플리케이션의 버그, 예외 처리 부족, 외부 의존성 오류 등으로 인해 발생할 수 있음
- 처리 실패는 데이터의 일관성과 정확성에 영향을 줄 수 있으며,
실패를 처리하고 복구하여 메시지의 정확한 처리를 보장해야함
Message Processing Guarantee 방식
실시간 메시지 처리 및 전송 관점에서 시스템의 보장 방식에는 크게 4가지가 존재
1. No guarantee
- 특정 메시지가 한 번, 여러 번 또는 전혀 처리되지 않을 수 있다는 것을 의미함.
- 메시지를 데이터베이스에 저장한 다음 애플리케이션이 진행 상태를 저장하기 전에 충돌이 발생하면, 다음 실행에서 해당 메시지를 다시 처리하고 데이터베이스에 두 번 저장하게 됩니다.
☞ Consumer publish remote call failure
- 결과를 데이터베이스에 저장하기 전에 진행 상태를 저장한 후 프로그램이 충돌하는 경우(enable.auto.commit = true, offset 저장 중 프로그램 충돌) → 다음 실행에서 메시지는 처리되지 않으므로 데이터 손실이 발생
2. At most once
- 메시지가 정확히 한 번 처리되거나 전혀 처리되지 않는다는 것을 의미
- 일반적인 예는 프로듀서가 'fire-and-forget' 접근 방식을 사용하여 메시지를 Kafka에 보내는 경우
- 진행 속도가 완전성보다 우선 되는 경우에 유용
- Producer는 Broker로부터의 응답을 무시하며 재시도를 하지 않고 메시지를 Kafka에 보냄
- Producer는 먼저 소스 시스템에서 읽은 데이터의 진행 상태를 저장한 다음 Kafka로 데이터를 기록 → 두 번째 단계 이전에 Producer가 충돌하면 데이터는 Kafka로 전달되지 않으며, 해당 메시지 대해 재시도도 하지 않음
☞ Producer failure
- Consumer는 Kafka로부터 메시지 일괄 처리를 받아서 이를 변환한 후 결과를 데이터베이스에 기록 → Consumer 애플리케이션은 enable.auto.commit을 false로 설정하고 오프셋을 데이터베이스에 기록하기 전에 Kafka로 오프셋을 커밋하도록 프로그래밍되어 있을 때 → Consumer가 오프셋을 커밋 후 데이터를 데이터베이스에 기록하는 단계에서 에러가 발생할 경우, 다음 실행 때 해당 레코드는 건너뜀에 따라 데이터가 손실됨
☞ Consumer processing failure
3. At least once
- 모든 메시지를 확실히 받고 처리하지만, 장애 상황에서는 일부 메시지를 중복 처리할 수 있다는 것을 의미
- Producer에서 카프카로 데이터를 일괄적을 보내 후 카프카로 부터 응답을 받지 못한 경우 다시 보내게 될 경우 → 첫 번째 일괄 처리가 성공적으로 저장되었어도, 응답이 손실되어 메시지가 두 번 추가됨
☞ Producer failure
- 파일 처리 중간에서 에러로 인해 프로세스가 중단되고 다시 실행될 경우, 다시 시작된 프로세스는 처음부터 다시 처리하게 되고, 이 경우 처음부터 에러가 발생한 부분 까지 Kafka에 중복으로 저장되게 됨
☞ Messaging system failure
- Consumer 애플리케이션은 enable.auto.commit을 false로 설정하고 데이터베이스 쓰기가 성공한 후에만 오프셋을 Kafka로 커밋하도록 프로그래밍되어 있을 경우
-> Consumer가 데이터를 데이터베이스에 기록한 후에 Kafka로 오프셋을 저장하기 전에 실패하면, 다음 실행 때 같은 레코드를 다시 처리하고 데이터베이스에 다시 저장
☞ Consumer processing failure
4. Exactly once(Effectively once)
- 많은 분산 메시징 시스템(Pulsar, Prevega 등) 및 데이터 처리 시스템(Kafka Streams, Spark, Flink, Delta Lake, Cloud Dataflow 등)은 특정 시나리오에서 Exactly once(또는Effectively once)의 시맨틱을 제공함
- 2017년에 Confluent는 Apache Kafka 0.11에 Exactly once를 소개하였는데 아이덤토성 쓰기(idempotent writes)와 트랜잭션으로 가능함
Idempotent writes(Idempotent producer)와 Transaction
1. Idempotent writes(Iempotent producer)
- 같은 요청을 여러 번 전송해도 결과가 변하지 않는 성질을 갖는 쓰기 작업
- enable.idempotence 구성 플래그를 true로 설정하여 이를 수행할 수 있다
- idempotence가 활성화된 상태에서 프로듀서는 각 레코드 일괄 처리와 함께 Kafka 클러스터가 프로듀서를 식별하는 데 도움을 주는 P(Producer)ID와 일련 번호(sequence number)를 전송
- Broker가 새로운 레코드 일괄 처리를 수신하면, 제공된 일련 번호와 PID가 이미 커밋한 번호인 경우 해당 일괄 처리는 재시도로 처리되고 무시됩니다
- Kafka 1.0.0부터는 동일한 프로듀서로부터 최대 5개의 동시 요청(max.in.flight.requests.per.connection=5)을 지원
- 최대 5개의 인플라이트 요청을 가지고 있으면서도 이러한 요청이 올바른 순서로 로그에 기록될 수 있음
2. Transaction(추가 공부 후 정리 필요)
- 토픽 내 여러 파티션에 대한 데이터 업데이트를 한 번에 처리하는 기능
- Transaction을 사용하려면 먼저 Producer 설정에서 idempotent writes를 활성화(enable.idempotence=true)하고, Transaction ID (transactional.id=my-tx-id)를 지정해야 함
→ Transaction ID는 프로듀서를 고유하게 식별하는 역할을 합니다
- Producer는 Kafka는 initTransactions메소드를 호출하여 kafka 클러스터에 자신을 등록함
- initTransactions메소드에는 프로듀서에 Transaction ID를 할당하는 과정이 있다
- 동일한 Transaction ID로 재연결할 때, 프로듀서는 이전과 동일한 식별자(PID)를 할당받으며 해당 PID와 관련 Epoch Number가 증가함
- Kafka는 이전 세션에서 대기 중인 Transaction을 커밋하거나 중단한 후에만 프로듀서가 새로운 데이터를 전송할 수 있도록 보장함
- 이전 Epoch Number를 가진 오래된 Producer가 작업을 수행하려고 시도하면 실패함