Kafka는 토픽 안에 파티션에 데이터를 저장한다. 브로커가 뭔지 프로듀서가 먼지 모르겠다면 해당 용어부터 빠르게 알고 넘어가자.
- 토픽 : 데이터를 구분하기 위해 사용하는 단위, 1개 이상의 파티션을 소유하고 있음.
- 파티션 : 프로듀서가 보낸 데이터들이 들어가 있는 데이터 덩어리. 한개의 데이터마다 레코드 단위로 이뤄짐. FIFO 구조.
- 레코드 : 한개의 데이터 단위
Partition
- 파티션은 Kafka의 병렬처리 핵심으로 컨슈머들이 레코드를 병렬로 처리할 수 있도록 매칭된다.
- 컨슈머 개술를 늘려 파티션의 개수도 늘리면 병렬 처리량이 증가 된다.
Topic
- 토픽 이름 제약조건
- 빈 문자열 토픽이름은 지원하지 않음
- 토픽이름은 . 혹은 .. 으로 생성될 수 없음, _ 와 . 가 동시에 들어갈 수도 없음
- __consumer_offset / __tranbsaction_state와 동일한 이름 사용불가
- 토픽은 우리 컴퓨터에서 폴더와 같은 것이다. 같이 개발하는 인원들이 알아보기 쉽게 정해야 한다.
Record
- 타임스탬프, 메세지키, 메세지 값, 오프셋, 헤더로 구성
- 타임스탬프 : 프로듀서가 생성한 날짜와 시간, 유닉스 타임으로 설정.
(임의로 프로듀서에서 데이터 발행 시 타임스탬프 값 설정 가능, 브로커에 적재된 시간으로 표시 가능) - 메세지 키 : 메세지 값을 순서대로 처리하거나 메세지 값의 종류를 나타내기 위해 사용
(키를 사용하지 않으면 라운드로빈 방식으로 파티션 할당 후 데이터 적재) - 메세지 값 : 실질적인 데이터, 메세지 값은 지렬화 되어 브로커로 전송되므로 컨슈밍 시엔 직렬화 형태 그대로 역직렬화 시행해야 함.
- 오프셋 : 해당 파티션에서 인덱스값
- 헤더 : 레코드의 추가적인 정보를 담는 메타데이터 저장소 용도로 사용, 해더는 키/값 형태로 데이터를 추가하며 레코드의 속성(스키마 버전 등)을 저장해 컨슈머에 참조 가능
- 타임스탬프 : 프로듀서가 생성한 날짜와 시간, 유닉스 타임으로 설정.
데이터 저장
- Kafka는 메모리나 데이터 베이스에 저장하지 않으며 따로 캐시 메모리를 구현해 사용하지도 않는다.
- 파일 시스템을 사용하기 때문에 메모리에 올려서 사용하는 것보다 느리다고 생각 할 수 있다.
- 그런데 어떻게 "고속" 메세징큐?
페이지 캐시 활용
- 페이지 캐시 : 파일의 입출력 향상을 위해 OS에서 만들어 놓은 메모리영역
- 쉽게 말해서 한번 읽어본 파일은 기억하고 있다가 다음에 또 열때는 디스크에서 찾을 것 없이 페이지 캐시 메모리에서 찾아내도록 만든 영역.
- 이런 특징으로 인해 Kafka 브로커를 위한 Heap size를 크게 설정할 필요가 없음.
- 시퀀셜 엑세스 : 순차적으로 디스크에 기록해 놓기 때문에 데이터를 찾기 위해 많은 시간이 걸리지 않음.
데이터 복제, 싱크
Replication
- 카프카 장애 허용 시스템으로 동작하도록 하는 원동력.
- 클러스터로 묶인 브로커 중 일부에 장애가 발생하더라도 데이터를 유실없이 사용하게 하기 위함
- 파티션 단위로 복제가 이뤄짐
(replication factor 옵션을 조절해 복재 개수를 설정, 기본값은 1로 최대 브로커 개수까지 정할 수 있음) - 복제 파티션은 리더와 팔로워로 구분된다.
- 리더 : 프로듀서와 컨슈머와 직접 통신하는 파티션
- 팔로워 : 리더 파티션의 복제본
- 팔로워 파티션은 리더 파티션의 오프셋을 확인하여 현재 자신이 가지고 있는 오프셋과 차이가 나는 경우, 리더 파티션으로 부터 데이터를 가져와서 자신의 파티션에 저장.(Replication 동작)
=> 이는 카프카의 강력한 장점으로 작용, 단 복제본 개수만큼 리소스를 더 차지함 - 리더 파티션을 가지고 있는 브로커가 다운되면?
- 해당 브로커에 있는 리더 파티션은 사용할 수 없어 팔로워 파티션 중 한개가 리더 지위를 받음.
- 서비스 운영을 끊지 않고 동작 => 고가용성
- 운영시엔 데이터 종류마다 다른 복제 개수를 설정, 상황에 따라서는 토픽마다 복제 개수를 다르게 설정
- 복제 개수가 적을 수록 당연히 데이터 처리속도가 빨라진다.
Controller
- 클러스터의 브로커들 중 한대가 이 역할을 수행함. 다른 브로커 상태를 체크, 브로커가 클러스터 이탈 시 리더 파티션 재분배 등의 역할.
- 컨트롤러 브로커에 장애가 발생한다면? 다른 브로커가 컨트롤러 역할 수행
데이터 삭제
- 디스크 기반 저장방식을 가지는 Kafka는 데이터를 컨슈밍 해도 삭제되지 않음.
- 브로커의 요청으로만 삭제 가능.삭제는 '로그 세그먼트'라는 파일단위로 삭제.
- 로그 세그먼트 : append only 성격을 가지며 데이터가 쌓이는 동안은 계속 열려있다.
- 세그먼트 파일이 닫히게 되는 용량이나 시간을 설정할 수 있는데 너무 자주 여닫도록 설정한다면 이로 부하가 발생할 수 있다.
- 데이터를 삭제해야 될 때 키값을 기준으로 데이터를 압축시키는 방법도 고려 가능하다.
- 컨슈머 그룹은 토픽이 특정 파티션으로부터 데이터를 가져가서 처리하고 이 파티션의 어느 레코드까지 가져갔는지 확인하기 위해 오프셋을 커밋함.
- __consumer_offsets 토픽에 저장
- 컨슈머 그룹은 이 토픽을 통해 어느 레코드까지 가져갔는지 알 수 있음.
데이터 소비
Coordinator
- 클러스 브로커들 중 한대가 이 역할을 수행. 컨슈머 그룹의 상태를 체크하고 파티션을 컨슈머와 매칭되도록 분배하는 역할
- 일부 컨슈머와 통신이 끊긴다면?
=> 리밸런스 과정을 거치게 함. - 이상적인 매칭은 파티션과 컨슈머의 1:1 매칭이라고 생각한다.
- 한개의 파티션에 한개의 컨슈머로 모든 파티션이 병렬로 동작할 수 있기 때문. 이 부분은 내가 경험했던 이야기와 함께 다시 상세히 설명하겠다.
그렇다면 Zookeeper의 역할은?
- Kafka의 메타데이터를 관리.
- 리더 파티션이 누군지, 컨트롤러가 누군지, 클러스터링 된 브로커들 등등 메타데이터(데이터의 데이터)를 가지고 있음.
- 추후 변경사항이 생기면 다시 파악해 변경된 데이터를 가지게 된다.
- **개인적인 생각으로 자주 변경될 거 같은 리더 파티션, 컨트롤러 .. 즉, 자주 죽을거 같은 브로커에 계속 이러한 역할을 부여 한다면 변경사항 때문에 Zookeeper와 잦은 통신해야 되는 소요가 발생하기 때문에 같은 브로커에서 장애가 난다면 엔지니어가 수동으로 역할을 지정해줄 필요가 있다고 생각한다.
참고자료
아파치 카프카 애플리케이션 프로그래밍 with JAVA - 최원영 지음 / 비제이퍼블릭
'Hadoop eco' 카테고리의 다른 글
[Kafka] Message Delivery Semantics (0) | 2023.05.23 |
---|---|
[Kafka] 기업 도입 사례들 (0) | 2023.05.23 |
[Hadoop] 03. YARN(Yet Another Resource Negotiator) (0) | 2022.12.18 |
[발표 자료] Flink, 왜 써야 할까? (1) | 2022.12.01 |
[발표 자료] Kafka를 다뤄본 경험 (0) | 2022.12.01 |