데브코스(DE)/스트리밍 데이터 처리
01. Kafka
jxwxnk
2024. 6. 29. 22:45
반응형
Kafka, Kafka 아키텍처, 중요 개념, Kafka Python 프로그래밍
Kafka 소개
Kafka란?
- 실시간 데이터를 처리하기 위해 설계된 오픈소스 분산 스트리밍 플랫폼
- 데이터 재생이 가능한 분산 커밋 로그(Distributed Commit Log)
- Scalability와 Fault Tolerance를 제공하는 Publish-Subscription 메시징 시스템
- Producer-Consumer
- High Throughput과 Low Latency 실시간 데이터 처리에 맞게 구현됨
- 분산 아키텍처를 따르므로 Scale Out 형태로 스케일 가능
- 서버 추가를 통해 Scalability 달성(서버 == Broker)
- 정해진 보유기간(retention period)동안 메시지 저장
기존 메시징 시스템 및 데이터베이스와의 비교
- 기존 메시징 시스템과 달리, 카프카는 메시지를 보유 기간 동안 저장
- 소비자가 오프라인 상태일 때에도 내구성과 내결함성 보장
- 기본 보유 기간은 일주일
- Kafka는 메시지 생산과 소비를 분리
- 생산자와 소비자가 각자의 속도에 맞춰 독립적으로 작업 가능하도록 함
- 시스템 안정성을 높일 수 있음
- Kafka는 높은 처리량과 저지연 데이터 스트리밍 제공
- Scale-Out 아키텍처
- 한 파티션 내에서는 메세지 순서를 보장해줌
- 다수의 파티션에 걸쳐서는 "Eventually Consistent"
- 토픽을 생성할 때 지정 가능(Eventual Consistency vs. Strong Consistency)
- 사내 내부 데이터 버스로 사용되기 시작
- 워낙 데이터 처리량이 크고 다수 소비자를 지원하기에 가능
Eventual Consistency란?
100대 서버로 구성된 분산 시스템에 레코드를 하나 쓴다면 그 레코드를 바로 읽을 수 있을까?
- 내가 쓴 레코드가 리턴이 될까?
- 보통 하나의 데이터 블록은 여러 서버에 나눠 저장됨(Replication Factor)
- 그래서 데이터를 새로 쓰거나 수정한면 전파되는데 시간 소요
- 보통 읽기는 다수의 데이터 카피 중 하나를 대상으로 일어나므로 앞서 전파 시간에 따라 데이터가 있을 수도, 없을 수도 있음
Strong Consistency vs. Eventual Consistency - 보통 데이터를 쓸 때, 복제가 완료될 때까지 기다리는 구조라면 Strong Consistency
- 그게 아닌 바로 리턴한다면 Eventual Consistency
Kafka의 주요 기능 및 이점
- 스트림 처리
- Kafka는 실시간 스트림 처리를 목표로 만들어진 서비스
- ksqlDB를 통해 SQL로도 실시간 이벤트 데이터 처리 가능
- High Throughput(높은 처리량)
- Kafka는 초당 수백만 개의 메시지 처리 가능
- Fault Tolerance(내결함성)
- Kafka는 데이터 복제 및 분산 커밋 로그 기능을 제공하여 장애 대응 용이
- Scalability(확장성)
- Kafka의 분산 아키텍처는 클러스터에 브로커를 추가하여 쉽게 수평 확장 가능
- 풍부한 생태계의 존재
- Kafka는 커넥터와 통합 도구로 구성된 풍붓한 에코시스템을 갖추고 있어 다른 데이터 시스템 및 프레임워크와 쉽게 연동 가능
- Kafka connect, Kafka Schema Registry
Kafka 아키텍처
데이터 이벤트 스트림
데이터 이벤트 스트림을 Topic이라고 함
* Producer은 Topic 생성, Consumer은 Topic에서 데이터를 읽어들이는 구조
* 다수의 Consumer가 같은 Topic을 기반으로 읽어들이는 것이 가능
Message(Event) 구조: Key, Value, Timestamp
- 최대 1MB
- Timestamp는 보통 데이터가 Topic에 추가된 시점
- Key 자체도 복잡한 구조를 가질 수 있음
- Key가 나중에 Topic 데이터를 나눠 저장할 때 사용됨 (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을 설정 가능(in-sync replica = "ack")
Kafka 아키텍처: Topic 파라미터
- 이름: “MyTopic”
- Partition의 수: 3
- 복제본의 수: 3
- Consistency Level (“acks”): “all”
- 데이터 보존 기한: 기본 일주일
- 메세지 압축 방식 등
Kafka 아키텍처: Broker - 실제 데이터를 저장하는 서버
- Kafka 클러스터는 기본적으로 다수의 Broker로 구성됨
- 여기에 원활한 관리와 부가 기능을 위한 다른 서비스들이 추가됨(Zookeper가 대표적)
- 한 클러스터는 최대 20만개까지 partition을 관리 가능
- Broker들이 실제로 Producer/Consumer들과 통신 수행
- Topic의 Partition들을 실제로 관리해주는 것이 Broker
- 한 Broker는 최대 4000개의 partition 처리 가능
- Broker는 물리서버 혹은 VM 위에서 동작
- 해당 서버의 디스크에 Partition 데이터들을 기록함
- Broker의 수를 늘림으로써 클러스터 용량을 늘림(Scale Out)
- 앞에서 20만개, 4천개 제약은 Zookeeper를 사용하는 경우임
- 이 문제 해결을 위해서 Zookeeper을 대체하는 모드도 존재(KRaft)
Kafka 아키텍처: 메타 정보의 관리
- Broker 리스트 관리(Broker Membership)
- 누가 Controller인가? (Controller Election)
- Topic 리스트 관리(Topic Configuration)
- Topic을 구성하는 Partition 관리
- Partition별 Replica 관리
- Partition들을 관리해주는 역할을 하는 것이 Controller(Broker 중의 하나가 이 역할을 수행)
- Topic별 ACL(Access Control Lists)관리
- Quota 관리
Kafka 아키텍처: Zookeeper와 Controller
- Kafka 0.8.2(2015년)부터 Controller가 도입됨
- Controller는 Broker이면서 Partition 관리
- 장기적으로 Zookeeper의 사용을 최소화하거나 사용 자체를 없애려는 것이 목표
- 현재로는 두 가지 모드가 존재함
- Zookeeper 모드
- 3, 5, 7대의 서버를 Zookeeper Ensemble을 구성하기 위해 사용
- Controller가 Zookeeper를 통해 메타데이터 관리와 리더 선출 담당
- 하나의 Controller가 존재
- KRaft 모드
- Zookeeper을 완전히 배제 Controller가 역할을 대신 수행
- 다수의 Controller들이 Zookeeper 역할을 대신 수행
- Controller들은 보통 Broker들이기도 함
- Zookeeper 모드
Zookeeper란?
- 분산 시스템에서 널리 사용된는 Distributed Coordination Service
- 동기화, 구성 관리, 리더 선출 등 분산 시스템을 관리하고 조율하기 위한 중앙 집중 서비스 제공
- 원래 Yahoo! Hadoop 프로젝트의 일부로 자바로 개발됨
- 이후 Apache 오픈소스 소프트웨어로 변신
- 하지만 다양한 문제가 존재함
- 지원하는 데이터 크기가 작고 동기모드로 동작하기에 처리속도 떨어짐
- 즉, 일정 스케일 이상으로 확장성 떨어짐
- 환경설정 복잡함
- 그러다보니 Zookeeper를 사용하던 서비스들이 Zookeeper을 대체하기 시작
- ElasticSearch가 또 다른 예시
- 지원하는 데이터 크기가 작고 동기모드로 동작하기에 처리속도 떨어짐
- Zookeeper의 일반적인 사용 사례
- 메시지 큐를 위한 Apache Kafka
- 분산 데이터베이스 조정을 위한 Apache HBase
- 분산 스트림 처리를 위한 Apache Storm 등
Kafka 중요 개념
Partition과 Segment
- 하나의 Partition은 다수의 Segment로 구성됨
- Segment는 변경되지 않는 추가만 되는 로그 파일이라고 볼 수 있음(Immutable, Append-Only)
- Commit Log
- 각 Segment는 디스크 상에 존재하는 하나의 파일
- Segment는 최대 크기가 있어 이를 넘어가면 새로 Segment 파일을 생성함
- 그래서 각 Segment는 데이터 오프셋 범위를 갖게 됨
- Segment의 최대
로그 파일의 특성(Partition의 특성 -> 정확히는 Segment의 특성)
- 항상 뒤에 데이터(Message)가 쓰여짐: Append Only
- 한번 쓰여진 데이터는 불변(Immuatable)
- Retention period에 따라 데이터를 제거하기도 함
- 데이터에는번호(offset)가 주어짐
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으로 나눠 저장(중복 저장)
- Replication Factor: Leader & Follower
- Consumer는 Broker를 통해 메세지를 읽음
- 하나의 Kafka 클러스터는 다수의 Broker로 구성됨
- 햐나의 Broker는 다수의 Partition들을 관리/운영
- 한 Topic에 속한 Message들은 스케일을 위해 다수의 Partition들에 분산 저장
- 다수의 Partition들을 관리하는 역할을 하는 것이 Broker들
- 한 Broker가 보통 여러 개의 Partition들을 관리하며 이는 Broker가 있는 서버의 디스크에 저장됨
- Broker들 전체적으로 저장된 Partition/Replica의 관리는 Controller의 역할
- 하나의 Partition은 하나의 로그 파일이라고 볼 수 있음
- 각 Message들은 각기 위치 정보(offset)을 갖고 있음
- 이런 Message들의 저장 기한은 Retention Policy로 지정
Producer
- 대부분의 프로그래밍 언어로 작성 가능
- Java, C/C++, Scala, Python, Go, .Net, REST API
- Command Line Producer 유틸리티도 존재
Producer의 Partition 관리 방법
- 하나의 Topic은 다수의 Partition으로 구성되며 이는 Producer가 결정
- Partition은 두 가지 용도로 사용됨
- Load Balancing
- Sementinc Partitioning(특정 키를 가지고 레코드를 나누는 경우)
- Producer가 사용 가능한 Partition 선택 방법
- 기본 Partition 선택: hash(key) % Partition의 수
- 라운드 로빈: 돌아가면서 하나씩 사용
- 커스텀 Partition 로직을 구현할 수도 있음
Consumer
- Topic을 기반으로 Message를 읽어들임(Subscription이란 개념 존재)
- Offset을 가지고 마지막 읽어들인 Message 위치 정보 유지
- Command Line Consumer 유틸리티 존재
- Consumer Group라는 개념을 Scaling 구현
- Backpressure 문제 해결을 위한 방법
- Consumer는 다시 Kafka에 새로운 토픽을 만들기도 함
- 아주 흔히 사용되는 방법으로 하나의 프로세스가 Consumer이자 Producer 역할 수행
Kafka 기타 기능
Kafka Connect
- Kafka Connect는 Kafka 위에 만들어진 중앙집중 데이터 허브
- 별도의 서버들이 필요하며 Kafka Connect는 별도의 오픈소스 프로젝트임
- 데이터 버스 혹은 메세지 버스라고 볼 수 있음
- 두 가지 모드가 존재
- Standalone 모드: 개발과 테스트
- Distributed 모드
- 데이터 시스템들 간의 데이터를 주고 받는 용도로 Kafka를 사용하는 것
- 데이터 시스템의 예: 데이터베이스, 파일 시스템, 키-ㄱ밧 저장소, 검색 인덱스 등
- 데이터 소스와 데이터 싱크
- Broker들 중 일부나 별개 서버들로 Kafka Connect를 구성
- 그 안에 Task들을 Worker들이 수행. 여기서 Task들은 Producer/Consumer 역할
- Source Task, Sink Task
- 외부 데이터(Data Source)를 이벤트 스트림으로 읽어오는 것이 가능
- 내부 데이터를 외부(Data Sink)로 내보내어 Kafka를 기존 시스템과 지속적으로 통합 가능
- 예) S3 버킷으로 쉽게 저장
- 그 안에 Task들을 Worker들이 수행. 여기서 Task들은 Producer/Consumer 역할
Kafka Schema Registry
- Schema Registry는 Topic 메시지 데이터에 대한 스키마를 관리 및 검증하는데 사용
- Producer와 Consumer는 Schema Registsry를 사용하여 스키마 변경을 처리
- Schema ID(와 버전)를 사용해서 다양한 포맷 변천(Schema Evolution)을 지원
- 보통 AVRO를 데이터 포맷으로 사용(Protobuc, JSON)
- 포맷 변경을 처리하는 방법
- Forward compatibility: Producer부터 변경하고 Consumer를 점진적으로 변경
- Backward Compatibility: Consumer부터 변경하고 Producer를 점진적으로 변경
- Full Compatibility: 둘다 변경
- 누가 메세지의 serialization과 deserialization을 담당하는가?
- 보통 Kafka 관련 라이브러리가 해줌
Serialization과 Deserialization
Serialization(직렬화)
- 객체의 상태를 저장하거나 전송할 수 있ㄴ는 형태로 변환하는 프로세스
- 보통 이 과정에서 데이터 압축 등을 수행. 가능하다면 보내는 데이터의 스키마 정보 추가
Deserialization(역직렬화) - Serialized된 데이터를 다시 사용할 수 있는 형태로 변환하는 Deserialization
- 이 과정에서 데이터 압축을 해제하거나 스키마 정보 등이 있다면 데이터 포맷 검증도 수행
KsqlDB
- Kafka Streams로 구현된 스트림 처리 데이터베이스로 KSQL을 대체
- SQL과 유사한 쿼리 언어. 필터링, 집계, 조인, 윈도윙 등과 같은 SQL 작업 지원
- 연속 쿼리: KsqlDB를 사용하면 데이터가 실시간으로 도착할 때 지속적으로 처리하는 연속 쿼리 생성 가능
- 지속 업데이트되는 뷰 지원: 실시간으로 지속적 업데이트되는 집계 및 변환 가능
- Spark에서 보는 것과 비슷한 추세: SQL이 대세
반응형