[Kafka] 카프카란 ? 주요개념 정리 및 Pub/Sub 모델 비교

반응형

카프카(kafka) 란?

Kafka는 대규모 실시간 데이터 스트리밍을 처리하는 데 사용되는 분산 이벤트 스트리밍 플랫폼이다.

 

먼저 "분산 이벤트 스트리밍"이라는 용어에 대해 알아보자

분산 이벤트이라는 말은 여러 대의 서버(노드)에 분산되어 저장된 이벤트(데이터) 를 말한다.

이벤트 스트리밍대량의 이벤트(데이터)를 실시간으로 처리하는 방식을 의미한다.

 

즉, 이 두 내용을 연결 시키면 분산 되어 있는 이벤트(데이터)들을 실시간으로 처리하는 플랫폼이라는 뜻이 된다.

링크드인의 카프카 적용 전 - 카프카 적용 후 아키텍처

그림의 왼쪽은 링크드인에서 개발한 카프카가 등장하기전의 아키텍처 모습니다.

데이터 저장소들이 도착지점까지 모든 시스템을 거치는 End - To - End 연결로 매우 복잡한 것을 볼 수 있다.

하지만 카프카가 적용된 오른쪽 그림을 보면 모든 이벤트와 데이터를 카프카가 처리하는 것을 볼 수 있다.

 

그렇다면 이 분산 이벤트를 실시간으로 어떻게 관리하는 걸까 ?

바로 kafka가 Pub / Sub 모델의 메세지 큐 형태로 동작하기 때문이다.


메세지 큐 (Message Queue, MQ)

카프카를 이해하기 위해서는 카프카의 핵심 개념인 메세지 큐에 대한 이해가 필요하다.

 

메세지 큐는 "메시지 지향 미들웨어 (MOM : 서로 다른 시스템, 애플리케이션, 서비스 간에 메시지를 교환하는 방식)"를 구현한 시스템이다.

 

메시지 큐를 사용하면 메세지를 보낸 사람(발행자)와 메세지를 받는 사람(수신자)가 서로를 직접 알 지 못해도 전송, 수신이 가능하다. (비동기 : 느슨한 결합)

바로 발행자와 수신자 사이메시지 큐가 이를 중개하고 있기 때문이다.

 

메세지큐의 장점
  • 수신자의 서비스에서 장애가 발생하더라도 발행자로 인해 발행된 메세지는 이미 메시지 큐에 남아 있기 때문에 수신자에게 메세지 전달을 보장할 수 있다.
  • 발행자와 수신자가 서로 의존하지 않고 독립적이기 때문에 확장하는데 문제가 없다.
  • 메세지 큐라는 중개소가 있기 때문에 발행자와 수신자가 서로의 요청과 응답을 기다리지 않고 큐에 담아 비동기로 통신할 수 있다.

 

Point to Point 와 Pub / Sub

메시지 큐는 크게 Point to Point(P2P) 와 Publish/Subscribe (Pub / Sub)모델로 구분된다.

  • Point to Point(P2P) : 한 명의 발행자의 메세지는 한 명의 컨슈머에 의해 소비되는 방식으로 즉, 1 : 1 메시지 전송 방식이다.
  • Publish/Subscribe (Pub / Sub) : 발행자가 특정 Topic(토픽)에 메시지를 보내면, 해당 Topic을 구독한 여러 수신자가 해당 메시지를 받는 방식이다.
  Point to Point(P2P) Publish/Subscribe (Pub / Sub)  둘다 지원
서비스 - Amazon SQS - Amazon SNS
- Kafka
- Redis
- ActiveMQ
- RabbitMQ

우리가 이번 포스팅에서 알아볼 Kafka는 Pub / Sub 를 지원한다.

Pub / Sub 모델을 기본으로 하지만 각 메시지가 한 번만 처리되도록 보장하는 P2P 스타일의 소비도 가능하다고 한다. (GPT 말함.)


카프카 용어 정리

출처 : https://www.linkedin.com/pulse/how-deploy-kafka-zookeeper-cluster-linux-based-operating-tiwari

◼ 카프카 클러스터 (kafka cluster)

브로커들의 모임으로 확장성과 고가용성을 위해 Broker들이 클러스터로 구성되어 있다.

 

◼ 브로커 (Broker)

각각의 Kafka 서버를 말한다.

프로듀서로 부터 메세지를 전달받아 토픽에 저장하고 컨슈머에 저장한다.

(하나의 브로커는 여러개의 토픽을 가질 수 있다.)

 

◼ 주키퍼 (zookeeper)

Kafka 클러스터 상태와 정보 등을 관리하는 역할을 한다.

(Kafka를 실행 시키기 위해선 Zookeeper도 같이 실행해야함)

 

◼ 프로듀서 (Producer)

메시지를 발행하는 주체이다. 메시지 발행 시 특정 토픽을 정하여 발행한다.

 

◼ 컨슈머 (Consumer)

메시지를 소비, 수신하는 주체이다. 특정 토픽을 구독하여 메시지를 전달 받는다.

 

 

 

◼ 토픽 (Topic)

