일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 자바
- node.js
- 개발이 취미인 사람
- Sequelize
- spring boot
- It
- state
- 반복문
- component
- swagger
- front-end
- class
- vue
- javascript
- restful api
- Kotlin
- Producer
- Nest.js
- java
- 상속
- SWIFT
- 조건문
- AWS
- back-end
- react
- file upload
- 개발자
- kafka
- 코틀린
- props
- Today
- Total
개발이 취미인 사람
[Kafka] - Producer 메시지 전송 방식 본문
개요
안녕하세요. 이번 시간에는 Kafka를 사용하면서 중복 없는 메시지 전송 방식에 대해 알아보겠습니다.
이전 시간에 Kafka Producer에 대해 알아봤습니다. 혹시 놓치신 분들은 아래 링크를 통해 학습하고 오시는 걸 추천드리겠습니다.
[Kafka] - Kafka Producer 메시지 생성
개념
Kafka를 사용하다 보면 자주 고려해야 하는 상황이 있습니다. 메시지가 중복으로 발송되면 어떻게 처리하지?...
Kafka는 주로 높은 처리량과 낮은 레이턴시를 보장하기 위해 성능적인 측면을 많이 고려했습니다.
그렇다고 메시지를 유실되거나 메시지 중복 이슈가 발생한다면 데이터 정합성이 중요한 서비스에는 적합하지 않다고 생각할 수 있습니다.
기본적으로 Kafka는 최소 한번 전송(At-Least-One)을 보장하며, 이 경우 중복 메시지가 발생할 수 있습니다.
그렇기 때문에 멱등성 옵션을 활용해서 중복 메시지 이슈를 해결할 수 있습니다. 다만 오해를 할 수 있는 부분은 중복 없는 전송 방식은 정확히 한번만 전송한다는 의미가 아닙니다.
멱등성이란 무엇일까요?
멱등성이란 동일한 작업을 여러 번 수행하더라도 결과가 달라지지 않는 것을 의미합니다.
메시지 시스템들의 메시지 전송 방식은 다음과 같습니다.
- 최소 한번 전송(At-Least-One)
- 최대 한번 전송(At-Most-One)
- 중복 없는 전송(Duplicate-Free)
- 정확히 한번 전송(Exactly-One)
이번 시간에는 1, 2, 3 번에 대해 알아보겠습니다. (4번 항목은 예시가 많이 필요해서요.)
최소 한번 전송(At-Least-One)
최초 한 번 전송은 브로커가 전달받은 메시지를 쓰기를 성공했지만 장애가 발생해서 프로듀서에게 ACK를 전달하지 못해서 메시지를 다시 전송하는 상황입니다.
최소 한번 전송 프로세스는 다음과 같습니다.
- 프로듀서는 브로커의 특정 토픽에 메시지 1을 전송합니다.
- 브로커는 메시지 1을 기록하고, 성공했음을 알리는 ACK를 프로듀서에게 응답합니다.
- 브로커의 ACK를 받은 프로듀서는 다음 메시지인 메시지 2를 브로커에게 전송합니다.
- 브로커는 메시지 2를 기록하고, 성공했음을 알리는 ACK를 프로듀서에게 전송하려고 했지만 네트워크 오류 또는 브로커 장애가 발생해서 프로듀서는 메시지 2에 대한 ACK 정보를 받지 못합니다.
- 메시지 2를 전송한 후 브로커로부터 ACK 정보를 받지 못한 프로듀서는 브로커가 메시지 2를 받지 못했다고 판단해 메시지 2를 다시 전송합니다.
위 상황은 다음과 같은 상황에 코드로 재현이 가능합니다.
/**
* @author Ryan
* @description 동기 전송
*/
public void sendSynchronousMessage(String topic, String key, Object message) {
try {
//최초 발송
kafkaTemplate.send(topic, key, message).get();
} catch (InterruptedException | ExecutionException e) {
try {
//재전송
kafkaTemplate.send(topic, key, message).get();
} catch (InterruptedException | ExecutionException e) {
//재전송 실패시 무시
...
}
}
}
동기 방식을 통해 ACK 정보를 기다렸다가 만약 실패하면 catch 구문에서 재전송을 진행합니다. 위와 같은 상황이라면 중복 이슈가 발생합니다.
최대 한번 전송(At-Most-One)
최대 한번 전송은 브로커에 ACK 응답 값을 무시하고 다음 메시지를 발송하는 방식입니다. 브로커에 전송한 메시지가 올바르게 쓰기가 발생했다면 문제가 없지만 만약 그렇지 못한 상황이라면 데이터 유실이 발생합니다.
최대 한번 전송 프로세스는 다음과 같습니다.
- 프로듀서가 브로커의 특정 토픽에 메시지 1을 전송합니다.
- 브로커는 메시지 1을 기록하고, 성공했음을 알리는 ACK를 프로듀서에게 응답합니다.
- 프로듀서는 다음 메시지인 메시지 2를 브로커에게 전송합니다.
- 브로커는 메시지 2를 기록하지 못하고, 성공했음을 알리는 ACK를 프로듀서에게 전송하지 못합니다.
- 프로듀서는 브로커가 메시지 2를 전달받았다고 가정하고, 메시지 3을 전송합니다.
위 상황은 다음과 같은 상황에 코드로 재현이 가능합니다.
/**
* @author Ryan
* @description 비동기 전송
*/
public void sendAsynchronousMessage(String topic, String key, Object message) {
kafkaTemplate.send(topic, key, message);
}
위 두 상황을 다시 한번 정리하면 다음과 같습니다.
- 최소 한 번 전송은 메시지 손실 가능성은 없지만 메시지 중복 이슈가 존재합니다.
- 최대 한 번 전송은 메시지 손실 가능성이 있지만 메시지 중복 이슈는 존재하지 않습니다.
Kafka는 0.11 버전에서는 프로듀서가 메시지를 중복 없이 브로커에게 전송할 수 있는 기능이 추가 됐습니다.
중복 없는 전송 (Duplicate-Free Delivery)
중복 없는 전송은 메시지를 전송할 때 Header에 Producer Id 와 메시지 번호 포함해서 발송합니다.
중복 없는 전송 전송 프로세스는 다음과 같습니다.
- 프로듀서가 브로커의 특정 토픽으로 메시지 1을 전송합니다. 이때 PID(Producer Id) 0과 메시지 번호 0을 헤더에 포함해 함께 전송합니다.
- 브로커는 메시지 A를 저장하고, PID와 메시지 번호 0을 메모리에 기록합니다. 그리고 메시지를 잘 받았다는 ACK를 프로듀서에게 응답합니다.
- 프로듀서는 다음 메시지인 메시지 2를 브로커에게 전송합니다. PID는 동일하게 0이고 메시지 번호는 1이 증가하여 1이 됩니다.
- 브로커는 메시지 B를 저장하고, PID와 메시지 번호 1을 메모리에 기록합니다. 그리고 메시지를 잘 받았다는 ACK를 프로듀서에게 전송하려고 합니다. 하지만 네트워크 오류 또는 브로커 장애가 발생하여 프로듀서는 메시지 2의 대한 ACK를 받지 못했습니다.
- 브로커로부터 ACK를 받지 못한 프로듀서는 브로커가 메시지 2를 받지 못했다고 판단해 메시지 2를 재전송합니다.
위 내용은 최소 한번 전송과 동일합니다. 하지만 다른 차이는 모두 알수 있듯 헤더에 PID 값과 메시지 번호를 전달하고 비교해서 중복 메시지를 처리하는 것 입니다.
프로듀서 옵션값설명
프로듀서 옵션 | 값 | 설명 |
enable.idempotence | true | 프로듀서가 중복 없는 전송을 허용할지 결정하는 옵션입니다. 기본 값은 false 이므로, 이 옵션을 설정하기 원한다면 true로 변경해야 합니다. true로 변경 시 다음에 나오는 옵션들도 반드시 변경해야합니다. 그렇지 않으면 ConfigException이 발생합니다. |
max.in.flight.requests.per.connection | 1 ~ 5 | ACK를 받지 않은 상태에서 하나의 커넥션에서 보낼 수 있는 최대 요청수 입니다. 중복 없는 전송을 보장하려면 5 이하로 설정해야 합니다. 더 높은 값은 메시지의 순서를 보장하지 못할 수 있습니다. |
acks | all | 브로커가 메시지를 모든 복제본에 기록한 후에만 성공을 응답하게 합니다. 높은 신뢰성을 보장하여 메시지 손실을 방지합니다. |
retries | 5 | 프로듀서가 실패한 요청을 무한히 재시도하도록 설정하여, 브로커와의 일시적인 네트워크 문제로 인한 메시지 손실을 방지합니다. |
기존에 최소 한번 전송(At-Least-One), 최대 한번 전송(At-Most-One) 방식들과 다르게 중복 없는 전송 방식은 로그 세그먼트에서 새로운 파일이 생성됩니다.
xxx.snapshot 이라는 파일이 생성이 되는데요 해당 파일을 확인하면 PID(Producer Id)와 메시지 번호가 존재하게 됩니다.
이번 시간에는 최소 한번 전송(At-Least-One), 최대 한번 전송(At-Most-One), 중복 없는 전송(Duplicate-Free)에 대해 알아봤습니다.
모르는 내용은 댓글을 달아주시면 감사하겠습니다.
'백앤드(Back-End) > Kafka' 카테고리의 다른 글
[Kafka] - Consumer 스태틱 맴버십 (1) | 2024.11.02 |
---|---|
[Kafka] - Consumer 그룹 코디네이터 (0) | 2024.10.30 |
[Kafka] - Broker 컨트롤러(Controller) (2) | 2024.10.18 |
[Kafka] - Broker 리플리케이션(Replication) 동작 원리 (0) | 2024.10.15 |
[Kafka] - Broker 메시지 복제와 커밋 ISR(In Sync Replica) (0) | 2024.08.02 |