본문 바로가기

Database

[DOIK 스터디 2기] Kafka 개념 및 Kafka 생태계 개념 정리

반응형

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

https://aws.amazon.com/ko/message-queue

 

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://medium.com/@stephane.maarek/the-kafka-api-battle-producer-vs-consumer-vs-kafka-connect-vs-kafka-streams-vs-ksql-ef584274c1e

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

https://hoing.io/archives/5108

반응형