회사에서 Unity와 백엔드가 데이터를 주고 받는 채널들 중에 하나인 Kafka를 처음 접하게 되었고, 이에 대해 한 번 공부한 글을 정리하여 올려본다.
우선, Kafka에 대해 알아보기 이전에 Message Queue에 대해 먼저 알아보자.
1. Message Queue
간단하게 Queue(First In First Out)라는 자료구조를 통해 Message를 전달한다라고 생각하면 된다.
메시지 큐를 사용하면 발신자와 수신자가 서로를 직접 알 필요 없어지므로 발신자/수신자 서로가 서로에게 의존하지 않게 되어 ‘느슨한 결합’을 만들어 낼 수 있다.
또, 메시지 큐를 사용하면 비동기 통신을 구현할 수 있다. Producer가 메시지를 메시지 큐에 발행하고, Consumer가 그 메시지를 가져가는 방식으로 통신한다면 비동기적으로 통신이 이루질 수 있다.
그러면 이 때, 메시지를 전달하는 부분과 메시지를 받는 부분을 필요로 하는데 메시지를 받는 부분은 ‘Producer’라 하고, 메시지를 받는 부분을 ‘Consumer’라고 한다.
메시지 큐는 크게 Point to Point와 Pub/Sub 모델로 구분할 수 있다.
- Point to Point
- 한 대의 발신자가 한 대의 수신자에게 메시지를 보내는 방식이다. 즉, 메시지 전송 대상이 한 대로 고정 되어 있다.
- PUB/SUB
- 발신자가 토픽이라고 불리는 공간에 메시지를 전송하면, 그 토픽을 구독하고 있는 수신자 모두 메시지를 수신하는 방식이다. 즉, 전송 대상이 다수이다.
MOM(Message Oriented Middleware)이라고 하면 흔히 RabbitMQ, ActiveMQ, Kafka를 이야기한다. 여기서는 PUB/SUB 구조는 Kafka만 지원하고 있다.
또 다른 구분으로는 메세지 브로커와 이벤트 브로커로 크게 구분할 수 있는데,
- 메시지 브로커
- 앞에서 설명한 것과 같이 Producer가 메세지를 생성하며, Consumer가 메시지를 받게 되며 이때 Counsumer가 메시지를 받으면서 메세지 큐에서 삭제된다.
- 이벤트 브로커
- 이벤트 브로커는 메세지 브로커의 Producer/Consumer의 역할을 동일하게 수행하지만, Consumer가 받은 메세지를 바로 삭제하지 않고 재사용할 수 있다는 점이 다르다.
2. Kafka
Kafka는 이벤트 브로커 방식으로 작동되며, 이제 Kafka에 대해서 좀 더 자세히 알아보도록 하자.
2.1 Kafka는 어떻게 생겨났나?
카프카는 Linked In에서 만들어졌다. -> 지금은 Apache에서 관리 중이다.
Linked In은 기존 end-to-end 통신 방식에서 많은 문제점을 겪고 있었고, 이런 문제점들을 해결하기 위해 Kafka를 만들어 도입하게 되었다.
아래는 Linked In이 Kafka를 도입하기 이전의 end-to-end 방식으로 데이터를 처리하던 방식이다. 변경된 방식을 보면 확실히 더 직관적이고 중앙집중식의 관리를 하기 편하다는 것을 알 수 있다.
그렇다면 Kafka는 과연 어떻게 복잡한 데이터 흐름에 도움을 줄까?
- 통합/중앙화된 전송 영역을 설계할 수 있다.
- 메세지를 생성하는 Producer와 Consumer를 분리할 수 있다.
- 대용량 메세지 처리와 더불어 빠른 처리량을 이룰 수 있다.
- 확장(Scale-out)이 용이하도록 설계할 수 있다.
2.2 Kafka 개념
- 카프카 클러스터
- Kafka Broker들의 모임, 확정성과 고가용성을 위하여 Broker들이 클러스터로 구성되어 있음
- 브로커
- 각각의 Kafka 서버
- Producer로 부터 받은 메시지를 저장하고 관리하는 역할을 수행
- Producer
- 메시지를 발행하고 생산
- Acks 설정 가능: 브로커가 메시지를 수신했을 때 Producer에게 수신 완료했다는 응답을 나타냄
- 0: Partition 리더가 받았는지 확인 하지 않음 → 전송 속도가 매우 빠름
- 1: Partition 리더가 받았는지 확인(Default)
- ALL: Partition 리더 뿐만 아니라 팔로워까지 메시지를 받았는지 확인
- Consumer
- 메시지를 구독하여 소비
- 한 개의 Consumer는 여러 개의 Topic 처리가 가능
- Topic
- 메시지를 구분하는 단위
- 메시지를 전송하거나 소비할 때 Topic 이름이 필요
- Topic은 한 개 이상의 Partition으로 구성됨
- Partition
- 메시지를 저장하는 물리적인 파일
- Topic은 여러 Broker에 분산되어 저장되며, 이렇게 분산된 Topic을 Partition이라고 함
- Partition은 Producer로 부터 Kafka Broker로 들어오는 엄청난 양의 메시지를 병렬로 처리할 수 있게 해줌
- Offset
- Consumer는 Offset 기준으로 마지막 시점부터 메시지를 순서대로 읽어서 처리
- Zookeeper
- Kafka 모듈과 독립적인 모듈로 분산 애플리케이션의 데이터 관리 용도로 사용되며, Kafka에서는 메시지 큐의 데이터 관리자라고 생각하면 된다.
- Zookeeper는 Kafka Message Broker와 1:1로 구성된다.
- Kafka는 Zookeeper를 출시예정인 4.x 이후 버전에서는 완전히 제거한다고 발표하였다. Zookeeper를 삭제하고 Kafka Raft 프로토콜을 적용한 모드를 ‘Kafka Raft Mode(KRaft)’라고 한다. 3.X 버전에서는 Zookeeper와 KRaft를 선택하여 운영할 수 있다.
- 그렇다면 왜 Zookeeper를 없애는 결정을 했을까?
- Kafka 스케일링으로 인해 Zookeeper의 성능적 병목 현상이 발생하였기 때문에
- Kafka Broker가 Cluster에 참여하거나 제거될 때 다수의 Reader 선택이 발생해야 하며 이로 인해 Zookeeper에 과부하가 걸리고 Cluster 속도가 일시적으로 느려지는 점
- Kafka Cluster 메타데이터가 때때로 Zookeeper와 동기화되지 않는 점
- Zookeeper 보안이 Kafka 보안보다 뒤떨어져 있는 점
- 브로커는 모든 토픽과 파티션에 대한 메타데이터를 주키퍼에서 읽어야 하며, 메타데이터의 업데이트는 주키퍼에서 동기 방식으로 일어나고, 브로커에는 비동기 방식으로 전달되었다. 이 과정에서 메타데이터의 불일치가 발생할 수도 있으며, 컨트롤러 재시작 시 모든 메타데이터를 주키퍼로부터 읽어야 하는 것도 부담이 되는 점
- 주키퍼와 카프카는 완전히 서로 다른 애플리케이션으로, 주키퍼와 카프카 둘 다 모니터링을 해주어야 하는 점
- Kafka 스케일링으로 인해 Zookeeper의 성능적 병목 현상이 발생하였기 때문에
2022.03.23 카프카 삭제 이슈
첫번째 이슈 해결
velog.io
Apache Kafka Zookeeper 제거 이유
주키퍼를 없앤 카프카
velog.io
위 블로그에서 작성한 글과 발생한 문제점들을 살펴보면 좀 더 이해하기 쉬워질 것이다.
아직 Kafka를 운영 단계까지 적용한 레벨이 아니라 실제 운영 시 발생되는 문제점과 예상 가능한 문제점들이 명확히 몰랐지만 위 블로그를 통해 주의해야 하는 상황을 한 번 더 숙지하고 가게 되어 좋았다.
2.3 주키퍼 모드 vs KRaft 모드
- 주키퍼 모드
-
- 주키퍼 모드는 주키퍼 앙상블과 카프카 클러스터가 존재하며, 카프카 클러스터 중 하나의 브로커가 컨트롤러 역할을 하게 된다.
- 컨트롤러는 파티션의 리더를 선출하는 역할을 하며, 리더 선출 정보를 브로커에게 전파하고 주키퍼에 리더 정보를 기록하는 역할을 한다.
- KRaft 모드
-
- KRaft 모드는 주키퍼와의 의존성을 제거하고, 카프카 단일 애플리케이션 내에서 메타데이터 관리 기능을 수행하는 독립적인 구조가 되었다.
- 주키퍼 모드에서 1개였던 컨트롤러가 3개로 늘어나고, 이들 중 하나의 컨트롤러가 액티브 컨트롤러이면서 리더 역할을 담당한다. 리더 역할을 하는 컨트롤러가 write하는 역할도 하게 된다.
- 또한 메타 데이터 관리를 주기퍼가 했다면, 이제는 카프카 내부의 별도 토픽을 이용하여 메타 데이터를 관리한다.
- 액티브인 컨트롤러가 장애 또는 종료되는 경우, 내부에서는 새로운 합의 알고리즘을 통해 새로운 리더를 선출한다.
2.4 카프카 특징
- 다른 MOM과 비교했을 때 Kafka는 어떤 특징을 가질까?
- 높은 처리량과 낮은 지연시간: 대용량 데이터를 실시간으로 처리할 수 있도록 설계되었다. 따라서 높은 TPS를 가지며, 실시간 데이터 스트림, 로그 집계, 이벤트 드리븐 아키텍쳐(EDA) 구현에 적합하다.
- 메시지 내구성: 카프카 메시지는 메모리가 아닌 디스크에 영구적으로 저장된다. 비교 대상으로 Redis의 PUB/SUB은 메시지가 디스크에 저장되지 않으며, 장애 발생 시 메시지가 유실된다. 다른 MOM의 경우에도 메시지를 디스크에 영구 저장하는 옵션도 제공하지만, 일반적으로 소비된 메시지는 삭제된다.
- 분산 아키텍쳐
- Pull 기반 메시지 소비: RabbitMQ와 ActiveMQ는 브로커가 컨슈머로 메시지를 Push 하는 방식이지만, 카프카는 컨슈머가 능동적으로 브로커로부터 메시지를 가져오는 Pull 방식이다. 이 때문에 Consumer는 Producer의 간섭이 없기 때문에 의존성이 감소한다.
3. 마무리
Kafka를 알고 보니 다양한 곳에 적용 가능할 거 같다는 생각이 들었다.
하지만 역시 내부적으로 파고 들려니 쉽게 이해되지 않는 점도 있었지만 여러 IT 블로그들을 참고하여 조금 더 쉽게 습득한 것 같다.
회사에서 Kafka를 도입하여 사용하려고 하고 있지만 아직 개발 단계에 미쳐 실질적으로 메시지를 주고 받는 테스트 이외에는 확인해보지 못하였다.
일정 버전 이후의 버전을 사용한다면 Zookeeper를 사용함으로써 발생하는 문제점은 신경 쓰지 않아도 되지만, 혹시 모를 상황에 대해 이전 문제에 대한 히스토리를 알고 가는 것도 중요하다고 생각하였다. (현재 개발 단계에서는 KRaft 모드를 사용중)
하지만 사용하기에 앞서 이렇게 글로 한 번 정리를 하고 가니 좀 더 든든한 느낌이 들었다.
다음 포스팅에서는 Kafka를 사용하여 테스트한 것과 개념적으로 공부하면서 궁금했던 것들에 대해 추가적으로 테스트를 해볼려고 한다.
- 참고 자료:
[서버] 메세지 큐(Message Queue) 을 알아보자
안녕하세요 오늘은 메세지 큐(Message Queue) 에 대해 전반적인 이해와 대표적인 종류을 알아보겠습니다.메세지 큐 를 본격적으로 알아보기 전에 메세지 지향 미들웨어(MOM) 에 대해 알아보겠습니다.
velog.io
Apache Kafka
Apache Kafka: A Distributed Streaming Platform.
kafka.apache.org
[서버] Kafka 에 대해서
velog.io
카프카가 무엇이고, 왜 사용하는 것 일까?
메시지 큐와 MOM 출처: https://www.cloudamqp.com/blog/what-is-message-queuing.html 카프카를 이해하기 위해서는 메시지 큐와 MOM을 먼저 알아야한다. 메시지 큐는 분산화된 환경에서 발신자와 수신자 사이에서
hudi.blog
Apache Kafka의 새로운 협의 프로토콜인 KRaft에 대해(1)
devocean.sk.com