[백엔드 개발자 면접] Kafka

diense_kk·2024년 11월 30일
0

Interview

목록 보기
6/8

Kafka

Kafka는 분산형 스트리밍 플랫폼으로, 대량의 데이터를 안정적이고 실시간으로 처리할 수 있도록 설계되었다.
카프카는 주로 대량의 이벤트 스트림 데이터를 처리하고 여러 시스템 간에 데이터를 신속하게 전송하는데 사용된다.

카프카는 기업에서 대규모 데이터 처리 및 이벤트 기반 시스템을 구축하는데 사용되며, 대용량의 로그 데이터를 수집하고 분석하는데 유용하다.

Pub-Sub 모델의 메시지 큐 형태로 동작하며 분산환경에 특화되어 있다.

Kafka는 큐처럼 메시지가 생산(요청)된 순서대로 소비(소비자에게 응답)되는 특성이 있다.

Kafka 등장 전

Kafka 등장 전에는 각 애플리케이션과 DB가 End-To-End로 연결되어 있고, 요구사항이 늘어남에 따라 데이터 시스템 복잡도가 높아지면서 몇가지 문제가 있었다.

문제점

1) 시스템 복잡도 증가
특정 부분에서 장애 발생 시 조치 시간이 증가한다. 연결 되어있는 애플리케이션을 모두 확인해야 하기 떄문이다.
2) 데이터 파이프라인 관리의 어려움
새로운 파이프라인 확장이 어려워지면서, 확장성 및 유연성이 떨어짐

Pub-Sub 모델

Pub-Sub 모델은 Publish/Subscribe의 줄임말로 메시지 기반의 미들웨어 시스템을 말한다.
일반적으로 Server-Client 구조에서는 메시지를 전송할 떄는 Publisher가 Subscriber(Receiver)에게 직접 메시지를 전송한다.
하지만 Pub-Sub 모델에서는 Publisher는 어떤 Subscriber가 있는지 모르는 상태에서 메시지를 전송하고 Subscriber는 Publisher에 대한 정보 없이 자신의 Interest에 맞는 메시지만을 전송 받는 것을 말한다.

Publisher와 Subscriber가 직접적으로 연결되지 않는 것이 핵심이다.

카프카는 발행-구독(Pub-Sub)모델에서 브로커의 역할을 하고있다.
발행자(Publisher)와 구독자(Consumer) 사이에서 이벤트라 불리는 메시지를 받고, 전달한다.

Message Queue

메시지 큐는 메시지 지향 미들웨어를 구현한 시스템으로 프로그램 간의 데이터를 교환할 때 사용하는 기술이다.

Producer - 정보를 제공
Consumer - 정보를 제공 받아서 사용
Queue - Producer의 데이터를 임시 저장 및 Consumer에 제공

Message Queue에서 메시지는 Endpoint간에 직접적으로 통신하지 않고, 중간에 Queue를 통해 중개된다.

MQ의 장점

1) 비동기
Queue라는 임시 저장소가 있기 때문에 나중에 처리 가능
2) 낮은 결합도
애플리케이션과 분리
3) 확장성
Producer/Consumer 서비스를 원하는대로 확장할 수 있음 (서버 인스턴스를 늘릴 수 있음)
4) 탄력성
Consumer가 다운되더라도 애플리케이션이 중단되는 것은 아니기 때문에 메시지는 지속하여 MQ에 남아있는다.
5) 보장성
MQ에 메시지가 들어가면 모든 메시지가 Consumer 서비스에게 전달되는 것을 보장한다.

Message Broker VS Event Broker

둘은 공통적으로 Publisher가 메시지를 보내면 메시지를 저장했다가 Consumer가 가져갈 수 있도록 중간 다리 역할을 해주는 브로커이다.

둘의 가장 큰 차이점은 메시지를 소비하고 그 메시지를 바로 삭제하냐? 이다.

Message Broker는 Consumer가 큐에서 데이터를 가져가게 되면 즉시 짧은 시간 내에 큐에서 데이터를 삭제하는 특징이 있다.

