Data Engineering/Kafka

[Linux/Kafka] Apache Kafka를 알아보자

seoraroong 2024. 8. 22. 16:01

Apache Kafka

Apache Kafka는 높은 처리량과 확장성을 제공하는 오픈 소스 분산 스트리밍 플랫폼이다.

Kafka는 실시간 데이터 스트림을 처리하고 관리하는 데 사용되며 대규모 데이터 처리 및 이벤트 기반 아키텍처에서 중요한 역할을 한다.

 

 

Kafka 이전의 방식

end - to - end 연결 방식

-> 데이터 연동의 복잡성이 높았다.

또한 데이터 파이프 라인 구조가 각기 다른 형태를 가졌다.

-> 데이터 파이프라인이란 쉽게 말해 서비스 구축을 위한 플랫폼인데 구조가 각기 달라 확장 관점에서 어려움이 존재했다.

 

Kafka는 플랫폼들을 연결하는 Interface이다 !

Hardware 관점 : MiddleWare 역할

Software 관점 : Interface 역할

-> end - to - end 방식이 아니고 중각에 MiddleWare 라는 중간 매개체가 있다.

 

 

Apache Kafka의 주요 구성 요소 

 

토픽 (Topic)

토픽은 메시지의 카테고리나 피드를 정의한다.

생산자 (Producer)는 데이터를 토픽에 발행하고, 소비자 (Consumer)는 특정 토픽에서 데이터를 구독한다.

 

메시지의 논리적 구분을 제공하며 하나의 토픽에는 여러 개의 파티션이 존재할 수 있다.

 

파티션 (Partition)

각각의 토픽 (Topic)은 여러 개의 파티션으로 나눌 수 있고, 파티션은 토픽의 논리적 구분을 나타낸다.

파티션은 데이터를 분산 저장하고 병렬로 처리할 수 있게 해준다.

데이터의 스케일 아웃 (Scale Out) 을 지원하며 각 파티션은 순서가 있는 로그 (log) 의 일부로 처리된다.

-> 스케일 아웃이란 토픽의 파티션을 추가해 데이터 분산, 병렬 처리 성능을 증가시키는 것이다. 클러스터의 노드를 추가해 스케일 아웃할 수 있고 데이터의 양에 따라 적절한 파티션 수를 조정해 성능을 최적화 할 수 있다.

 

각 파티션은 Kafka 클러스터의 브로커 (Broker)에서 물리적으로 저장된다.

파티션은 데이터의 순서를 보장하고, 파티션 내에서 데이터는 특정 순서로 기록된다. 이를 오프셋 (offset)이라고 한다

 

 

브로커 (Broker)

브로커는 Kafka 클러스터를 구성하는 서버 인스턴스이다.

Kafka 클러스터는 여러 개의 브로커로 이루어져 있고, 각 브로커는 클러스터의 데이터를 저장하고 처리한다.

3대 이상의 브로커로 클러스터가 구성된다.

 

브로커의 역할은 크게 다음과 같다.

 

- 데이터 수신

프로듀서 (Producer)가 Kafka 클러스터에 데이터를 전송하면 데이터는 브로커로 전달된다. 

각 브로커는 특정 토픽의 파티션을 관리하고, 데이터를 해당 파티션에 저장하게 된다.

 

- 데이터 저장

각 파티션의 데이터는 브로커의 디스크에 순차적으로 저장된다.

Kafka는 데이터를 로그 파일 형태로 저장하고, 이 파일들은 브로커의 파일 시스템에 저장된다.

 

실제로 메시지가 저장되는 파일 시스템 단위는 segment이고, 메시지가 저장될 때 segment file이 open된다. 

 

데이터의 내결함성 보장을 위해 각 파티션의 데이터는 클러스터 내의 다른 브로커에도 복제된다.

복제본은 파티션의 리더 (Leader) 브로커와 팔로워 (Follower) 브로커 간의 데이터 일관성을 유지할 수 있게 된다.

 

- 데이터 제공

컨슈머 (Consumer)가 데이터를 읽어올 때, 브로커는 요청된 데이터를 컨슈머에게 제공한다.

 

- 파티션 리더 및 팔로워

각 파티션은 리더(Leader)와 팔로워(Follower)로 구성된다.

리더 브로커는 파티션의 주 데이터 소스로서 쓰기와 읽기 요청을 처리한다.

팔로워 브로커는 리더 브로커의 데이터 복제본을 유지하고, 리더가 작업에 실패할 경우 새로운 리더가 될 수 있다.

리더 브로커를 Controller 브로커라고도 하는 것 같다.

 

프로듀서 (Producer)

