Search

[상세 내용] 카프카 기본 개념과 구조

2022.10.15(일)

카프카 기초 개념부터 알아두자.

카프카를 구성하는 주요 요소

카프카(kafka) or 카프카 클러스터(Kafka cluster) : 데이터를 받아서 전달하는 데이터 버스(data bus) 역할이며, 여러 대의 브로커를 구성한 클러스터를 의미한다. (아파치 프로젝트 애플리케이션 이름)
프로듀서(producer) : 카프카에 데이터(메시지)를 만들어서 주는 쪽을 말한다. (클라이언트를 총칭함)
컨슈머(consumer) : 데이터(메시지)를 빼내서 소비하는 쪽을 말한다. (클라이언트를 총칭함)
토픽(topic) : 메시지 피드들을 토픽으로 구분함, 각 토픽의 이름은 카프카 내에 고유하다.
주키퍼(ZooKeeper) : 카프카의 정상 동작을 보장하기 위해 메타데이터를 관리하는 코디네이터이며, 브로커의 정상상태 점검(health check)를 담당한다.
브로커(broker) : 카프카 애플리케이션이 설치된 서버 또는 노드이다.
파티션(partition) : 병렬 처리 및 고성능을 얻기 위해 하나의 토픽을 여러 개로 나눈 것을 말한다.
세그먼트(segment) : 프로듀서가 전송한 실제 메시지가 브로커의 로컬 디스크에 저장되는 파일을 말한다.
메시지(message) or 레코드(record) : 프로듀서가 브로커로 전송하거나 컨슈머가 읽어가는 데이터 조각을 말한다.

리플리케이션

예시) --partition 1, --replication-factor 3 위 옵션으로 peter-overview01 토픽 생성 의미) --replication-factor 3 : 카프카 내 원본을 포함한 3개의 리플리케이션을 유지하겠다.
JavaScript
각 메시지들을 여러 개로 복제해서 카프카 클러스터 내 브로커들에 분산시키는 동작을 말한다.
리플리케이션 동작으로 하나의 브로커가 종료되어도 카프카는 안정성을 유지할 수 있다.
주의할 점
리플리케이션 팩터 수가 커지면 안정성은 높아짐, But 브로커 리소스를 많이 사용하게 됨
복제에 대한 오버헤드를 줄여 최대한 브로커를 효율적으로 사용해야 함
토픽 생성 시 리플리케이션 팩터 수를 기준을 세워 효율적으로 카프카 운영하기
4 또는 5 이상으로 설정 가능하지만, 운영 경험 상 3일 경우 충분히 안정성 보장 및 적절한 디스크 공간을 사용할 수 있다.
테스트 및 개발환경 : 1로 설정
운영 환경(로그성 메시지로서 약간의 유실 허용) : 2로 설정
운영 환경(유실 허용하지 않음) : 3으로 설정

파티션

