들어가기전
카프카를 학습하던 중 카프카 구성에 대한 그림이 머릿속에 잘 들어오지 않아 이번 글을 작성하게 되었습니다. 이 글에 나오는 대부분 이미지는 책(아파치카프카 애플리케이션 프로그래밍 with 자바)을 참조하여 그렸습니다.
카프카란?
카프카는 실시간으로 기록 스트림을 게시, 구독, 저장 및 처리할 수 있는 분산 데이터 스트리밍 플랫폼입니다.
극단적인 예로 아래와 같은 MSA Service가 있다고 가정합니다.
아키텍처의 복잡도가 매우 높은 것을 한 눈에 알아볼 수 있습니다. 다음 그림은 카프카를 도입하여 아키텍처를 재설계한 그림입니다.
극단적인 예를 들기 위한 아키텍처 그림입니다. 실제로는 무조건 카프카를 쓰기보다 용도에 맞게 사용해야합니다.
이 것 말고도 다양하게 카프카를 사용할 수 있습니다.
다음으로 카프카 구성에 대해 알아보겠습니다.
Name | Description |
카프카 클러스터 | 카프카 서버 |
브로커 | 카프카 클라이언트와 데이터를 주고받기 위해 사용하는 주체 데이터를 분산 저장하여 장애가 발생해도 안전하게 사용할 수 있도록 도와주는 애플리케이션 |
토픽 | 데이터를 구분하기 위해 사용하는 단위 |
파티션 | 프로듀서가 보낸 데이터들이 들어가 저장되는 곳 카프카 병렬처리의 핵심 개념 |
프로듀서 | 카프카의 시작점 데이터를 선언하고 브로커의 특정 토픽의 파티션에 전송하는 애플리케이션 |
컨슈머 | 카프카 브로커에 적대된 데이터를 가져오는 애플리키에션 |
자세히 알아보겠습니다.
카프카 브로커 / 클러스터 / 주키퍼
카프카 클러스터는 주키퍼와 연동하여 동작합니다.
카프카 클러스터의 브로커 중 리더를 선정할 때 주키퍼의 도움을 받습니다.
주키퍼는 내부에서 다수결을 통해 리더를 정합니다.
다수결 원칙이 성립하려면 주키퍼는 홀수로 구성되어야만 합니다.
리더가 정해집니다.
데이터 복제, 싱크
데이터 복제는 카프카를 장애 허용 시스템으로 동작하도록 하는 원동력입니다.
복제하는 이유는 클러스터로 묶인 브로커 중 일부가 장애가 발생하더라도 데이터를 유실하지 않고 안전하게 사용하기 위함입니다. 토픽을 생성할 때 복제 개수를 설정할 수 있습니다. ( 1: 복제 없음, MAX: 브로커 개수 )
- 브로커 0의 파티션 : 리더
- 브로커 1의 파티션 : 팔로워
- 브로커 2의 파티션 : 팔로워
브로커 0 장애 발생
브로커 0의 파티션( 리더 )에서 장애가 발생할 경우 다른 브로커의 파티션에게 리더를 위임합니다.
컨트롤러
클러스터의 브로커 중 하나의 브로커는 컨트롤러 역할을 합니다.
컨트롤러는 다른 브로커의 상태를 체크하고 장애가 생긴 브로커가 리더라면 리더를 재분배합니다.
컨트롤러가 장애가 생긴다면 다른 브로커에게 컨트롤러를 위임합니다.
컨슈머 오프셋 저장
컨슈머 그룹은 토픽이 특정 파티션으로부터 데이터를 가져가서 처리하고 이 파티션의 어느 레코드까지 가져갔는지 확인하기 위해 오프셋을 커밋합니다. 오프셋은 __consumer_offsets 토픽에 저장됩니다.
자세한 내용은 토픽과 파티션 챕터에서 다루겠습니다.
코디네이터
클러스터의 브로커 중 하나의 브로커는 코디네이터 역할을 합니다.
코디네이터는 컨슈머 그룹의 상태를 체크하고 파티션을 컨슈머와 매칭되도록 분배하는 역할을 합니다.
자세한 내용은 토픽과 파티션 챕터에서 다루겠습니다.
토픽과 파티션
토픽은 데이터를 구분하기 위해 사용하는 단위입니다. 토픽은 최소 1개 이상의 파티션을 가지고 있습니다. 파티션에 저장된 데이터를 레코드라고 부릅니다.
프로듀서가 전송한 레코드는 파티션에 저장됩니다. 파티션은 카프카의 병렬처리의 핵씸으로 그룹으로 묶인 컨슈머들이 레코드를 병렬로 처리할 수 있도록 매칭합니다.
파티션 vs 큐
파티션은 자료구조에서 큐와 비슷한 구조로 작동합니다.
하지만 큐는 데이터를 POP하면 레코드를 삭제하지만 카프카에서는 보관하고 있습니다.
파티션의 데이터는 파일로 저장되어 관리됩니다. 또한 데이터를 보관하는 정책을 설정할 수 있습니다.
- 일정 데이터가 쌓이면 삭제
- 일정 데이터가 쌓이면 압축하여 보관
컨슈머 개수를 늘려 스케일 아웃
왼쪽의 구조에서 오른쪽의 구조로 변경( 스케일 아웃 ) 하여 처리량을 늘릴 수 있습니다.
프로듀서
프로듀서는 토픽의 파티션에 데이터를 전송하는 애플리케이션입니다.
프로듀서는 Paritioner로 데이터를 Accumulator에 쌓아놓고 발송합니다.
Paritioner의 종류
- UniformStickyPartitioner : 일정 데이터를 쌓아놓고 묶어서 전송 ( 성능상 권장 )
- RoundRobinPartitioner: 순회하면서 전송
프로듀서는 Listener를 이용해 브로커에게 데이터를 정상 전송했는지에 대한 여부를 확인할 수 있습니다.
컨슈머
컨슈머는 토픽의 파티션의 데이터를 가져오는 애플리케이션입니다.
토픽의 데이터를 가져오는 컨슈머
토픽의 여러 파티션의 데이터를 하나의 컨슈머로 가져올 수 있습니다.
지정된 파티션의 데이터를 가져오는 컨슈머
토픽의 특정 파티션을 지정하여 해당 파티션의 데이터만 가져오도록 설정할 수 있습니다.
놀고있는 컨슈머
컨슈머 그룹에서 컨슈머 개수가 파티션의 개수보다 많으면 컨슈머는 아무런 동작을 하지 않습니다.
특정 컨슈머에 장애가 생긴 경우
컨슈머에 장애가 발생한 경우 리벨런싱이 발생 후 장애가 발생한 컨슈머를 제외시킵니다.
컨슈머 그룹을 이용한 처리
컨슈머 그룹이 다르면 그룹별로 파티션의 데이터를 가져올 수 있습니다.
오프셋 커밋
컨슈머는 데이터를 가져오면 처리 완료한 레코드의 오프셋을 커밋합니다.
오프셋 커밋 종류
- Auto ( 권장하지 않음. 데이터 중복처리 발생 )
- 비동기
- 동기
컨슈머 안전하게 종료
wakeup이라는 명령어를 날려 컨슈머가 종료되었다는 것을 알려주면 나머지 컨슈머들이 파티션을 할당받게 됩니다.
'Study > message-queue' 카테고리의 다른 글
Spring-Kafka Lifecycle (1) | 2021.09.04 |
---|---|
[kafka] @KafkaListener를 이용한 Consumer 구현 (0) | 2021.08.26 |
[kafka] Concurrency 설정 기준 (ConcurrentMessageListenerContainer 사용) (1) | 2021.08.24 |
[kafka] Message Listeners를 이용한 Consumer 구현 (0) | 2021.08.23 |
[kafka] KafkaTemplate을 이용한 Producer 구현 (1) | 2021.08.20 |