프로듀서는 Kafka 클러스터에 데이터를 생성하고 발행하는 클라이언트 애플리케이션이다.

프로듀서는 특정 토픽에 데이터를 전송하고, 이 데이터는 해당 토픽의 파티션에 저장된다.

 

프로듀서의 역할은 크게 다음과 같다. 

 

- 데이터 생성 및 전송

프로듀서는 데이터를 Kafka 토픽에 발행한다.

데이터는 프로듀서가 지정한 토픽의 파티션에 저장된다.

프로듀서는 메시지를 파티션에 할당할 때 특정 키를 사용하여 데이터를 특정 파티션으로 보내거나, 랜덤으로 파티션을 선택할 수 있다.

 

- 파티션 결정 

프로듀서는 메시지를 저장할 파티션을 결정한다. 

키 기반 분산으로 특정 파티션을 선택하거나, 랜덤하게 선택한다.

또한, 파티션을 적절히 분산시켜 데이터의 부하를 균등하게 분산할 수 있다.

 

- 확인 및 재전송

데이터 전송 후, 프로듀서는 전송이 성공적으로 이루어졌는지 확인하는 과정을 거친다. 

실패 시, 재전송 전략을 설정할 수 있다.

 

컨슈머 (Consumer)

컨슈머는 Kafka 토픽에서 데이터를 읽어오는 클라이언트 애플리케이션이다.

컨슈머는 Kafka의 파티션에서 데이터를 읽어들여 처리하게 된다.

 

컨슈머의 역할은 크게 다음과 같다.

 

- 데이터 읽기

컨슈머는 특정 토픽을 구독해 해당 토픽의 데이터에 접근한다. 

구독한 토픽의 파티션에서 데이터를 읽어오게 된다.

 

- 데이터 처리 및 오프셋 관리 

읽어온 데이터 (메시지)를 처리하고, 읽어온 메시지의 오프셋을 관리한다.

오프셋은 파티션 내의 메시지 순서를 추적해, 실패 시 재처리하거나 중복 처리를 방지하는 데 사용된다.

 

컨슈머 그룹 (Consumer Group)

컨슈머 그룹은 같은 토픽을 구독하는 여러 개의 컨슈머 인스턴스의 집합이다.

모든 컨슈머는 같은 그룹 ID를 사용해 그룹을 형성한다.

 

컨슈머 그룹의 역할은 크게 다음과 같다.

 

- 병렬 처리 

컨슈머 그룹 내의 각 컨슈머는 서로 다른 파티션을 담당한다. 이를 통해 데이터의 병렬 처리가 이루어져 성능이 향상 되고,

데이터 처리의 부하를 분산시킬 수 있다.

 

- 중복 소비 방지

컨슈머 그룹 내의 컨슈머들은 같은 파티션들을 중복해 읽지 않으므로 데이터의 중복 소비를 방지할 수 있다.

 

- 확장성

컨슈머 그룹에 새로운 컨슈머를 추가하면, 새로운 컨슈머가 파티션을 분담하게 되어 데이터 처리의 확장성을 높일 수 있다.

 

Zookeeper

Zookeeper는 Kafka 클러스터 메타데이터를 관리하고, 클러스터의 상태를 모니터링하는 분산 시스템 서비스이다.

 

Zookeeper의 역할은 크게 다음과 같다.

 

- 메타데이터 관리

Zookeeper는 Kafka 클러스터의 브로커, 토픽, 파티션, 오프셋 등의 메타데이터를 저장하고 관리한다.

 

- 브로커 상태 모니터링

Zookeeper는 파티션의 리더 브로커와 팔로워 브로커의 상태를 조정하며, 리더 브로커가 실패할 경우 새로운 리더를 선출한다.

또한 브로커의 상태를 지속적으로 모니터링해 장애 발생 시 클러스터의 안정성을 유지한다.

 

- 분산 협업 지원

Zookeeper는 분산 시스템에서의 일관성을 유지하고, 클러스터의 분산 조정과 협업을 지원한다.

 

Apache Kafka Architecture

 

Kafka Cluster에서 레코드가 전송되는 과정은 간단히 다음과 같다.

 

