DOIK 스터디 2기 - 5번째 글로 Kafka 개념 및 생태계에 대해 정리해본다.
공부하는 내용을 정리하는 글이라 부정확할 수 있음 주의
Apache Kafka는 실시간 이벤트 기반 애플리케이션 개발을 지원하는 오픈소스 분산형 스트리밍 플랫폼이다.
Kafka는 크게 3가지 기능을 통해 작업을 수행한다.
1. Application에서 Data 또는 Event stream을 Kafka로 Produce(발행)하거나 Subscription(구독)할 수 있다.
2. 서버는 항상 장애에 대비해야 한다. Kafka는 장애가 발생하더라도 처리하고 있는 데이터들을 안전하고 안정적인 방식으로 처리할 수 있도록 설계되어 있다.
3. 레코드들은 순서대로, FIFO 방식으로 Queue에 넣어서 실시간 처리된다.
Kafka 용어 정리
Kafka를 이해하기 위해서는 Kafka에서 사용하는 기본적인 용어들을 알고 있어야 한다.
1. 주키퍼(Zookeeper) : 분산 애플리케이션에서 코디네이터 역할을 수행하는 애플리케이션이다.
- Kafka의 Metadata 관리 및 Broker의 상태 점검을 담당한다.
2. Broker : Kafka 애플리케이션이 실제로 구동되는 인스턴스를 의미한다.
- Kafka Broker 인스턴스 중 한대는 Controller로의 역할을 수행한다.
- Controller는 특정 Broker에 장애가 발생할 경우 해당 Broker에 존재하는 Leader Partition을 재분배하는 역할을 수행한다.
3. Producer : Kafka로 Message를 보내는 역할을 하는 클라이언트를 뜻한다.
(특정 Topic으로 메시지 발행을 담당)
4. Consumer : Kafka에서 Message를 꺼내가는 역할을 하는 클라이언트를 뜻한다.
(특정 Topic을 구독 하여 메시지를 Polling하여 비즈니스 로직을 처리)
5. Topic : Message를 Topic이라고 하는 단위로 구분한다. (논리적으로 구분하는 단위)
6. Partition : 병렬 처리 및 고성능을 얻기 위해 하나의 Topic을 여러개로 나눈 것을 의미 (물리적으로 나눔)
- DB에서 Primary, Second로 나눈 것처럼 물리적으로 나눈 것을 의미하여 성능적으로 이득을 얻기 위해, 고가용성을 위해 Partition으로 나누게 된다.
7. Segment : Producer가 전송한 실제 Message가 Broker 내 특정 위치에 Local Disk에 저장되는 파일을 뜻한다.
8. Message, Record : Producer가 Broker로 전송하는 데이터 / Consumer가 읽어가는 데이터의 조각 및 단위를 뜻한다.
9. Replication : Broker의 장애에 대비하여 데이터를 유실되지 않고 안전하게 사용하기 위한 전략이다.
- 위에서 설명했듯이 Kafka의 복제 단위는 Partition이다.
- Partition은 Leader Partition, Follower Partition으로 구분된다.
Follower Partition은 Leader Partition의 Offset을 확인하고 자신의 Offset 차이와 비교하여 Sync를 수행한다.
- ISR(In-Sync Replica) : Leader와 Follower Partition이 모두 Sync 된 상황을 뜻한다.
여기까지 용어들을 간단하게 정리하였으니 좀 더 자세하게 알아보자.
Kafka Message
Kafka를 아주 간단하게 보자면 1) Producer가 Message를 발행하고 2) Consumer가 Message를 구독한다는 것이다.
여기서 Message란 무엇이며 Message의 구조, Message를 저장하는 논리적인 단위인 Topic과 물리적인 단위인 Partition에 대해서도 좀 더 알아보자.
Kafka Message 구조 (Message = Record)
Kafka message는 Timestamp, Headers, Offsets, Key, Value로 구성되어 있다.
Offset : Offset은 Producer가 정하는게 아닌 Producer가 전송한 Record가 Broker에 적재되는 순간 Offset 필드가 정의된다.
- Offset은 0부터 1씩 증가되며 중복 처리 위해 사용된다.
Header : 데이터 처리 시 참고될만한 정보들을 담는다.
Key : 처리하고자 하는 메시지 값의 분류를 위한 용도로 사용될 수 있다.
- Producer는 Topic(논리적인 단위) 내 어떤 Partition(물리적인 단위)로 Record로 보낼지 정해야 하는데 이는 다양한 Algorithm에 의해 결정된다.
- 이를 Partitioning이라고 하는데 Partitioner(파티셔닝을 수행하는 주체)가 Message Key를 기준으로 어떤 Topic에 어떤 Partition으로 보낼 지 기준을 정할 수 있다.
(참고) Partitioning 전략
1. Direct Partition Assignment : 직접 파티션을 지정하는 전략
2. Partitioning by kafka key : Message key에 의해 파티션을 지정하는 전략
3. Random Partitioning : 랜덤하게 파티션을 지정하는 전략
Message의 Key와 Value는 특정한 Schema를 가지게 된다. (RDB의 Table schema와 유사한 개념)
일반적으로 Producer와 Consumer가 동일한 Schema를 가지고 있어야 메시지를 발행하고 구독할 때 애플리케이션단에서 정상적인 데이터 처리를 할 수 있도록 보장할 수 있기 때문에 동일한 Schema를 가지고 있는 것이 매우 중요하다.
Schema 관리는 일반적으로 Kafka Schema Registry에서 관리할 수 있기도 하다.
Kafka Message - 직렬화, 역직렬화
Kafka는 Record를 Byte 형태의 배열로만 저장한다.
이러한 이유로 Producer에서 Kafka로 Record를 보낼 때나 Consumer에서 Kafka로부터 Record를 읽어들일 때에 JSON, Avro와 같은 형태로 Record를 직렬화 및 역직렬화를 수행해야 한다.
=> Producer 및 Consumer 설정에서 어떤 방식으로 직렬화 및 역직렬화를 수행할지 설정해야 함을 의미한다.
Producer
Producer는 다음의 역할을 담당한다.
1. 직렬화 (Serialization) : Serializer는 지정된 설정을 통해 Message key와 value를 어떤 Byte array로 변환할지 정한다.
2. 파티셔닝 (Partitioning) : 어떤 Partition으로 Record를 보낼지 정한다.
3. 압축 (Compression) : Record 압축 설정이 되어 있을 경우 설정된 포맷으로 압축을 수행한다. 대표적인 Message 압축 포맷은 gzip, snappy, lz4이 있다.
4. 메시지 배치 (Message Accumulator) : 설정값에 의거하여 Record들을 Queue에 저장했다가 한 번에 Broker에게 전달한다.
5. 전달 (Sender) : 실제로 Broker에게 보내야 하는 Record들은 Record Batch에 의해 전송된다.
Producing Process
Producer에서 Kafka로 Record를 발행할 때 몇가지 거쳐야하는 절차들이 있다.
1. Procuder에서 Record를 만들고 send() Method를 통해 Record를 보낸다.
2. Producer Config에서 기 지정한 Serializer 설정을 통해 특정 Byte Array(JSON, Avro, ..)로 변환되고 Partitioner에 의해 어떤 Partition으로 보낼지 결정할 수 있다.
3. Kafka에서는 성공, 실패 유무에 대한 metadata 정보를 응답으로 보내주게 되고 Producer의 Retry 설정을 통해 재시도를 할지 정하게 된다.
Producer 주요 설정
bootstrap.servers : 카프카 클러스터에 연결하기 위한 브로커 호스트, 포트 정보를 리스트로 기입한다.
acks : Producer가 Kafka Topic의 Leader Partition에게 Message를 보낸 후 요청을 완료하기 전 ack(승인) 수
1. ack=0 : ack를 기다리지 않음 (빠르게 메시지를 보낼 수 있지만 메시지가 손실될 가능성이 높음)
2. ack=1 : Leader Partition은 데이터를 기록하지만 모든 Follower Partition를 확인하지 않음 (메시지 손실 발생 가능성 O)
3. ack=all : Leader Partition은 ISR(In-Sync Replica) Follower Partition으로부터 데이터에 대한 ack(복제 유무)을 기다리기 때문에 데이터를 보장할 수 있다.
Consumer
Consumer는 특정 Topic을 구독(Subscription)하고 Topic 내 특정 Partition에 저장된 Record를 가져오는 역할을 하는 애플리케이션이다.
Consumer의 특징들은 다음과 같다.
1. 1개의 Topic에 서로 다른 Consumer Application이 동시에 구독할 수 있다.
- APP1이 Record를 가져가도 Record가 삭제되진 않는다. 각 Consumer는 어느 Topic의 어떤 Partition의 어느 Offset까지 읽었는지를 '_consumer_offset' 이라고하는 Topic에 저장하여 관리한다.
- 이렇게 함으로써 Consumer App이 중단 후 다시 구동되어도 자신이 어디서부터 Record를 읽어야하는지 _consumer_offset 토픽으로부터 확인하여 메시지를 다시 읽어들이게 된다. 이로 인해 안정적인 메시지 구독이 가능하게 된다.
2. Consumer Group을 통해 관리된다.
- Kafka Consumer는 1개 이상의 Consumer가 Consumer group을 구성하여 1개의 Topic을 구독할 수 있다.
- Consumer group 내 Consumer는 Topic Partition의 소유권을 나눠 갖는다.
>> 예를 들어, Consumer0, 1이 있고 3개의 Partition으로 이루어진 Topic A가 있다고 가정할 때 Consumer0은 Partition0을, Consumer1은 Partition 1, 2에 대한 소유권을 가지고 구독할 수 있다.
>> 이 때 Consumer group에 Consumer가 추가되거나 이탈될 경우 Consumer Group 내 Partition 소유권이 재조정되는데 이를 리밸런싱(Rebalancing)이라고 한다.
Consumer 주요 설정
group.id : 컨슈머가 속한 컨슈머 그룹을 식별하는 식별자
enable.auto_commit : 백그라운드에서 주기적으로 Offset을 Commit
auto.offsset.reset : Kafka에서 초기 Offset이 없거나 현재 Offset이 더 이상 존재하지 않은 경우에 다음 옵션을 통해 Reset
- earlist : 가장 초기의 오프셋값으로 설정
- latest : 가장 마지막의 오프셋값으로 설정 (default)
- none : 이전 오프셋값을 찾지 못하면 에러
max.poll.records : poll() 메서드에 대한 최대 레코드수를 조정 (default : 500)
max.poll.interval.ms : Consumer Group 내 Consumer가 살아 있지만 poll() 메서드를 호출하지 않을 경우 장애라고 판단
-> Consumer Group에서 해당 Consumer를 제외시킨 후 다른 컨슈머가 해당 Partition으로부터 Message를 가져감
(default : 5m)
auto.commit.interval.ms : 주기적으로 Offset을 Commit하는 시간 (default : 5s)
Kafka 생태계 간단 정리
Kafka 생태계에는 다양한 생태계들이 존재하는데 대표적으로 Schema Registry, Kafka Connect, Kafka Streams, KSQL 등이 존재한다.
위 사진을 보면 Kafka Streams와 KSQL은 Kafka와만 상호작용하는것을 확인할 수 있다.
이로 유추해봤을 때Kafka Streams와 KSQL은 Kafka의 데이터로 무언가를 처리하여 Kafka로 다시 적재하는 로직이 있을 것이라고 추측할 수 있다.
Kafka Connect는 Source DB로부터 Kafka로 적재하고 Kafka로부터 Target DB에 적재하는것 또한 유추할 수 있다.
1. Kafka Streams : Data Stream을 읽고 처리하여 다른 Topic으로 전송하거나 데이터를 집계하는 등의 작업을 수행할 수 있도록 도와주는 라이브러리이다.
- Library로 제공되기 때문에 복잡한 비즈니스 로직을 처리할 수 있다는 장점이 있다.
- Kafka 특정 Topic으로부터 데이터를 읽고 실시간으로 데이터를 발행할 수 있도록 도와준다.
Source Processor : 1개 이상의 Topic에서 데이터를 가져오는 프로세서
Stream Processor : 다른 프로세서가 변환한 데이터를 처리하는 역할 (분기 처리)
Sink Processor : 데이터를 특정 Topic으로 저장하는 역할
2. Kafka Connect : 데이터 소스(MySQL, S3, ElasticSearch, ..)와 Kafka 간 데이터 이동을 간단하게 관리 및 설정하는데 도움을 주는 플랫폼이다.
- Procuder 역할을 하는 Source Connector와 Consumer 역할을 하는 Sink Connector로 나뉜다.
- Source Connector : 데이터 저장소(Postgres, MongoDB, ..)에 있는 데이터로부터 Kafka에 데이터를 저장하기 위한 애플리케이션
- Sink Connector : Kafka에 저장된 Record를 읽고 대상 저장소(S3, ..)로 저장하기 위한 애플리케이션
내부 구조
- Connectors : Task를 관리하여 데이터 스트리밍을 조정하는 높은 수준의 추상화
- Tasks : Kafka에 데이터를 적재하거나 가져올 때 어떤 방식으로 처리할지에 대한 구현체
- Workers : Connector 및 Task를 실행하는 프로세스
- Converters : Connect와 데이터를 보내거나 받는 시스템 간 데이터 변환을 위한 코드
- Transforms : Connector에서 생성되거나 전송되는 각 메시지를 변경하는 간단한 로직
- DLQ : Connect에서 Connector의 오류를 처리하는 방법
3. KSqlDB : 내부 Topic을 구독하여 분석하거나, 구독한 토픽을 정제하여 다른 Topic으로 발행할 때 유사 SQL(KSQL)을 이용한 로직 구현을 하는데 도와주는 플랫폼이다.
- KSQL Engine이 있는 KSQL Server가 필요하다.
- 프로그래밍 처리(Kafka Streams) 없이 KSQL만으로 간단하게 처리할 때 사용한다.
KSQL Architecture
- KSQL Engine : KSQL Query가 실행되는 곳
- KSQL Interface : KSQL Engine에 Client로 액세스할 수 있는 인터페이스 (CLI, UI, ..)
KSQL 주요 용어
Stream : 구조화된 데이터의 연속된 데이터 (Immutable)
- Stream 데이터는 1) Kafka Topic으로부터 혹은 2) 이미 존재하는 Stream으로부터 파생하여 만들 수 있다.
Table : 변경되는 데이터의 현재 상태를 나타낸다. (Mutable)
즉, Stream은 순차적으로 들어오는 데이터를 뜻하며 Table은 현재 상태의 최신값으로 업데이트되어 보관된 데이터를 뜻한다.
State : 상태
- Stateless : 상태에 영향을 주지 않는 연산
- Stateful : 상태기반의 연산 (group by, count, ..)
4. Schema Registry : Kafka Client(Producer, Consumer)간 Record의 Schema를 저장, 관리하는 애플리케이션이다.
- 스키마는 데이터의 구조와 형식을 정의하는데 사용되며, 데이터 시스템에서 상호 운용성과 일관성을 유지하는 데 중요한 역할을 한다.
- Schema Registry는 이러한 Schema 중앙에서 저장, 관리, 검색할 수 있도록 지원하며, Kafka의 다양한 Producer, Consumer 간에 일관된 데이터 형식을 보장하게 해준다.
- 다양한 데이터 포맷과 프로토콜을 지원하며 Avro, JSON 등 다양한 스키마 형식을 다룰 수 있다.
Schema Registry 주요 기능
- Schema 등록, 버전 관리
- Schema 유효성 검사
- Schema 업데이트
- Schema 검색
Ref
https://blog.voidmainvoid.net/271
https://always-kimkim.tistory.com/entry/kafka101-broker
https://velog.io/@hyun6ik/Apache-Kafka-Producer
https://always-kimkim.tistory.com/entry/kafka101-message-topic-partition
'Database' 카테고리의 다른 글
[Database] Vector DB Milvus 공식 문서 정리 (0) | 2024.04.22 |
---|---|
[DOIK 스터디 2기] JMX를 통한 Kafka Connect 모니터링 (0) | 2023.11.18 |
[DOIK 스터디 2기] Percona Operator for MongoDB 개념 및 실습 (3) | 2023.11.12 |
[DOIK 스터디 2기] CloudNativePG (PostgreSQL 오퍼레이터) 알아보기 및 간단한 실습 (2) | 2023.11.03 |
[DOIK 스터디 2기] MySQL Operator on Kubernetes를 이해하기 위한 MySQL, InnoDB Cluster 개념과 MySQL Operator 구조 (1) | 2023.10.28 |