반응형

메시지 큐 사용 이유

  • 컴포넌트 사이의 강한 결합 완화
  • producer/consumer을 독립적으로 확장 가능
  • 특정 컴포넌트 장애 발생해도 다른 컴포넌트는 작업 가능
  • 비동기 통신을 통한 성능 개선

메시지큐 vs 이벤트 스트리밍 플랫폼

  • 메세지 큐: rabbit mq
  • 이벤트 스트리밍 플랫폼: 카프카
  • 메세지큐 + 데이터 장기보관, 반복 소비, 스트리밍 기능 = 이벤트 스트리밍 플랫폼

 

큐?

  • producer가 메시지를 큐에 보내고 consumer는 큐를 구독하고 구독한 메시지를 소비
  • producer/consumer 는 모두 클라이언트고 서버 역할을 하는 것은 메세지 큐
  • 일대일 모델
    • 메세지는 오직 한 소비자만 가져갈 수 있음; 소비되면 삭제됨
    • 한 큐에 여러 소비자가 붙으면 큐의 병렬처리
  • 발행 구독 모델
    • 토픽: 고유한 이름을 가진; 메시지를 보내고 받을 때 토픽에 보내고 받음
    • 해당 토픽을 구독하는 모든 소비자에게 전달

메시지 큐가 서버인 이유

메시지 큐는 시스템의 중심에서 메시지를 저장하고 관리하며, 전달을 책임지는 역할을 하기 때문에 서버로 간주됩니다. 다음과 같은 이유가 있습니다:

(1) 중앙 관리 역할

메시지 큐는 모든 메시지를 중앙에서 관리합니다.

  • Producer는 메시지를 큐에 넣기만 하고,
  • Consumer는 큐에서 꺼내오기만 합니다.
    즉, 메시지의 저장, 전달, 보관 등 모든 복잡한 작업은 메시지 큐가 처리합니다. 이 중앙 관리 기능은 전형적인 서버의 역할입니다.

(2) 요청/응답 모델

  • Producer는 메시지를 큐에 요청(Request)으로 전송합니다.
  • Consumer는 큐에 요청(Request)을 보내 메시지를 가져옵니다.
  • 메시지 큐는 이 요청들을 처리하고 응답(Response)하거나, 메시지를 전달하는 서버 역할을 수행합니다.

(3) 리소스 제공자

메시지 큐는 Producer와 Consumer 사이에서 리소스를 제공하는 역할을 합니다. 예를 들어:

  • 메시지의 내구성(Durability)과 순서 보장(Order Guarantee)을 관리합니다.
  • 특정 Consumer가 일시적으로 작동하지 않아도 메시지를 보관하여 이후에 전달합니다.
    Producer와 Consumer는 메시지 큐에 의존하여 이 서비스를 이용하므로 클라이언트로 간주됩니다.

Producer와 Consumer가 클라이언트인 이유

Producer와 Consumer는 메시지 큐를 사용하는 사용자로 동작하기 때문에 클라이언트로 간주됩니다.

(1) 요청을 보냄

  • Producer는 메시지를 큐로 보내는 요청을 보냅니다.
  • Consumer는 메시지를 큐에서 가져오라는 요청을 보냅니다.
    요청(Request)을 보내는 주체는 일반적으로 클라이언트로 간주됩니다.

(2) 큐에 의존

Producer와 Consumer는 메시지 큐가 없다면 서로 직접 통신해야 합니다. 그러나 메시지 큐를 사용함으로써:

  • Producer는 큐에 메시지를 보내는 데만 집중합니다.
  • Consumer는 큐에서 메시지를 가져오는 데만 집중합니다. 결국 이 둘은 큐가 제공하는 서비스(메시지 저장 및 전달)에 의존하는 클라이언트로 동작합니다.

 