메시지를 구분하는 단위로 프로듀서로 부터 전송된 데이터는 토픽이름으로 구별된다.

 

◼ 파티션 (partition)

하나의 토픽은 다음과 같이 하나 이상의 파티션으로 나눠진다.

어느 파티션에 저장지는 키를 지정할 경우 동일한 키(예: 같은 사용자ID)를 가진 메시지는 같은 파티션에 저장하고

키가 없을 경우에는 라운드로빈 방식으로 순차적으로 저장된다.

 

파티션의 레코드는 위 처럼 offset이라 불리는 파티션 내에서 메시지의 위치(식별자)를 갖는다.

그리고 새로운 토픽이 추가되면 저장될 파티션의 끝에 추가되고 만약 파티션 0에 저장된다면 offset이 6인 레코드가 추가된다.

그림을 보면 파티션 별로 offset을 가지고 있는 것을 볼 수 있는데 동일 파티션 내에서는 유의미한 순서를 가져 순서를 보장하지만

파티션 간에는 offset이 겹쳐 순서가 보장되지 않는다.

 

오프셋은 파티션에서 레코드를 읽고 사용하는 Consumer에게 특히 유용하게 사용된다.

Consumer는 자신이 어디까지 처리했는지 카프카로부터 꺼낸 토픽에서 파티션과 오프셋 정보를 확인할 수 있다.

그리고 해당 오프셋을 Consumer처리하면 수동 또는 자동으로 커밋 처리를 한다.

다음 Consumer가 토픽을 읽을 때는 커밋된 다음 오프셋부터 읽기 시작점이 된다.

이러한 방식으로 다른 Consumer가 실수로 같은 데이터를 처리하는 것 방지할 수 있고 처리 못한 offset을 재처리할 수도 있다.

 

◼ 리더와 팔로워

카프카에서 파티션은 리더(Leader)와 팔로워(Follower)로 구성되어 있다.

각 파티션에는 하나의 리더와 0개 이상의 팔로워가 있다.

 

리더는 다음과 같은 역할을 한다.

  • 해당 파티션의 모든 읽기/쓰기 요청을 처리
  • 프로듀서로부터 메시지를 직접 받아 저장
  • 컨슈머에게 메시지를 전달
  • 팔로워들과 동기화를 유지

 

팔로워는 다음과 같은 역할을 한다.

 

  • 리더의 데이터를 복제하여 저장
  • 리더와 지속적으로 동기화를 수행
  • 리더가 실패할 경우 새로운 리더가 됨 (failover)
  • 읽기 요청은 처리할 수 있지만 쓰기 요청은 처리할 수 없다. (readOnly)

뭐가 비슷해보이는 기술이하나 생각나지 않나?

맞다 바로 DB Replication처럼 복제본을 추가하여 파티션의 고가용성을 챙기는 것이다.

 

이 복제를 위해서는 반드시 여러 개의 브로커가 필요하다.

이 이유는 리더와 팔로워 간의 동기화는 ISR(In-Sync Replicas) 메커니즘을 통해 관리되기 때문이다.

ISR란 리더와 충분히 동기화된 팔로워들의 집합을 의미한다.

출처: https://damdam-kim.tistory.com /17

 

 

  1. 리더는 팔로워들의 동기화 상태를 지속적으로 모니터링한다.
  2. 각 팔로워는 리더로부터 메시지를 복제하고 fetch 요청을 보낸다.
  3. replica.lag.time.max.ms 설정값(기본 10초) 내에 fetch 요청이 없으면 해당 팔로워는 ISR에서 제외된다.
  4. 제외된 팔로워가 다시 동기화를 따라잡으면 ISR 목록에 다시 포함된다.

그리고 다음과 같은 설정이 추가로 있다.

# 전체 복제본 갯수
replication.factor=3

# 최소 동기화 복제본이 2인 경우
min.insync.replicas=2

전체 복제본은 3개 (1 리더 + 2 팔로워)이며 최소 2개의 복제본이 동기화되어 있어야 프로듀서가 메세지를 발행할 수 있는 설정이다.

만약 동기화된 복제본이 1개뿐이라면 프로듀서는 메시지를 발행할 수 없고 에러를 응답받는다.

 

 

 

 

이렇게 ISR 내의 팔로워만이 새로운 그룹의 리더가 될 수 있어 Kafka는 데이터 안전성을 보장하면서 가용성을 챙길 수 있다.

 

 

◼ 컨슈머 그룹 (Consumer Group)

컨슈머 그룹은 하나 이상의 컨슈머가 모여 구성된 그룹이다.

같은 그룹 내의 컨슈머들은 협력하여 토픽의 파티션들을 분산 처리한다.

각 파티션은 그룹 내 하나의 컨슈머에게만 할당되고 컨슈머들은 각자의 offset으로 관리한다.

(하나의 파티션이 그룹 내의 여러 컨슈머에 할당되지 않는다.)

파티션의 개수가 4개일 때 컨슈머 그룹 내에 컨슈머가 4개가 존재한다면

각 컨슈머들이 파티션을 하나씩 할당 받아 해당 토픽의 작업을 병렬 처리할 수 있다.

