Kafka
Kafka 소개
Kafka의 탄생
- 2008년 LinkedIn에서 내부 실시간 데이터 처리를 위해 개발한 소프트웨어 플랫폼 (Scala, Java)
- 2011년 초에 오픈소스화 (Apache)
- 현재 포춘지 선정 100대 기업 중 80% 이상이 Kafka 사용
Kafka 소개
- 실시간 데이터 처리를 위한 오픈소스 분산 스트리밍 플랫폼
- Scalability와 Fault Tolerance를 제공하는 Publish-Subscription 메시징 시스템
- High Throughput & Low Latency으로 실시간 데이터 처리에 맞게 구현
- 분산 아키텍처를 따르기 때문에 Scale Out(서버=Broker) 형태로 스케일 가능
- 정해진 보유 기간 (retention period) 동안 메시지 저장
기존 메시징 시스템 및 데이터 베이스와 비교
- 기존 메시징 시스템과 달리 Kafka는 메시지 보유 기간 동안 저장
- Consumer가 오프라인 상태일 때도 Scalability와 Fault Tolerance을 보장
- 기본 보유 기간은 7일
- Kafka는 메시지 생산과 소비를 분리
- Producer와 Consumer가 각자의 속도에 맞춰 독립적으로 작업이 가능하도록 함
- 시스템 안정성을 높일 수 있음
- Kafka는 높은 처리량과 저지연 데이터 스트리밍을 제공
- 한 파티션 내에 메시지 순서 보장 (하나의 Topic은 다수의 파티션으로 관리)
- 다수의 파티션의 걸쳐서는 Eventual Consistent
- Topic을 생성할 때 지정 가능 (Eventual Consistency vs Strong Consistency)
- 처리량이 크고 다수의 소비자를 지원하기에 사내 내부 데이터 버스로 사용되기 시작
Eventual Consistency
- 다수의 서버로 구성된 분산 시스템에 레코드 하나를 쓴다면 바로 읽을 수 있을까?
- 보통 하나의 데이터 블록은 여러 서버에 나눠 저장됨 (Replication Factor)
- 데이터를 새로 쓰거나 수정하면 이게 전파되는데 시간이 걸림
- 읽기는 다수의 데이터 복사 중 하나를 대상으로 일어나기에 전파 시간에 따라 데이터의 유무 결정
- Strong Consistency vs Eventual Consistency
- 데이터를 쓸 때, 복제가 완료될 때까지 기다리는 구조라면 Strong Consistency
- 모든 데이터는 아니더라도 일부의 데이터로 리턴한다면 Eventual Consistency
Kafka 주요 기능 및 이점
- 스트림 처리
- 실시간 스트림 처리를 목표로 만들어진 서비스
- ksqlDB를 통해 SQL로도 실시간 이벤트 데이터 처리 가능
- High Throughput : 초당 수백만 개의 메시지 처리 가능
- Fault Tolerance : 데이터 복제 및 분산 커밋 로그 기능을 통해 장애 대응 용이
- Scalability : Kafka의 분산 아키텍처는 클러스터에 브로커를 추가하여 쉽게 수평 확장 가능
- 오랜 기간 오픈 소스 유지
- 커넥터와 통합 도구로 구성된 풍부한 에코 시스템을 통해 타 시스템 및 프레임워크와 쉽게 연동
- Kafka Connect, Kafka Schema Registry
Kafka 아키텍처
데이터 이벤트 스트림
- 데이터 이벤트 스트림을 Topic이라 부름
- Producer는 Topic을 만들고 Consumer는 Topic에서 데이터를 읽는 구조
- 다수의 Consumer가 같은 Topic을 기반으로 읽어 들이는 것이 가능
Message (Event) 구조 : Key, Value, Timestamp
- 최대 1MB
- Timestamp는 보통 데이터가 Topic에 추가된 시점
- Key 자체도 복잡한 구조를 가질 수 있음 (Partitioning)
- Header는 선택적 구성요소로 경량 메타 데이터 정보 (key-value pairs)
Kafka 아키텍처 : Topic과 Partition
- 하나의 Topic은 확장성을 위해 다수의 Partition으로 나뉘어 저장
- 메시지가 어느 Partition에 속하는지 결정하는 방식은 키의 유무에 따라 달라짐
- 키가 있다면, Hashing 값을 Partition의 수로 나눈 나머지로 결정
- 키가 없다면, 라운드 로빈으로 결정
Kafka 아키텍처 : Topic과 Partition 복제본
- 하나의 Partition은 Fail-over를 위해 Replication Partition을 가짐
- 각 Partition 별로 Leader와 Follower 존재
- 쓰기는 Leader를 통해 이뤄지고 읽기는 Leader/Follower들을 통해 이뤄짐
- Partition 별로 Consistency Level 결정 가능
Kafka 아키텍처 : Topic 파라미터
- 이름 : "MyTopic"
- Partition 수 : 3
- 복제본 수 : 3
- Consistency Level ("acks") : "all"
- 데이터 보존 기한 : default = 7d
- 메시지 압축 방식
- 파라미터 레퍼런스
Kafka 아키텍처 : Broker
- 실제 데이터를 저장하는 서버
- Kafka Broker를 Kafka Server 혹은 Kafka Node라고 부르기도 함
- Kafka 클러스터는 기본적으로 다수의 Broker로 구성
- 원활한 관리와 부가 기능을 위한 다른 서비스 추가 (Zookeeper가 대표적)
- 한 클러스터는 최대 20만 개까지 partition 관리 가능
- Broker가 실제로 Producer/Consumer와 통신 수행
- Topic의 Partition을 실제로 관리해 주는 것이 Broker
- 한 Broker는 최대 4000개의 Partition 처리 가능
- Broker는 물리 서버 혹은 VM 위에서 동작
- Broker의 수를 늘림으로써 클러스터 용량을 늘림 (Scale Out)
- Zookeeper를 사용하는 경우 20만 개, 4000개 제약이 있음, 이를 해결하기 위해 대체하는 KRaft 등장
Kafka 아키텍처 : 메타 정보 관리
- Broker 리스트 관리 (Broker Membership)
- Topic 리스트 관리 (Topic Configuration)
- Topic을 구성하는 Partition 관리
- Partition 별 Replica 관리
- Topic 별 ACL (Access Control Lists) 관리
- Quota 관리
Zookeeper와 Controller
- Kafka 0.8.2 (2015년)부터 Controller가 도입
- Controller는 Broker이면서 Partition 관리
- Zookeeper
- 3, 5, 7대의 서버를 Zookeeper Ensemble을 구성하기 위해 사용
- Controller가 Zookeeper를 통해 메타데이터 관리와 리더 선출 담당
- 하나의 Controller 존재
- KRaft
- Zookeeper를 완전히 배제하여 Controller가 역할을 대신 수행
- 다수의 Controller들이 Zookeeper 역할을 대신 수행
Zookeeper
- 분산 시스템에서 널리 사용되는 Distributed Coordination Service
- 원래 야후 Hadoop 프로젝트의 일부로 개발 (Java)
- 문제점
- 지원하는 데이터 크기가 작고 동기 모드로 동작하기에 처리 속도가 느림
- 확장성이 떨어지고 환경 설정이 복잡
Kafka 중요 개념
Producer, Broker, Consumer, Controller, Consumer Group
- Producer
- 대부분의 프로그래밍 언어로 작성 가능 (Java, Scala, Python, C/C++ 등)
- Command Line Producer 유틸리티도 존재
- Broker
- 하나의 Kafka 클러스터는 다수의 Broker로 구성
- 하나의 Broker는 다수의 Partition을 관리 및 운영
- Broker에 저장된 Partition, Replica의 관리는 Controller의 역할
- Consumer
- Topic을 기반으로 Message를 읽음
- Offset을 가지고 마지막으로 읽은 Message 위치 유치
- Command Line Consumer 유틸리티 존재
Topics, Partitions, Segments
- Topic
- Consumer가 데이터(Message)를 읽는다고 없어지지 않음
- Consumer 별로 어느 위치의 데이터를 읽고 있는지 위치 정보(offset)를 유지
- 다수의 Consumer가 병렬적으로 데이터를 읽어가도 문제 X
- Fault Tolerance를 위해 이 정보는 중복 저장됨
Partition과 Segment
- 하나의 Partition은 다수의 Segment로 구성
- Segment는 변경되지 않는 추가만 되는 로그 파일이라 볼 수 있음 (Immutable, Append-Only)
- 각 Segment는 디스크 상에 존재하는 하나의 파일
- Segment는 최대 크기가 있어서 이를 넘어가면 새로 Segment 파일을 만듦
- 각 Segment는 데이터 offset 범위를 갖게 됨
- Segment의 최대 크기는 1GB 혹은 일주일 치의 데이터
Commit Log
- Sequential, Immutable, Append-Only
- WAL (Write Ahead Logging)
- 데이터 무결성과 신뢰성을 보장하는 표준 방식
- 데이터베이스에 대한 모든 변경 사항을 먼저 Commit Log라는 추가 전용 파일에 기록
- Replication과 Fault Tolerance의 최소 단위
- Data Recovery와 Replay에 사용 가능
Broker의 역할
- Topic은 다수의 시간 순으로 정렬된 Message로 구성
- Producer는 Topic을 먼저 생성하고 속성 지정
- Producer는 Message를 Broker로 전송
- Broker는 이를 Partition으로 나눠 저장 (중복 저장)
- Consumer는 Broker를 통해 메시지를 읽음
Kafka 기타 기능
Kafka Connect
- Kafka Connect는 Kafka 위에 만들어진 중앙 집중 데이터 허브
- 별도의 서버들이 필요하며 Kafka Connect는 별도의 오픈 소스 프로젝트
- 데이터 버스 혹은 메시지 버스라고 볼 수 있음
- Standalone 모드와 Distributed 모드 존재
- 데이터 시스템 간의 데이터를 주고받는 용도로 Kafka를 사용
- 데이터 시스템 : 데이터베이스, 파일 시스템, key-value 저장소, 검색 인덱스 등
- 데이터 소스와 데이터 싱크
- Broker 중 일부나 별개 서버로 Kafka Connect 구성
- Task를 Worker가 수행, 여기서 Task는 Producer/Consumer 역할
- 외부 데이터(Data Source)를 이벤트 스트림으로 읽어오는 것이 가능
- 내부 데이터를 외부(Data Sink)로 내보내어 Kafka를 기존 시스템과 지속적으로 통합 가능
Kafka Schema Registry
- Schema Registry는 Topic 메시지 데이터에 대한 스키마를 관리 및 검증하는 데 사용
- Producer와 Consumer는 Schema Registry를 사용하여 스키마 변경을 처리
- Schema ID를 사용해 다양한 포맷 변천 (Schema Evolution)을 지원
- 포맷 변경을 처리하는 방법
- Forward Compatibility : Producer부터 변경 후 Consumer를 점진적으로 변경
- Backward Compatibility : Consumer부터 변경하고 Producer를 점진적으로 변경
- Full Compatibility : 둘 다 변경
Serialization과 Deserialization
- Serialization (직렬화)
- 객체의 상태를 저장하거나 전송할 수 있는 형태로 변환하는 프로세스
- 데이터 압축 등을 진행, 가능하다면 보내는 데이터의 스키마 정보 추가
- Deserialization (역직렬화)
- Serialized된 데이터를 다시 사용할 수 있는 형태로 변환하는 프로세스
- 데이터 압축 해제 등을 진행, 스키마 정보 등이 있다면 데이터 포맷 검증도 수행
Kafka 아키텍처 : REST Proxy
- 클라이언트가 API 호출을 사용하여 Kafka를 사용 가능하게 해 줌
- 메시지를 생성 및 소비하고, 토픽을 관리하는 간단하고 표준화된 방법을 제공
- REST Proxy는 메시지 Serialization과 Deserialization을 대신 수행해 주고 Load Balancing도 수행
- 특히 사내 네트워크 밖에서 Kafka에 접근해야 할 필요성이 있는 경우 유용
Kafka 아키텍처 : Steams와 KSQL
- Kafka Streams : Kafka Topic을 소비하고 생성하는 실시간 스트림 처리 라이브러리
- Spark Streaming으로 Kafka Topic을 처리하는 경우 micro batch에 가까움
- Kafka Streams로 Kafka Topic을 처리하는 경우 realtime에 가까움
- KSQL : Confluent에서 개발한 Kafka용 오픈 소스 SQL 엔진 (지금은 사용 X)
Kafka 아키텍처 : ksqlDB
- Kafka Streams로 구현된 스트림 처리 데이터베이스로 KSQL을 대체
- SQL과 유사한 쿼리 언어로 필터링, 집계, 조인, 윈도우잉 등 SQL 작업 지원
- 연속 쿼리 : 데이터가 실시간으로 도착할 때 지속적으로 처리하는 연속 쿼리 생성 가능
- 지속 업데이트되는 뷰 지원 : 실시간, 지속적으로 업데이트되는 집계 및 변환 가능
- Spark에서 보는 것과 비슷한 추세 -> SQL이 대세
Kafka Python 프로그래밍
간단한 Producer 만들기
from time import sleep
from json import dumps
from kafka import KafkaProducer
producer = KafkaProducer( # Producer 객체 생성
bootstrap_servers=['localhost:9092'], # Broker 중 하나 이상을 지정
value_serializer=lambda x: dumps(x).encode('utf-8')
)
for j in range(999):
print("Iteration", j)
data = {'counter': j}
producer.send('topic_test', value=data)
sleep(0.5)
Lambda 함수
- 람다 함수는 함수형 언어에서는 기본 개념
- Imperative Programming (Step-by-step) : Python, C/C++, Java
- Functional Programming (수학 공식처럼 함수를 연결해서 계산) : Erang, Lisp
- Declarative Programming (원하는 결과와 어디서 그걸 얻을지만 기술) : SQL
- 람다 함수를 사용하는 경우
- higher-order 함수(함수를 인자로 받는 함수)의 인자로 사용
- higher-order 함수 예 : map, filter, reduce, sorted, value_serializer
- 람다 함수 포맷
lambda 'arguments' : expression
간단한 Consumer 만들기
from kafka import KafkaConsumer
from json import loads
from time import sleep
consumer = KafkaConsumer(
'topic_test',
bootstrap_servers=['localhost:9092'],
auto_offset_reset='earliest',
enable_auto_commit=True,
group_id='my-group-id',
value_deserializer=lambda x: loads(x.decode('utf-8'))
)
for event in consumer:
event_data = event.value
# Do whatever you want
print(event_data)
sleep(2)
'[프로그래머스] 데이터 엔지니어링 데브코스 3기 > TIL(Today I Learn)' 카테고리의 다른 글
[TIL - 70일 차] Kafka와 Spark Streaming 기반 스트리밍 처리 (5) (0) | 2024.06.28 |
---|---|
[TIL - 69일 차] Kafka와 Spark Streaming 기반 스트리밍 처리 (4) (0) | 2024.06.28 |
[TIL - 67일 차] Kafka와 Spark Streaming 기반 스트리밍 처리 (2) (0) | 2024.06.25 |
[TIL - 66일 차] Kafka와 Spark Streaming 기반 스트리밍 처리 (1) (0) | 2024.06.24 |
[TIL - 65일 차] 하둡과 Spark (5) (0) | 2024.06.21 |