토픽, 파티션, 브로커

  • 메시지는 토픽에 보관
  • 토픽에 보관되는 데이터 양이 많으면? 파티션 사용(샤딩 기법)
  • 토픽을 여러 파티션으로 분할하여 메시지를 나눠 보냄
  • 파티션은 메세지 큐 클러스터 내의 서버에 고르게 분산 배치
  • 파티션을 유지하는 서버: 브로커
  • 파티션을 브로커에 분산하여 높은 확장성 달성; 토픽 용량 확장 시 파티션 개수 증가
  • 각 파티션은 FIFO 큐; 한 파티션 안에서는 순서 유지; 위치=offset
  • 파티션 키; 같은 키를 가진 모든 메시지는 같은 파티션으로 없으면 무작위로 보내짐
  • 소비자 그룹: 토픽을 구독하는 소비자가 여럿인 경우 각 구독자는 해당 토픽을 구성하는 파티션의 일부를 담당
    • 같은 그룹 내 소비자는 메시지를 병렬로 소비, 그러면 같은 파티션 안의 메세지를 순서대로 소비할 수는 없다
    • 어떤 파티션은 한 그룹 안에서 한 소비자만 읽게 하여 순서 보장
    • 그룹 내 소비자의 수가 구독하는 토픽의 파티션 수보다 크면 어떤 소비자는 해당 토픽에서 데이터를 읽을 수 없음
    • 처리량을 늘리려면 소비자를 추가

 

데이터를 저장하는 큐를..

  • 디비?
    • 읽기 쓰기가 대규모로 빈번하게는 부적합
  • 쓰기 우선 로그(write ahead log WAL)?
    • 지속성
    • 읽기/쓰기 모두 순차적 -> 디스크
    • 파일 하나에 계속 쓰면 관리가 힘드므로 여러 세그먼트로 분리

 

생산자 작업 흐름

producer는 메시지를 producer 내부의 라우팅 계층에 보내 어떤 브로커(의 파티션)로 보내야하는지 파악하고 전송할 메세지를 버퍼 메모리에 잠시 보관했다가 목적지로 일괄 전송(배치 양을 늘리면 응답 속도가 느려짐)하여 대역폭을 넓힌다. 리더 브로커가 받아서 저장하고 replica가 일정 수 만들어지면 데이터가 소비 가능해지며 producer에게 완료회신을 보낸다.

소비자 작업 흐름

consumer는 특정 파티션의 오프셋의 위치에서부터 이벤트를 묶어 가져온다.

푸시 vs 풀

  • 푸시: 브로커가 데이터를 consumer에게 보냄
    • 낮은 지연: 바로 보냄 하지만 consumer 속도가 느리면 부하가 걸림
  • 풀: consumer가 브로커에게 가져감
    • 소비 속도는 consumer가 알아서 조절. 만약 큐가 쌓이면 소비자를 추가하거나 기다리거나
    • 다음 오프셋부터 한 번에 가져가 배치 처리 가능
    • 단, 데이터가 없어도 시도 -> 롱 폴링으로 consumer 통신 횟수 감소 가능(가져갈 게 없어도 일정시간 기다림)

 

소비자 그룹(Consumer Group)이란?

  • 소비자 그룹(Consumer Group)은 Kafka에서 메시지를 읽어가는 Consumer의 논리적인 묶음입니다.
  • 같은 그룹에 속한 Consumer들은 특정 토픽의 파티션을 분배받아 메시지를 처리합니다.
  • 소비자 그룹 ID를 기준으로 그룹이 구분됩니다.

특징:

  1. 같은 그룹 내의 Consumer는 같은 메시지를 읽지 않습니다.
    • 파티션 하나는 소비자 그룹 내에서 단일 Consumer만 처리합니다.
    • 이를 통해 메시지 처리가 병렬로 이루어집니다.
  2. 다른 소비자 그룹은 독립적으로 동작합니다.
    • 서로 다른 소비자 그룹은 동일한 메시지를 중복으로 처리할 수 있습니다.
    • 예: groupA와 groupB는 동일한 토픽을 구독할 수 있으며, 각각 모든 메시지를 독립적으로 처리합니다.

브로커와 소비자 그룹의 관계

Kafka 브로커와 소비자 그룹은 메시지의 생산(Producer)부터 소비(Consumer)까지의 흐름에서 중요한 관계를 형성합니다.

(1) 브로커는 메시지를 저장하고 제공

  • 브로커는 토픽과 파티션을 기반으로 메시지를 저장하고 관리합니다.
  • Producer는 메시지를 브로커에 전송하고, 브로커는 이를 적절한 파티션에 저장합니다.

