Kafka는 수많은 기업들에서 사용하고 있는 기술스택이다
그렇다면 왜 많이 사용할까?
그 답은, 카프카를 만든 링크드인을 보면 어느정도 알 수 있다.
(현재는 Apache 재단에서 관리되고 있다고 한다)
이 이미지는 카프카가 도입되기 전 링크드 인의 데이터 처리 시스템이라고 한다.
그냥 살짝 보기만 하더라도 유지보수 지옥에 빠질 것 같아서 어지럽다
이렇게 end-to-end 방식으로 소통하는 데이터 처리 시스템은 극명한 문제점이 존재했다.
1. 시스템 복잡도가 너무 높다
여기저기서 데이터를 전송하기 때문에 데이터의 흐름을 한눈에 파악하기 어려워서 관리가 매우 힘들다.
특정 부분에서 장애가 발생하면 연결된 모든 애플리케시연을 모두 체크해줘야 하기 때문에, 복구하기 까지 시간이 너무 오래 걸린다.
버전 업그레이드, 하드웨어 장비 교체 시, 연결되어 있는 어플리케이션들에게 side effect는 없는지 확인을 해야해서 관리 포인트가 늘어나, 버전 업그레이드와 하드웨어 교체도 매우 보수적으로 바라볼 수 밖에 없다.
2. 데이터 파이프라인 관리가 어렵다
각 어플리케이션 간에 별도의 파이프라인이 존재하고, 각 파이프라인마다 데이터 포맷과 처리 방식이 다르다.
새로운 파이프라인 확장이 어려워서 확장성과 유연성이 떨어진다.
각 파이프라인마다 데이터 포맷 처리 방식이 달라서 데이터 불일치 가능성이 존재하여 신뢰도가 감소했다.
그래서 이러한 문제점을 해결하기 위해 링크드인은 아래 4가지 목표를 설정해서
카프카를 개발하게 되었다.
End-to-end 통신이 아닌, 통합/중앙화된 전송 영역을 설계하자.
메세지를 생성하는 producer와 소비하는 comsumer로 분리하자.
대용량 메세지 처리와 빠른 처리속도를 갖도록 만들자.
확장(scale-out)이 가능하도록 하자.
그 결과 위와 같은 시스템으로 설계할 수 있었다고 한다.
즉, 각 데이터 흐름이 여러 곳으로 흩어져 있던 기존 end-to-end 방식과는 다르게
데이터의 흐름을 중앙에서(카프카 클러스터) 관리하기 때문에 편하게 유지보수를 할 수 있게 되었다
만약, 이벤트가 발생하면 이벤트 스트림을 통해서 이벤트가 전달되며
각 서비스들이 필요한 이벤트를 캐치해서 가져가게 된다.
이를 Event Driven System(EDA)라고 한다.
비동기 방식
producer가 데이터를 만들고 consumer는 원할때, 해당 topic에서 데이터를 소비하기만 하면 된다.
producer와 consumer가 완벽하게 분리된 비동기 방식을 사용하기
때문에 데이터 요청이 몰리면서 발생하는 병목지점과 지연에 대한 대처가 가능 하다.
파티셔닝
topic을 여러개로 나눌 수 있습니다.
각 파티션들은 다른 파티션들과 관계없이 처리할 수 있으므로, 효과적인 수평 확장이 가능합니다.
이 외에도 카프카를 사용할 이유는 여러가지가 존재합니다.
메세지 전송 방식
Producer나 브로커의 설정 및 구성에 따라서 메세지 전달 보장 수준을 3가지 방식으로 구분할 수 있습니다.
1. 최대 한 번 (At most once) : 메세지가 한번만 전송되며, 재 전송은 없다. → 메세지 유실 가능성은 존재한다.
무조건 최대 1번만 전송하고, 이에대한 확인 메세지 (ACK)를 받지 않아도 재전송은 없다.
이 전략은 메세지의 유실 가능성을 감수하더라도 중복 전송을 막고 높은 처리량과 짧은 대기시간을 만족시켜준다
그래서 대량의 로그를 수집하는데 유용하게 사용된다
2. 최소 한 번 (At least once) : 메세지가 반드시 전송되며, 최소한 한 번 이상은 전송이 보장된다.
→ 메세지 유실 가능성은 없지만 메세지가 중복으로 전송될 수 있다.
중복은 허용하지만, 메세지의 손실은 허용하지 않는다.
그래서 Ack를 받지 못하면 브로커가 메세지를 저장했는지, 응답만 전송하지 못했는지, 둘다 실패했는지를 판단 할 수 없다.
그래서 이 전략은 메세지의 손실을 방지하기 위해서 중복은 허용하는 방식이다.
3. 정확히 한 번 (Exactly once) : 메세지가 정확히 한번만 전송되며, 재전송은 일어나지 않는다.
→ 메세지가 유실되지 않고 중복으로 전송되지도 않는다.
이 방식은 멱등성을 가장 잘 따르는 방식이다.
이 방식은 메세지가 딱 한번 전달되고 어떤 메세지도 손실되지 않고
프로듀서 ID와 시퀀스 번호를 활용해서 Ack를 받고 메세지를 전송한다.
하지만 이런 특성때문에 다른 방식에 비해 응답 대기 시간이 길어지고 처리량이 떨어질 수 밖에 없다.
멱등성 보장 설정
멱등성은 동일한 작업을 여러번 수행 하더라도 동일한 결과가 나타나는 특성을 말합니다.
따라서 멱등성을 지닌 프로듀서는 같은 데이터를 여러번 생성하더라도, 카프카 클러스터에는 한번만 저장됩니다
그렇다면 producer에 멱등성을 어떻게 보장해줄까요?
이를 위해 카프카는 프로듀서 ID(PID)와 시퀀스 번호를 기반으로 메세지를 추적하고, 동일한 커밋에 대해 중복처리를 방지합니다
멱등성을 위해 아래와 같은 설정이 필요합니다
acks : 프로듀서가 요청을 보내고 리더가 레플리카의 수신을 확인해야 하는 개수를 결정, all 또는 -1로 설정
enable.idempotence: 프로듀서가 레코드 쓰기 작업을 단 한 번만 허용할 것인지를 결정. 'true'로 설정해야 멱등성을 보장한다.
max.in.flight.requests.per.connection: 한 번에 몇 개의 요청을 전송할 것인지를 결정. 이 값은 1 이상 5 이하로 설정해야 한다.
retries: 메시지를 전송하기 위해 재시도되는 횟수를 결정. 이 값은 0 이상으로 설정해야 한다
min.insync.replicas: 동기화하는 레플리카의 수를 결정. acks=all일 경우 보통 2로 설정한다(브로커 설정이다).
enable.idempotence = true로 설정하면, 위 이미지처럼 각 프로듀서에는 고유한 프로듀서 ID(PID)가 할당됩니다.
만약 메세지가 토픽에 저장되고 ack 가 전달되지 않아서 다시 메세지를 브로커에 보낸경우,
프로듀서의 요청이 거부당하는 것을 확인할 수 있습니다.
그래서 프로듀서는 실패에 따른 요청을 다시 보낼 수 있지만,
모든 메세지는 한번만 기록되기 때문에 요청이 거부당한다는 것을 알 수 있습니다
새로운 프로듀서는 새로운 고유 PID가 할당되므로 위 사진과 같은 방식은 해당 단일 프로듀서에만 적용된다는 것을 알아야 합니다.
카프카에서 max.in.flight.requests.per.connection 설정은 멱등성(idempotence)을 보장하는 데 중요한 역할을 합니다
- 메세지 순서 보장 : max.in.flight.requests.per.connection 값이 5 이하일 때, 프로듀서는 한 메시지가 실패하면 그 후의 메시지들은 서버에 전송되지 않습니다. 이러한 동작은 메시지의 순서가 변경되지 않도록 보장하는 데 중요합니다.
만약 이 값이 5보다 크다면, 프로듀서는 재시도하는 동안 다른 메시지들을 전송할 수 있어, 메시지 순서가 뒤바뀔 위험이 있습니다.
- 중복 메시지 방지: 멱등성 프로듀서는 메시지의 중복 전송을 방지합니다. max.in.flight.requests.per.connection 값이 너무 크면 네트워크 지연 등의 문제로 인해 중복 메시지가 발생할 가능성이 증가합니다.
따라서 이 값을 5 이하로 설정하여 이러한 문제를 줄일 수 있습니다.
'Back-End' 카테고리의 다른 글
클라이언트에서 서버로 쿠키가 전달되지 않는다 (React, Spring) (0) | 2025.04.06 |
---|---|
DI 패턴을 사용하여 IoC 설계 원칙을 구현하고 있다 (0) | 2025.03.31 |
MSA에서 SAGA Pattern을 사용하는 이유 (0) | 2025.03.28 |
Path Variable과 Request Param 의도는 다르다 (차이점) (0) | 2025.03.19 |
MSA에서 멀티모듈을 도입하게된 이유 (멀티레포, 모노레포, SpringBoot) (0) | 2025.03.16 |