하나의 토픽이 한 번에 처리할 수 있는 한계를 높이기 위해, 하나의 토픽을 여러 개로 나눠 병렬 처리하는 것을 파티션이라고 한다. 이를 통해 병렬 처리뿐만 아니라, 분산 처리도 가능해진다.
주의할 점
컨슈머의 LAG 프로듀서가 보낸 메시지 수(카프카에 남아 있는 메시지 수) - 컨슈머가 가져간 메시지 수 LAG 지표를 통해 컨슈머에 지연을 확인할 수 있다.
파티션 번호는 0부터 시작한다.
❗️한 번 늘린 파티션 수는 절대로 줄일 수 없다.
위와 같은 이유로 초기에 작게 유지하면서 메시지 처리량 & 컨슈머의 LAG 등을 모니터링하여 조금씩 늘려야 한다.
적절한 파티션 수를 산정하기 위해 계산해주는 사이트(https://eventsizer.io/)도 존재한다. 그러나 무조건 가이드를 따라야 하는 것은 아니므로 이를 꼭 참고하자.

세그먼트

프로듀서에 의해 브로커로 전송된 메시지는 토픽의 파티션에 저장되고, 각 메시지들은 세그먼트라는 로그 파일의 형태로 브로커의 로컬 디스크에 저장된다. 프로듀서 → 브로커 → 파티션 → 브로커의 로컬 디스크(세그먼트 형태)

예시

1.
프로듀서는 카프카의 peter-overview01 토픽으로 메시지 전송
2.
peter-overview01 토픽은 파티션이 하나뿐이므로, 프로듀서로부터 받은 메시지를 파티션0의 세그먼트 로그 파일에 저장
3.
브로커의 세그먼트 로그파일에 저장된 메시지는 컨슈머가 읽어감

카프카는 왜 안정적이고, 높은 처리량을 갖게 되었을까?

위 질문에 답할 수 있는 핵심 개념에 대해서 알아보자.

분산 시스템

분산 시스템은 성능이 높다는 장점도 있지만, 하나의 서버에서 장애 발생 시 다른 서버가 처리 가능하기 때문에 장애 대응에 탁월하다. 그리고 부하가 높은 경우에 시스템 확장이 용이하다는 점이 있다.
카프카도 분산 시스템이므로 한계치에 도달했다면 브로커를 추가하는 방식으로 확장이 가능하다.

페이지 캐시

높은 처리량을 위해 추가된 기능이다. 카프카는 OS의 페이지 캐시를 활용하는 방식으로 설계되어 있다. (운영체제(OS)는 성능을 높이기 위해 꾸준히 발전되고 있는데 특히 페이지 캐시 활용이 대표적이다)
해당 기능으로 디스크 I/O에 대한 접근이 줄어든다. (카프카  페이지 캐시  디스크)

배치 전송 처리

수 많은 통신들을 묶어서 처리한다면 네트워크 오버헤드를 줄일 수 있고, 장기적으로 더욱 빠르고 효율적으로 처리 가능하다. 따라서 배치 전송이 단건 전송보다 훨씬 효율적이다.
카프카는 위와 같은 장점을 지닌 배치 전송을 권장한다.

압축 전송

카프커에서 성능이 높은 압축 전송을 사용하는 것을 권장한다. (지원하는 압축 방식은 gzip, snappy, lz4, zstd 등이 있다)
높은 압축률이 필요한 경우 : gzip, zstd 권장
빠른 응답 속도가 필요한 경우 : lz4, snappy 권장
그러나 위와 같이 절대적인 기준은 없으나 직접 테스트 해보고 결정하는 것이 좋다.
압축만으로 네트워크 대역폭이나 회선 비용 등을 줄일 수 있으므로, 배치 전송과 결합해 사용한다면 높은 효과를 얻을 수 있다.

토픽, 파티션, 오프셋

토픽 : 카프카는 토픽에 데이터를 저장한다. (메일 전송 시스템에서 이메일 주소 정도로 이해)
파티션 : 토픽은 병렬 처리를 위해 여러 개의 파티션으로 나뉜다. 즉, 하나의 토픽도 높은 처리량을 수행할 수 있다.
오프셋(offset) : 파티션의 메시지가 저장되는 위치이며, 순차적으로 증가하는 숫자(64비트 정수) 형태이다. 이를 통해 메시지 순서를 보장하고 컨슈머에서 마지막까지 읽은 위치를 알 수 있다.

고가용성 보장

카프카는 분산 시스템이라 하나가 다운되어도, 다른 곳에서 역할을 대신해 안정적인 서비스가 가능하다.
원본과 리플리케이션을 구분하기 위해 카프카에서는 리더와 팔로워라고 부른다.
참고로 리플리케이션은 토픽 자체를 복제하는 것이 아니라 토픽의 파티션을 복제하는 것이다.
리더(reader) : 프로듀서, 컨슈머로부터 오는 모든 읽기와 쓰기 요청을 처리한다.
팔로워(follower) : 오직 리더로부터 리플리케이션하게 된다.

주키퍼의 의존성

주키퍼는 지노드를 이용해 브로커의 노드 관리, 토픽 관리, 컨트롤러 관리 등 매우 중요한 역할을 하고 있다.
지노드(znode) : 카프카의 메타 정보가 주키퍼에 기록된다.
2021년 말 또는 22년 초 무렵 주키퍼가 삭제된 버전이 릴리즈
카프카가 성장하면서 주키퍼 성능의 한계가 드러났다.

프로듀서는 어떻게 동작할까?

프로듀서 디자인 및 전체 흐름

1.
ProducerRecord : 카프카로 전송하기 위한 실제 데이터이며 아래와 같이 구성된다.
레코드는 토픽, 파티션, 키, 벨류로 구성
레코드 전송할 때, 카프카의 특정 토픽으로 메시지 전송하는데 토픽, 벨류(메시지 내용)은 필수 & 특정 파티션을 지정하는 파티션과 레코드들을 정렬하기 위한 키는 선택사항이다.
2.
프로듀서의 send() 메소드를 통해 시리얼라이저와 파티셔너를 거치게 된다.
파티션을 지정한 경우 : 파티셔너는 아무 동작하지 않고 지정된 파티션으로 레코드를 전달한다.
파티션을 지정하지 않은 경우 : 키를 가지고 파티션을 선택해 레코드를 전달한다. 그리고 기본적으로 라운드 로빈 방식으로 동작한다.
send() 메소드 호출 이후 : 레코드들을 파티션별로 잠시 모아둔다. 프로듀서가 카프카 전송 전, 배치 전송을 하기 위함이다. (전송 실패 시 재시도 동작을 하게 되고, 지정된 횟수만큼 재시도하게 되면 최종 실패하게 됨, 성공 시 메타 데이터 반환 )

❗️TODO : 프로듀서 주요 옵션

컨슈머는 어떻게 동작할까?

❗️TODO : 컨슈머 주요 옵션

❗️TODO : 컨슈머 그룹의 이해