(2) 소비자 그룹은 메시지를 병렬로 처리

  • 각 소비자 그룹은 특정 토픽의 메시지를 구독(subscribe)합니다.
  • 그룹 내의 Consumer들은 토픽의 파티션을 나누어 처리합니다.
    • 예: 토픽에 6개의 파티션이 있고, 소비자 그룹 내에 Consumer가 3명 있으면 각 Consumer는 2개의 파티션을 담당합니다.

(3) 파티션 할당 전략

  • Kafka는 소비자 그룹 내에서 파티션을 동적으로 할당합니다.
    • Round-Robin 또는 Range와 같은 기본 전략이 사용되며, 커스텀 전략도 구현 가능합니다.
  • 새로운 Consumer가 그룹에 추가되거나 제거되면 리밸런싱(Rebalancing)이 발생하여 파티션이 다시 분배됩니다.
    • consumer rebalancing: 코디네이터(소비자들과 통신하는 브로커 노드; heatbeat, offset 정보 관리) 필요

(4) 소비자 오프셋 관리

  • 소비자 그룹은 오프셋(Offset)을 관리하여 메시지를 어디까지 처리했는지 추적합니다.
    • Kafka는 이 오프셋 정보를 브로커 내부의 __consumer_offsets라는 내부 토픽에 저장합니다.
    • 이를 통해 Consumer는 중단 후에도 이어서 처리할 수 있습니다.

 

주키퍼

  • 브로커의 상태 저장소
    • 각 소비자 그룹/소비자의 오프셋
    • 읽기와 쓰기가 잦고 데이터 일관성이 중요
  • 토픽 설정, 파티션 수, 메시지 보관 기간 등의 메타 데이터 저장소
    • 자주 변경되지 않고 일관성 중요
  • 분산 시스템의 key value 저장소

 

선정된 리더가(소비자 그룹이건, 파티션의 리더이건) replica 계획, 파티션 배치 계획 등을 정해서 코디네이터로 보내주면 코디네이터가 그걸 전파하는 방식

 

사본 동기화

ISR(in sync replicas) 리더와 동기화된 사본. 리더는 항상 ISR

몇 개가 동기화될 때 까지 기다릴지 설정 가능; 성능과 영속성을 고려해야 함

  • ACK = all : 전체가 다 동기화 될 때까지 기다림, 영속성 중요할 경우
  • ACK = 1 : 리더가 저장하면 다음으로. 응답 지연은 개선되나 리더가 장애 생기면 복제가 안될 수 있어 소실됨
  • ACK = 0 : 생산자는 메시지만 던지고 다음으로. 재시도도 하지 않음. 메세지 손실을 감수할 때

메세지 전달 방식

  • 최대 한 번
    • 메시지가 소실되어도 재전달하지 않음(ack = 0)
    • consumer가 메시지를 읽고 처리하기 전에 오프셋부터 갱신(갱신하고 죽으면 메시지는 다시 소비될 수 없음)
  • 최소 한 번
    • acl = 0; ack = all 메시지가 브로커에게 전달되었음을 반드시 확인
    • 소비자가 데이터를 성공적으로 처리한 뒤에 오프셋 갱신(갱신하지 못하고 죽으면 중복처리)
    • 멱등성 중요(고유 키 중복처리 ㄴㄴ)
  • 정확히 한 번
    • 복잡

 

메세지 필터링

주문 토픽에 발행하는데 지불 시스템이 가져간다면? 일부만 필요

지불 토픽을 별도로 만들어서 주문 데이터르 중복 발행?

생산자와 소비자 결합이 높아져서 ㄴㄴ

-> 필터링으로 해결

다 읽고 필요 없는 걸 버리자니 성능이 저하

브로커카(메시지 큐가) 많은 일을 하면 안 된다(데이터 추출 등)

메시지의 메타 데이터에 태그를 두어 태그를 필터링하도록 하고 태그를 구독..

 

2024.09.25 - [서버 세팅 & tool/rabbitmq] - [rabbitMq] 하나의 메세지를 여러 소비자에게 동등하게 보낼 때.. 그럼 카프카는?

728x90
반응형

+ Recent posts