Procuer -> Topic (Partition) -> Consumer

 

  • Partition 개수 ≥ Consumer 개수 : 가능
  • Partition  개수 < Consumer 개수 : 불가능
    • Consumer가 더 많은 경우, 남은 Consumer는 파티션을 할당 받지 못하고 대기 상태가 된다.
      • 대기 상태 → 불필요한 스레드(Thread)

 

  • 여러 대의 Consumer
    • Consumer 1개에서 장애 발생시 대비 가능
      • Rebalance 발생 : 파티션에 대한 Consumer 할당을 재조정
      • Road Balancing
      • 나머지 Consumer가 파티션으로부터 pooling 수행하게 된다

 

  • Consumer Group
    • 목적에 따라 Consumer들을 Grouping 할 수 있다
      • Topic 1개에 여러 개의 Consumer Group을 할당할 수 있게 된다
    • Consumer Group에 장애 발생
      • Consumer group 간 간섭(coupling)을 줄인다
      • 만약, hadoop에 이슈가 발생해서 적재 지연이 발생했다면?
        • ElasticSearch에 적재하는 Consumer의 동작에는 Issue 없다

 

  • Kafka Broker Issue에 대응하기 위한 방법

        (Consumer에 Issue 발생 시 대응 방법 : Rebalancing)

  • 파티션을 다른 Broker에 복제해 Issue에 대응 (Load Balancing)
    • Replication 개수는 파티션 개수와 동일하게 맞춰준다
    • Replication : 복제할 Broker의 개수
    • 고가용성을 위한 파티션 복제 기능 → 데이터 유실 방지 (이건 파티션 복제)

 

ISR (In-Sync Replica)

특정 파티션의 리더, 팔로워의 레코드가 모두 복제되어서 sync가 맞는 상태를 말한다.

 

Kafka Rack-awareness

1개의 Rack에 여러 개의 Broker를 밀어넣는 것은 위험한 방법이다.

다수의 Rack에 Broker option을 분산하여 배치하는 것이 좋은 전략이라고 할  수 있다.

 

Reason why Kafka Cluster have many Server-Fault Logic

  • 서비스 운영에 있어 장애 허용 (Fault-tolerant)은 중요하다.
    • Kafka Broker 이슈는 다발적으로 발생
      • 일부 서버가 중단되어도 데이터가 유실되어서는 안된다

 

Kafka Streams

Kafka Streams는 Apache Kafka의 확장 모듈로, 실시간 스트림 데이터 처리를 위한 API를 제공한다.

Kafka Streams를 사용하면 데이터 스트림을 효율적으로 처리하고 분석할 수 있다.

 

- 데이터 변환을 위한 API

Kafka Streams는 실시간 데이터 스트림을 처리하고 변환하는 데 필요한 다양한 API를 제공한다.

이를 이용해 데이터를 필터링, 매핑, 집계, 조인할 수 있어 직관적인 방식으로 스트림 처리를 구현할 수 있다.

 

- Stream Processing 지원

Stateful 또는 Stateless와 같은 State-Based Stream을 처리할 수 있다. 

 

Stateful vs Stateless:

  • Stateless Processing: 데이터 스트림을 변환하거나 필터링하는 데 필요한 상태가 없는 처리이다. 예를 들어, 메시지를 단순히 변환하거나 필터링하는 경우가 해당한다.
  • Stateful Processing: 상태를 유지하면서 데이터를 처리하는 경우이다. 예를 들어, 집계 연산(합계, 평균 등)을 수행하거나, 윈도우 기반의 데이터 분석을 하는 경우가 해당한다.  Kafka Streams는 내부 상태 저장소를 사용하여 이러한 상태 정보를 관리한다.

Stateful Processing의 구현: Kafka Streams는 RocksDB와 같은 분산 상태 저장소를 사용하여 상태를 관리하고, 복잡한 상태 기반 연산을 지원한다.

 

 

- Stream API와 DSL (Domain-Specific Language) 동시 지원

 

  • Stream API: 낮은 수준의 제어가 필요한 경우에 사용된다. Kafka Streams의 핵심 구성 요소와 연산을 직접 다루는 API로, 고급 사용자나 특정 요구 사항이 있는 경우에 적합하다.
  • DSL (Domain-Specific Language): 더 간단하고 직관적인 API로, 스트림 처리를 쉽게 정의할 수 있다. 사용자가 자주 사용하는 패턴을 지원하며, 복잡한 스트림 처리 작업을 더 간편하게 구현할 수 있다.

 

- Exactly Once 처리 보장

Kafka Streams는 Exactly Once Semantics (EOS)를 지원한다.

이것은 메시지가 정확히 한 번만 처리되도록 보장하는 기능으로, 데이터의 중복 처리나 손실을 방지한다.

Kafka의 트랜잭션 기능을 활용해 데이터가 중복되거나 손실되지 않도록 처리한다.

 

 

- 고가용성 (High Availability)

Kafka Streams는 복제와 분산 처리를 통해 높은 가용성을 지원한다.

상태 저장소와 처리 인스턴스가 클러스터 내에서 분산되어 있어 장애 발생 시에도 시스템이 계속 작동할 수 있다.

 

 

