카프카 기본 개념과 구조
책을 읽고 정리를 위해 메모한 내용에 대해 작성했습니다.
카프카 기초 다지기
카프카를 구성하는 주요 요소
- 주키퍼: 카프카의 메타데이터 관리 및 브로커의 정상상태 점검을 담당
- 카프카 또는 카프카 클러스터: 여러 대의 브로커를 구성한 클러스터를 의미
- 브로커: 카프카 애플리케이션이 설치된 서버 또는 노드
- 프로듀서: 카프카로 메시지를 보내는 역할을 하는 클라이언트를 총칭
- 컨슈머: 카프카에서 메시지를 꺼내가는 역할을 하는 클라이언트를 총칭
- 토픽: 카프카는 메시지 피드들을 토픽으로 구분하고, 각 토픽의 이름은 카프카 내에서 고유함
- 파티션: 병렬 처리 및 고성능을 얻기 위해 하나의 토픽을 여러 개로 나눈 것
- 세그먼트: 프로듀서가 전송한 실제 메시지가 브로커의 로컬 디스크에 저장되는 파일
- 메시지 또는 레코드: 프로듀서가 브로커로 전송하거나 컨슈머가 읽어가는 데이터 조각
리플리케이션
- 리플리케이션이란 각 메시지들을 여러 개로 복제해서 카프카 클러스터 내 브로커들에 분산시키는 동작을 의미
- 리플리케이션 동작 덕분에 하의 브로커가 종료되더라도 하나의 브로커 종료되더라도 카프카는 안정성을 유지할 수 있음
replication-factor: 카프카 내 몇 개의 리플리케이션을 유지하겠다는 의미의 옵션replication-factor가 1이라면 리플리케이션이 1개, 3이라면 원본을 포함한 리플리케이션이 총 3개라는 뜻peter-overview01토픽을 리플리케이션 팩터 수 3으로 설정한 후 브로커에 배치된 상태peter-kafka01 peter-overview01 peter-kafka02 peter-overview01 peter-kafka03 peter-overview01
- 실제로는 카프카에서 토픽이 리플리케이션되는 것이 아닌 토픽의 파티션이 리플리케이션되는 것
- 안정성을 목적으로 모든 토픽에 대해 각 3개의 리플리케이션으로 설정할 수 있음
- 리플리케이션 팩터 수가 커지면 안정성은 높아지지만 그만큼 브로커 리소스를 많이 사용하게 됨
- 복제에 대한 오버헤드를 줄여서 최대한 브로커를 효율적으로 사용하는 것을 권장
- 토픽 생성 시 다음과 같이 기준을 세워두고 리플리케이션 팩터 수를 설정해 사용한다면 좀 더 효율적으로 카프카를 운영할 수 있음
- 개발이나 테스트 환경: 리플리케이션 팩터 수를 1로 설정
- 운영 환경(로그성 메시지로서 약간의 유실 허용): 리플리케이션 팩터 수를 2로 설정
- 운영 환경(유실 허용하지 않음): 리플리케이션 팩터 수를 3으로 설정
- 안정성을 높이기 위해 리플리케이션 팩터 수를 늘릴 수도 있지만 저자의 경험 상 리플리케이션 팩터 수가 3일 경우에 충분히 메시지 안정성도 보장하고 적절한 디스크 공간을 사용할 수 있다고 함
파티션
- 파티션이란 하나의 토픽이 한 번에 처리할 수 있는 한계를 높이기 위해 토픽 하나를 여러 개로 나눠 병렬 처리가 가능하게 만든 것
- 하나를 여러 개로 나누면 분산 처리도 가능하며 이렇게 나뉜 파티션 수만큼 컨슈머를 연결할 수 있음
- 토픽과 파티션의 관계
브로커 토픽1 토픽2 토픽3 토픽1 파티션0 토픽3 파티션0 파티션1 파티션2 - 토픽1:
--partition 1옵션으로 파티션 1개를 가지는 토픽 - 토픽3:
--partition 3옵션으로 파티션 3개를 가지는 토픽
- 토픽1:
- 파티션 번호는 0부터 시작
파티션 수
- 파티션 수도 토픽을 생성할 때 옵션으로 설정하게 됨
- 파티션 수를 정하는 기준은 다소 모호한 경우가 많음
- 파티션 수는 각 메시지 크기나 초당 메시지 건수 등에 따라 달라지므로 정확하게 예측하기가 어려움
- 파티션 수는 초기 생성 후 언제든지 늘릴 수 있지만, 반대로 한번 늘린 파티션 수는 절대로 줄일 수 없음
- 초기에는 토픽 생성 시 파티션 수를 작게 2 또는 4 정도로 생성한 후 메시지 처리량이나 컨슈머의 LAG 등을 모니터링하면서 조금씩 늘려가는 방법이 가장 좋음
- LAG: 프로듀서가 보낸 메시지 수(카프카에 남아 있는 메시지 수) - 컨슈머가 가져간 메시지 수
세그먼트
- 프로듀서에 의해 브로커로 전송된 메시지는 토픽의 파티션에 저장되며, 각 메시지들은 세그먼트라는 로그 파일의 형태로 브로커의 로컬 디스크에 저장됨
- 파티션과 세그먼트의 관계
토픽3 파티션0 파티션1 파티션2 파티션0 세그먼트0 세그먼트1 파티션2 세그먼트0 세그먼트1 세그먼트2 - 각 파티션마다 N개의 세그먼트 로그 파일들이 존재
- 로그 파일 예
// 1. 로그 파일 위치로 이동
cd /data/kafka-logs/
// 2. 파일 목록 확인
ls
// 3. 0번 파티션 디렉토리로 이동
cd peter-overview01-0
// 4. 파일 목록 확인
ls
- 토픽, 파티션, 세그먼트의 관계도
- 프로듀서 -> 카프카 -> 컨슈머
- 카프카 -> 토픽 -> 파티션 -> 세그먼트:00.log
- 프로듀서 -> 카프카 -> 컨슈머
- 프로듀서는 카프카의 peter-overview01 토픽으로 메시지 전송
- peter-overview01 토픽은 파티션이 하나뿐이므로, 프로듀서로부터 받은 메시지를 파티션0의 세그먼트 로그 파일에 저장
- 브로커의 세그먼트 로그 파일에 저장된 메시지는 컨슈머가 읽어갈 수 있음
- 컨슈머는 peter-overview01 토픽을 컨슘해서 해당 토픽 내 파티션0의 세그먼트 로그 파일에서 메시지를 가져옴
카프카의 핵심 개념
- 카프카의 높은 처리량, 빠른 응답 속도, 안정성 때문에 많이 도입되고 있음
- 카프카가 높은 처리량과 안정성을 지니게 된 특성들을 하나씩 살펴보며 카프카를 좀 더 깊이 설명
분산 시스템
- 분산 시스템은 높은 성능을 목표로 하며 하나의 서버 또는 노드 등에 장애가 발생할 때 다른 서버 노드 또는 노드가 대신 처리하므로 장애 대응이 탁월하며, 부하가 높은 경우에는 시스템 확장이 용이함
- 카프카도 분산 시스템으로 최초 구성한 클러스터의 리소스가 한계치에 도달해 더욱 높은 메시지 처리량이 필요한 경우, 브로커를 추가하는 방식으로 확장이 가능함
- 카프카에서 브로커는 온라인 상태에서 매우 간단하게 추가할 수 있음
- 최초에는 하나의 카프카 클러스터가 총 3대의 브로커로 운영 중이어도, 서비스가 폭발적으로 증가할 경우 나중엔 총 30대 또는 50대 그 이상의 브로커 수로 확장할 수 있음
페이지 캐시
- 높은 처리량을 얻기 위해 몇 가지 추가한 기능 중 하나로 페이지 캐시가 사용됨
- OS의 페이지 캐시를 활용하는 방식으로 설계되어 있음
- 페이지 캐시는 직접 디스크에 읽고 쓰는 대신 물리 메모리 중 애플리케이션이 사용하지 않는 일부 잔여 메모리를 활용하여 디스크 I/O에 대한 접근이 줄어들므로 성능을 높임
- 카프카가 직접 디스크에서 읽고 쓰기를 하지 않고 페이지 캐시를 통해 읽고 쓰기를 한다고 이해
배치 전송 처리
- 카프카가 프로듀서, 컨슈머 클라이언트들과 서로 통신하며 수많은 메시지를 주고받는데 이때 발생하는 수많은 통신을 묶어서 처리하여 단건으로 통신할 때에 비해 네트워크 오버헤드를 줄일 수 있을 뿐만 아니라 장기적으로는 더욱 빠르고 효율적으로 처리할 수 있음
- 카프카에서는 지연 없이 실시간으로 처리되어야 하는 작업이 아니라면 배치 전송을 권장
압축 전송
- 카프카는 메시지 전송 시 좀 더 성능이 높은 압축 전송을 사용하는 것을 권장
- 카프카에서 지원하는 압축 타입
- gzip, snappy, lz4, zstd 등
- 배치 전송과 결함해 사용한다면 네트워크 대역폭이나 회선 비용 등을 줄이는데 높은 효과를 얻을 수 있음
- 파일 하나를 압축하는 것보다 비슷한 파일 10개, 혹은 20개를 압축하는 쪽의 압축 효율이 더 좋음
- 일반적인 압축 권장
- 높은 압축률이 필요한 경우라면 gzip이나 zstd를 권장
- 빠른 응답 속도가 필요하다면 lz4나 snappy를 권장
- 메시지 형식이나 크기에 따라 또 다른 결과를 나타낼 수 있으니 실제로 메시지를 전송해보면서 압축 타입별로 직접 테스트를 해보고 결정하는 것이 가장 좋음
토픽, 파티션, 오프셋
- 토픽이라는 곳에서 데이터 저장
- 이메일 주소 정도의 개념으로 이해하면 접근하기 쉬움
- 토픽은 병렬 처리를 위해 여러 개의 파티션이라는 단위로 다시 나뉨
- 파티셔닝을 통해 단 하나의 토픽이라도 높은 처리량을 수행할 수 있음
- 파티션의 메시지가 저장되는 위치를 오프셋이라고 부르며, 오프셋은 순차적으로 증가하는 숫자(64비트 정수) 형태로 되어 있음
- 각 파티션에서의 오프셋은 고유한 숫자로, 카프카에서는 오프셋을 통해 메시지의 순서를 보장하고 컨슈머에서는 마지막까지 읽은 위치를 알 수 있음
고가용성 보장
- 카프카는 분산 시스템이기 때문에 하나의 서버나 노드가 다운되어도 다른 서버 또는 노드가 장애가 발생한 서버의 역할을 대신해 안정적인 서비스가 가능함
- 이러한 고가용성을 보장하기 위해 리플리케이션 기능을 제공함
- 카프카에서의 리플리케이션
- 토픽 자체를 복제하는 것이 아닌 토픽의 파티션을 복제하는 것
- 토픽을 생성할 때 옵션으로 리플리케이션 팩터 수를 지정할 수 있으며, 이 숫자에 따라 리플리케이션들이 존재
- 원본과 리플리케이션을 구분하기 위해 리더와 팔로워라고 부름
- 리더는 하나이며, 리플리케이션 팩터 수에 따라 팔로워 수가 증가
- 팔로워 수가 늘면 안정적이고 좋을 것 같지만 디스크 공간도 소비되므로 이상적인 리플리케이션 팩터 수를 유지해야 함
- 일반적으로 권장하는 리플리케이션 팩터 수는 3으로 구성하는 것을 권장
주키퍼의 의존성
- 주키퍼는 다양한 분산 애플리케이션에서 코디네이터 역할을 하는 애플리케이션으로 사용되고 있음
- 주키퍼는 여러 대의 서버를 앙상블(클러스터)로 구성하고, 살아 있는 노드 수가 과반수 이상 유지된다면 지속적인 서비스가 가능한 구조
- 주키퍼는 반드시 홀수로 구성해야 함
- 지노드(znode)를 이용해 카프카의 메타 정보가 주키퍼에 기록되며, 주키퍼는 이러한 지노드를 이용해 브로커의 노드 관리, 토픽 관리, 컨트롤러 관리 등 매우 중요한 역할을 하고 있음
- 최근 들어 카프카가 점점 성장하면서 주키퍼 성능의 한계가 드러나기 시작하여 주키퍼의 한계에서 벗어나고자 카프카에서 주키퍼에 대한 의존성을 제거하려고 진행 중이며 주키퍼가 제거된 카프카 버전이 릴리스 예정
- 카프카의 중요한 메타데이터를 저장하고 각 브로커를 관리하는 중요한 역할을 하는 것이 주키퍼
프로듀서의 기본 동작과 예제 맛보기
(추가 예정)
컨슈머의 기본 동작과 예제 맛보기
(추가 예정)
참고 서적
- 실전 카프카 개발부터 운영까지(고승범, 책만)
'dev > 기타' 카테고리의 다른 글
| 카프카 스트림즈와 ksqlDB 정복 - 7장 Processor API (0) | 2023.07.04 |
|---|---|
| [정리] 실전 카프카 개발부터 운영까지(5) (0) | 2022.10.20 |
| [정리] 실전 카프카 개발부터 운영까지(1) (0) | 2022.07.19 |
| 특정 IP의 특정 Port Open 여부 확인 (0) | 2022.06.21 |
| Angular Git Commit Message Convention (0) | 2022.06.13 |