하지만 Event Broker는 이벤트를 처리한 후에 바로 삭제하지 않고 저장하여, 이벤트 시점이 저장되어 있어서 Consumer가 특정 시점부터 이벤트를 다시 소비할 수 있는 장점이 있다.
예를들어, 장애가 발행한 시점부터 그 이후의 이벤트를 다시 처리할 수 있음

Message Broker - Redis, RabbitMQ
Event Broker - Kafka

Kafka 구성요소

Kafka Cluster

브로커들의 모임으로 확장성과 고가용성을 위해 Broker들이 클러스터로 구성되어 있다.

Broker

각각의 Kafka 서버를 말한다.
Producer에게 메시지를 전달받아 토픽에 저장하고 컨슈머에 저장한다.
하나의 브로커는 여러 개의 토픽을 가질 수 있다.

Zookeeper

Kafka의 분산처리를 위한 관리 도구이다.
Kafka 클러스터 상태와 정보 등을 관리하는 역할을 한다.
Zookeeper는 어떤 브로커가 특정 파티션 및 토픽의 리더인지 결정하고 리더 선택을 수행하는데 사용 된다.

한계 - Kafka 자체가 아닌 외부에서 메타데이터를 관리하여, Kafka 확장성에 제한이 된다.

KRaft 모드

KRaft 모드는 Kafka가 Zookeeper 없이 독립적으로 클러스터 메타데이터를 관리할 수 있게 해준다.
KRaft 모드를 통해 Kafka가 단순화 되어 확장성, 안정성, 일관성 등에 도움이 된다. Kafka 자체 관리 시스템이기 때문에 메타데이터의 일관성과 안정성을 보장한다.

Kafka 메타데이터 로그를 관리하는 Raft 쿼럼으로 클러스터 메타데이터의 각 변경사항에 대한 정보가 포함이 되어 Zookeeper에 저장되어 있는 모든 것을 대신 저장하고 있다.

Producer

메시지를 발행하는 주체이다. 메시지 발행 시 특정 토픽을 정하여 발행한다.

Consumer

메시지를 소비, 수신하는 주체이다. 특정 토픽을 구독하여 메시지를 전달 받는다.

Partition

분산 처리를 위해 사용 하는 것으로, Topic 생성 시 Partition 개수를 지정할 수 있다.(개수 변경이 가능하지만 추가만 가능하다. 줄이는건 불가능)
카프카의 토픽에 메시지가 쓰여지는 것도 어느정도 시간이 소비된다. 몇 천건의 메시지가 동시에 카프카에 write 되면 병목현상이 발생할 수 있다.

파티션이 1개라면 모든 메시지에 대핸 순서가 보장된다.
파티션이 여러개면 Kafka 클러스터가 라운드 로빈 방식으로 분배해서 분산처리 되기 때문에 순서를 보장하지 않는다.
파티션이 많으면 처리량은 좋지만 장애 복구 시간이 늘어난다.
파티션 내부에서 각 메시지는 Offset(고유번호)로 구분된다.

Offset

파티션 내에서 메시지의 위치(식별자)를 나타낸다. 책의 페이지 번호를 알면 해당 페이지로 바로 이동할 수 있듯이, 오프셋 값을 알면 해당 메시지로 바로 접근할 수 있다.

Consumer Group

컨슈머 그룹은 하나의 이상의 컨슈머가 모여 구성된 그룹이다.

컨슈머 그룹은 하나의 Topic에 대한 책임을 갖고 있다.
즉, 어떤 Consumer가 Down된다면, 파티션 재조정을 통해 다른 컨슈머가 해당 파티션의 sub을 맡아서 한다. Offset 정보를 그룹간에 공유하고 있기 때문에 down되기 전 마지막으로 읽었던 메시지 위치부터 시작한다.
한 그룹 안에 있는 여러 컨슈머들이 서로 다른 파티션에서 동일한 토픽을 동시에 소비하는 것이다.

Kafka에서 파티션당 하나의 컨슈머만 메시지를 처리할 수 있다. 따라서 파티션 개수와 컨슈머 개수를 동일하게 하면 모든 파티션을 병렬로 처리할 수 있어 성능을 극대화한다.

