카프카 1편 [구조 및 개념]

작성자 : 플랫폼 개발실 R&D팀 유주빈 대리
해당 글은 API 문서에 대한 독해 및 개인공부 글입니다. 따라서 개인적인 해석이 있을 수 있습니다.

1. 이벤트 스트리밍(event streaming)

스트리밍(streaming) 이란 무엇일까? 스트리밍(streaming)은 ‘흐름’ 이라는 뜻으로 데이터가 흐른다는 뜻에서 사용하는 용어이다. 이러한 ‘흐름’을 통해 원하는 데이터를 보내기도 하고 받기도 할 수 있다. 이를 통해 실시간으로 분석 및 추가적인 로직을 통해 서비스를 제공할 수 있다. 결국 카프카에서 ‘이벤트 스트리밍(event streaming)’이란 일련의 데이터 흐름의 각각의 데이터 이벤트(event)를 지속적인 전달을 하는 스트리밍(streaming)이라는 개념을 갖는다.

2. 카프카의 핵심 3가지

  • 이벤트 데이터 흐름에서 발행(publish)과 구독(subscribe)을 통해 하나의 시스템에서 또 다른 시스템으로 내보내기/가져오기를 할 수 있다.
  • 이벤트 데이터를 내구성 있고 안정적으로 저장이 가능하다.
  • 이벤트 스트리밍 과정에서 이벤트를 발생시키거나 소급이 가능하다.

위의 핵심 3가지 기능은 분산되고 확장성이 뛰어나고 탄력적이며 내결함성이 있으며 안전한 방식으로 제공이 된다. 또한 하드웨어, 가상 머신, 컨테이너, 온프레미스 및 클라우드에 배포할 수 있다.

3. 카프카의 서버와 클라이언트

Kafka는 고성능 TCP 네트워크 프로토콜을 통해 통신하는 서버와 클라이언트로 구성된 분산 시스템이다.

서버: Kafka는 하나 이상의 서버의 클러스터로 실행된다. 이는 지속적으로 데이터를 가져오고 내보내 Kafka를 관계형 데이터베이스 및 다른 Kafka 클러스터와 같은 기존 시스템과 통합할 수 있다. 서버에 장애가 발생할 경우 다른 서버가 작업을 넘겨받아 데이터 손실 없이 지속적인 운영을 보장한다.

클라이언트: 네트워크 문제 또는 시스템 장애 발생 시에도 병렬, 규모 및 내결함성 방식으로 이벤트의 스트림을 읽고, 쓰고, 처리하는 분산 애플리케이션과 마이크로 서비스를 작성할 수 있다. 또한 클라이언트는 Kafk스트림 라이브러리, Go, Python, C/C++ 및 REST APIs를 포함한 자바와 스칼라에서 사용할 수 있다.

4. 작동 원리

카프카는 일반적으로 “카프카 브로커”라고도 불리며 “브로커”에 맞게 중개자로서의 역할을 한다.

프로듀서와 콘슈머 관계

생산자(producer)는 Kafka에 이벤트를 게시(쓰기)하는 클라이언트 애플리케이션이고, 소비자(consumer)는 이러한 이벤트에 가입(읽고 처리, subscribe)하는 애플리케이션이다. Kafka에서는 생산자(producer)와 소비자(consumer)가 서로 완전히 분리되고 독립적이며, 이는 Kafka가 알려진 높은 확장성을 달성하기 위한 핵심 설계 요소이다. 예를 들어, 생산자들은 소비자를 기다릴 필요가 없으며 Kafka는 이벤트를 한 번 정확하게 처리할 수 있는 능력과 같은 다양한 보증을 제공한다.

4-1. 작동 원리 : 토픽(topic)

이러한 카프카 브로커는 이벤트 데이터 생성을 하는 생산자(producer)와 데이터를 수신하는 소비자(consumer)의 사이에 토픽(topic)이라는 것을 통해 발행과 구독의 관계를 만든다.

카프카 발행과 구독

생산자(producer)는 메세지(데이터)를 발행하며 발행시 어떤 토픽(topic)에 발행을 할지 결정한다. 이렇게 발행된 메세지는 토픽(topic) 내부의 파티션(partition)에 저장이 된다. 이렇게 내부의 파티션(partition)에 저장된 메세지는 해당 파티션(partition)에 append가 된다.

왜 여러개의 파티션으로 나눠서 메세지를 저장할까?

만약 파티션의 개념이 없이 분리되지 않은 하나의 공간에만 저장인 된다고 가정해보면 알 수 있다. Kafka는 순차적으로 들어온 순서에 따라 append를 한다. 이때, 많은 양의 메세지가 들어온다면 순차적인 데이터 저장 속도에 많은 불이익이 생긴다. 파티션으로 분리가 되어 있다면 데이터 처리가 병렬로 처리될 수 있는 이점을 얻을 수 있다.