- Kafka Security 완벽 지원

  • ACL (Access Control Lists): Kafka의 ACL은 인증 및 권한 관리를 통해 보안을 강화한다. 특정 사용자나 애플리케이션이 특정 토픽에 대해 읽기, 쓰기 권한을 가질 수 있도록 제어한다.
  • SASL (Simple Authentication and Security Layer): SASL은 Kafka 클러스터와 클라이언트 간의 인증을 지원하는 프로토콜이다. 다양한 인증 메커니즘(예: PLAIN, SCRAM, GSSAPI)을 제공하여, Kafka 클러스터의 보안을 강화한다.

 

- Stream Processing을 위한 별도 클러스터

Kafka Streams 애플리케이션은 Kafka 클러스터와 별도로 동작할 수 있으며, 별도의 클러스터나 인프라에서 스트림 처리를 할 수 있다.

 

Kafka Connect

Kafka Connect는 Kafka와 외부 시스템 간의 데이터 이동을 자동화하고 단순화하는 도구이다.

이를 이용해 데이터를 Kafka로 가져오거나 Kafka에서 외부 시스템으로 전송할 수 있다.

코드 없이 Configuration으로 데이터를 이동하는 것이 목적이다 
Source System → Kafka Connect Source → Kafka Cluster → Kafka Connect Sink → Target System

 

  • Source System: 데이터가 출발하는 원본 시스템이다. (데이터베이스, 파일 시스템, API 등)
  • Kafka Connect Source: 원본 시스템에서 데이터를 Kafka 클러스터로 가져오는 컴포넌트이다. 이 컴포넌트는 Kafka Connect의 Source Connector를 사용하여 데이터를 Kafka 토픽으로 전송한다.
  • Kafka Cluster: Kafka의 중앙 데이터 저장소로, 토픽에 데이터가 저장된다. Kafka 클러스터는 데이터를 지속적으로 저장하고, 필요한 경우 컨슈머에게 제공한다.
  • Kafka Connect Sink: Kafka 클러스터에서 데이터를 가져와서 대상 시스템으로 전송하는 컴포넌트이다. Kafka Connect의 Sink Connector를 사용하여 데이터를 외부 시스템으로 이동한다.
  • Target System: 데이터가 전송되는 최종 목적지 시스템이다. (데이터 웨어하우스, 다른 데이터베이스, 애널리틱스 시스템 등)

 

  • 운영 모드:
    • Standalone Mode: 단일 작업 인스턴스에서 Kafka Connect를 실행하며, 소규모 또는 테스트 환경에서 유용
    • Distributed Mode: 여러 Kafka Connect 작업 인스턴스에서 실행하여 고가용성과 확장성을 지원한다. 대규모 데이터 처리와 생산 환경에서 사용된다.

 

  • REST API Interface:
    • Kafka Connect는 REST API를 통해 관리하고 제어할 수 있다. 이를 통해 커넥터의 상태 확인, 설정 변경, 작업 모니터링 등이 가능하다.
  • Stream 및 Batch 데이터 전송:
    • Stream: 실시간 데이터 스트림을 Kafka로 전송하고 처리한다.
    • Batch: 주기적으로 대량의 데이터를 배치 처리하여 Kafka로 전송하거나 Kafka에서 가져올 수 있다.
  • Custom Connector:
    • 기능: 기본 제공되는 커넥터 외에도 사용자 정의 커넥터를 개발하여 특수한 요구 사항에 맞게 데이터를 처리할 수 있다.
    • 장점: 다양한 플러그인을 사용하여 여러 데이터 소스와 싱크 시스템을 지원한다.

 

 

 

Kafka MirrorMaker

Kafka MirrorMaker는 클러스터 간의 데이터 복제를 위한 도구이다.

클러스터 간 데이터의 일관성을 유지하고 복제해 데이터의 가용성을 높이는 데 사용된다. 

 

Source Kafka Cluster → Mirror Maker → Target Kafka Cluster

 

 

  • Source Kafka Cluster: 데이터를 복제할 원본 Kafka 클러스터이다. 이 클러스터의 토픽과 데이터를 대상으로 복제한다.
  • Mirror Maker: Source Kafka Cluster에서 데이터를 읽어 Target Kafka Cluster로 전송하는 도구이다. MirrorMaker는 데이터를 읽고, 복제하며, 대상 클러스터에 전달한다.
  • Target Kafka Cluster: 데이터가 복제되어 저장되는 대상 Kafka 클러스터이다. 원본 클러스터의 토픽 및 데이터를 복제하여 보관한다.