Kafka Broker 3개 추천

Kafka Broker를 최소 3개를 사용하는 것을 추천한다는 글을 봤다.

Producer acks

acks는 프로듀서가 보낸 데이터를 카프카가 정상적으로 수신했는지 확인하는 옵션이다.

1) acks = 0
acks 값이 0이라면, 프로듀서는 카프카에게 메시지를 전송하고 Leader 파티션이 메시지를 잘 받았는지 확인하지 않는다.
프로듀서가 메시지를 보내는 동안 Leader 파티션이 Down 되면 메시지 손실이 발생하고, 확인하는 과정이 없기 때문에 가장 빠르다.
메시지 손실을 감안하고 빠르게 보내야 하는 경우 사용할 수 있다.

2) acks = 1
acks 값이 1이라면, 프로듀서는 메시지를 전송하고 Leader 파티션이 메시지를 잘 받았는지 기다린다.
Leader 파티션이 메시지를 받았기 때문에 메시지 손실률은 acks 값이 0일때 보다 상대적으로 적으며 속도는 조금 더 느리다.

acks 값이 1이라도 메시지가 손실될 수 있는 경우가 있다
2-1) Leader 파티션이 메시지를 받은 뒤 프로듀서에게 정상 응답을 한다.
2-2) 그 후 Follower 파티션이 메시지를 복제하기 전에 Leader 파티션이 Down 된다면 메시지를 손실하게 된다.

3) acks = -1 or all
acks 값이 -1 or all 이라면, Leader 파티션이 정상적으로 수신했고 Follower 파티션도 복제가 안료됨을 보장할 수 있다. 데이터 손실률은 없지만 기다리는 시간이 길어지기 때문에 가장 느리다.

만약 브로커가 3개(1 Leader Broker + 2 Follower Broker)인 경우 Follower 1대만 복제에 실패한다면 프로듀서가 보낸 메시지는 실패할 수도 있고 아닐 수도 있다.
이 결과는 min.insync.replicas 값에 의해 좌우된다.

min.insync.replicas 옵션

min.insync.replicas 옵션은 프로듀서가 acks=all로 설정하여 메시지를 보낼 때 필요한 최소 복제본의 수를 의미한다.
이 옵션은 프로듀서가 아닌 브로커의 옵션이다.

1) min.insync.replicas 1
acks 값이 all이기 때문에 Leader Broker + Follower Broker 쓰기를 기다린다. 이때 Follower Broker의 복제가 실패하더라도 min.insync.replicas 값이 1이기 때문에 프로듀서에게 정상적으로 응답을 한다. 따라서 복제에 실패할 수 있다.

2) min.insync.replicas 2
값이 2이기 때문에 Leader + Follower 쓰기가 성공하면 정상적으로 응답한다. 만약 Follower Broker 복제에 실패하게 되면 에러가 발생한다.

min.insync.replicas 값과 관련하여 가장 중요한 것은 하나의 브로커의 개수가 min.insync.replicas 옵션 값보다 같거나 많아야 된다.
만약 값이 2인 상태에서 브로커 하나에 장애가 발생하면 애초에 브로커의 개수가 min.insync.replicas 개수 보다 작기 때문에 프로듀서는 데이터 전송에 실패한다.
아래 그림이 그 예시이다.

결론

위 그림을 보면 브로커 3대에 min.insync.replicas 값이 2이다. 1대의 Leader Broker와 2대의 Follower Broker 파티션이 있는데 최소 복제 수가 2이기 때문에 Follower 복제가 하나 실패하더라도 문제 없이 동작한다.
지금까지 본 예제중에 가장 안정적이다.

따라서 실무에서는 3대의 브로커를 사용하고 min.insync.replicas 값은 2로 설정하는 것이 가장 안정적이라고 한다. 다만 서비스에 맞게 메시지가 조금 손실되더라도 빠른 속도를 제공하고 싶다면 실무에서 프로듀서의 acks 값을 1로 설정하여 사용하는 경우도 많다고 한다.

0개의 댓글