무조건 파티션 수량을 늘린다면 이득일까?

무분별한 파티션 분할은 파티션별로 데이터에 대한 핸들러가 낭비가 될 수 있다. 또한 카프카는 파티션별로 Leader를 선출한다. 이때, 만약 Leader 파티션을 갖은 하나의 카프카가 강제로 종료가 된다면 파티션에 대한 Leader를 재선출을 해야하는데 파티션의 수가 많을수록 많은 Leader를 선출해야 한다는 단점이 있으며 이로인해 장애 복구에 대한 시간이 오래걸릴 수 있다.

4-2. 작동 원리 : 파티션 규칙

카프카의 토픽(topic)은 하낭 이상의 파티션을 갖는다. 이때, 생산자(producer)가 토픽(topic)에게 발행한 메세지는 어떠한 파티션에 저장이 되는지에 대한 결정이 필요하다. 이때 아래와 같이 결정이 된다.

  • key가 있는경우
    • key를 hash하여 특정 파티션으로 보내며 해당 키는 특정 파티션과 맵핑이 되어 있다. 이러한 맵핑은 파티션 개수가 변경되지 않는다면 유지된다.
  • key가 없는 경우
    • 전통적인 Round Robin 알고리즘을 통해 균등하게 파티션을 선택한다.

4-3. 작동 원리 : 컨슈머 그룹

카프카의 메세지를 구독하는 소비자(consumer)는 컨슈머 그룹(consumer group)에 속하여 데이터를 받으며 컨슈머 그룹(consumer group)은 하나의 토픽(topic)에 대해 책임을 갖는다.

카프카 컨슈머 그룹(consumer group)

그림에서 보면 ‘테스트 토픽’에는 파티션이 3개가 존재한다. 이를 ‘컨슈머 그룹0’이 구독을 하고 있으며 내부에 컨슈머0~2 까지 3개의 컨슈머(consumer)가 존재한다. 현재 파티션 수와 컨슈머 수가 동일하므로 파티션과 컨슈머는 1:1 맵핑이 되어 있다. 여기서 빨강색으로 되어있는 데이터는 현재 컨슈머들이 받는 데이터를 뜻한다. 여기서 ‘컨슈머 그룹0’은 각 파티션별로 현재 어디까지 데이터를 소비했는지에 대한 Offset 정보를 알고 있어 다음에 소비할 데이터를 순차적으로 갖고 갈 수 있다.

파티션 수와 컨슈머(consumer) 수가 다르면 어떻게 될까?

첫 번째로 파티션 수와 컨슈머 수의 관계가 아래와 같다고 가정한다.

  • 파티션 수 : 컨슈머 수 = 3 : 2

파티션 수 : 컨슈머 수 = 3 : 2

파티션 수가 더 많을 경우, 특정 몇몇의 컨슈머(consumer)는 하나 이상의 파티션에 대한 책임진다. 현재 예시에서는 컨슈머0~1 까지 2개의 컨슈머가 3개의 파티션을 담당하고 있으므로 콘슈머1이 채택되어 2개의 파티션을 감당한다.

  • 파티션 수 : 컨슈머 수 = 3 : 4

파티션 수 : 컨슈머 수 = 3 : 4

컨슈머(consumer) 수가 더 많을 경우, 특정 몇몇의 컨슈머(consumer)는 아무것도 하지 않게 된다. 현재 예시에서는 컨슈머0~3 까지 4개의 컨슈머가 3개의 파티션을 담당하고 있으므로 각각 파티션과 1:1 맵핑이 되고 컨슈머3은 남게 된다.

컨슈머(consumer) 중에 하나가 장애가 발생한다면 어떻게 될까?

컨슈머 그룹0에 속한 컨슈머2가 아래와 같이 장애가 발생했다고 가정한다.

콘슈머 에러 발생

콘슈머2는 현재 카프카 브로커(Kafka)의 파티션3으로부터 정상적인 메세지를 처리할 수 없는 상황이다. 이때, 카프카는 장애를 극복하기 위해 일련의 과정이 필요하며 이를 리밸런싱(rebalancing)이라고 한다.

콘슈머 에러 발생

결국 이러한 리밸런싱(rebalancing)을 통해 정상적인 콘슈머들이 파티션1~3에 대해 처리를 할 수 있도록 설정이 된다.

참고

1
2
3
- https://kafka.apache.org/documentation
- https://12bme.tistory.com/528
- https://medium.com/@umanking/%EC%B9%B4%ED%94%84%EC%B9%B4%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0-%ED%95%98%EA%B8%B0%EC%A0%84%EC%97%90-%EB%A8%BC%EC%A0%80-data%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0%ED%95%B4%EB%B3%B4%EC%9E%90-d2e3ca2f3c2
Share