좀더 쉽게 이해하려면 컨슈머를 알림 서버에 로드 밸런싱을 적용하고 가용하는 서버를 4대라 해보자.

그럼 order라는 토픽이 있고 4개의 파티션이 있다면 각 알림 서버들은 파티션을 하나씩 할당 받아 해당 토픽의 작업을 처리하는 것이다.

이렇게 하나의 토픽을 여러 파티션에 나누어 저장하고 사용하여 병렬 처리 능력을 향상시킬 수 있다.

주의할 점은 파티션이 컨슈머보다 많다면 병렬 처리 능력은 향상되지 않을 것이다.

파티션 개수보다 컨슈머 개수가 많으면 일부 컨슈머는 파티션을 할당받지 못하고 유휴(idle) 상태가 되어 리소스를 낭비하게 될 수 있다.

 

만약 컨슈머 그룹 내에서 컨슈머의 변화가 있다면 파티션과 컨슈머의 매칭관계를 변경하는 리밸런싱이 발생한다.

 

◼ 리밸런싱

컨슈머 그룹 내에서 파티션의 소유권을 재분배하는 과정이다.

리밸런싱은 컨슈머 그룹 내의 수가 변경될 뿐아니라 파티션 수에 변화에도 발생한다.

주의할점은 리밸런싱이 발생하면 컨슈머 그룹 내의 컨슈머들은 읽기 작업이 중단된다.

서비스 상태에 일시적인 영향을 주게 되므로 컨슈머, 파티션의 추가가 필요하다면 적절한 시점에 추가하는 것이 필요하다.

 

리밸런싱 과정은 다음과 같다.

  1. 모든 컨슈머가 브로커에 현재 상태를 알리기 위해 하트비트를 보낸다. (heartbeat.interval.ms 로 전송 주기 결정)
  2. 카프카 세션 타임 아웃(session.timeout.ms) 설정 시간 동안 하트비트가 없으면 해당 컨슈머는 장애로 간주되어 리밸런싱이 시작된다.
  3. 컨슈머가 poll() 메서드를 호출하는 (메시지를 수신하는) 최대 간격인 max.poll.interval.ms 설정 시간을 초과하면 해당 컨슈머를 제외하고 리밸런싱이 시작된다.

Pub / Sub 모델 별 차이

 

  Kafka RabbitMQ Redis Pub/Sub AWS SNS
데이터 유지 디스크에 데이터를 지속적으로 저장하며
TTL(Time-To-Live) 설정으로 오래된 데이터를 삭제할 수 있다.
또한 Consumer가 어디까지 메시지를 읽었는지 추적 가능.
메시지는 메모리와 디스크에 저장될 수 있으며
기본적으로 메시지는 Consumer가 처리하면 삭제된다.
기본적으로 메모리 기반의 스토리지로 데이터 유실 위험이 있다.
영속성을 위해선 AOP, RDB 추가 설정이 필요.
메시지 저장 기간이 제한적이다.
확장성 Topic의 Partition을 통해 확장성을 제공하며, 분산 처리가 가능 Queue를 통해 확장성을 제공하지만 Kafka 만큼의 높은 병렬처리 능력은 부족 Pub/Sub 모델에서는 병렬 처리나 분산 처리 방식이 제한적 AWS 인프라를 통한 자동 확장이 가능하며, 리전 간 메시지 전달도 지원
우선순위 변경 불가능하지만
한 파티션 내에서는 FIFO 보장.
priority queue를 지원해 우선순위에 따라 처리 가능. - 변경 불가능하지만 FIFO 보장
장점 - 이벤트가 전달되어도 삭제되지 않고 디스크에 저장된다.
- 고성능, 고가용성, 분산처리에 효과적.
- producer 중심적으로 많은 양의 데이터를 병렬 처리 가능하다.
- Direct, Fanout, Topic, Headers의 라우팅 옵션을 제공하여 유연한 라우팅이 가능하다.
- Manage UI가 기본 제공
- Broker 중심적인 형태로 publisher와 consumer간의 보장되는 메시지 전달
- 플러그인도 제공되어 확장성 뛰어나다.
인메모리로 빈번하고 속도가 중요한 작업에 적합 푸시 기반 알림 제공
- 서버리스로 관리 부담이 적음.
- AWS 서비스들과 쉬운 통합.
- 메시지 필터링 기능 제공
단점 - 범용 메세지 시스템에서 제공되는 다양한 기능이 제공되지 않는다.
- 분산 시스템 관리를 요구
- kafka보다 느리다.
- 대용량 데이터 처리에 상대적으로 부적합하다.
이벤트 도착을 보장하지 못한다. - 비용이 사용량에 따라 증가
- 메시지 저장 기간이 제한적
사용 사례 대용량 실시간 스트림 데이터 처리 및 분석에 적합 데이터 처리보단, 관리적 측면이나 다양한 기능 구현을 위한 서비스를 구축할 때 사용 캐싱, 세션 관리 등 인메모리 스토어가 필요하거나 경량의 실시간 Pub/Sub 시스템에 사용 간단한 메시징 및 알림 사용