티스토리 뷰
토픽 & 파티션
- 토픽은 카프카에서 데이터를 구분하기 위해 사용하는 단위이다.
- 파티션에는 프로듀서가 보낸 데이터들이 들어가 저장되는데 이 데이터를 레코드라고 부르며, 1개 이상의 파티션을 소유하고 있다.
- FIFO 구조와 같이 먼저 들어간 레코드를 컨슈머가 먼저 가져가게 된다.
- 일반적인 자료구조의 큐는 데이터를 가져가면 삭제 되지만 카프카에서는 삭제되지 않고, 파티션의 레코드는 컨슈머가 가져가는 것과 별개로 관리된다.
- 이런 특징때문에 토픽의 레코드는 다양한 목적을 가진 여러 컨슈머 그룹들이 토픽의 데이터를 여러번 가져갈 수 있다.
토픽 생성시 파티션이 배치되는 방법
- 파티션이 5개인 토픽을 생성했을 경우, 첫 번째 그림과 같이 0번 브로커부터 시작하여
round-robin
방식으로 리더 파티션들이 생성된다. - 카프카 클라이언트는 리더 파티션이 있는 브로커와 통신하여 데이터를 주고 받으므로, 여러 브로커에 골고루 네트워크 통신을 하게 된다.
- 이를 통해, 데이터가 특정 서버(여기서는 브로커)와 통신이 집중되는(hot spot) 현상을 막고,
scale out
하여 데이터가 많아지더라도 자연스럽게 대응할 수 있게 된다.
파티션 개수와 컨슈머 개수의 처리량
- 파티션은 카프카의 병렬 처리의 핵심으로써, 그룹으로 묶인 컨슈머들이 레코드를 병렬로 처리할 수 있도록 매칭된다.
- 파티션과 컨슈머는 1:1로만 매핑된다.
- 컨슈머의 처리량이 한정된 상황에서 많은 레코드를 병렬로 처리하는 가장 좋은 방법은 컨슈머의 개수를 늘려 스케일 아웃하는 것이다.
- 컨슈머 개수를 늘림과 동시에 파티션 개수도 늘리면 처리량이 증가하는 효과를 볼 수 있다.
파티션 개수를 줄이는 것은 불가능
- 카프카에서 파티션 개수를 줄이는 것은 지원하지 않기 때문에 파티션를 늘리는 작업을 할 때는 신중히 파티션 개수를 정해야 한다.
- 한번 늘리면 줄이는 것은 불가능하기 때문에 토픽을 삭제하고 재생성하는 방법 외에는 없기 때문이다.
- 카프카에서는 파티션의 데이터를 세그먼트로 저장하고 있으며, 만에 하나 지원을 할지라도 여러 브로커에 저장된 데이터를 취합하고 정렬해야하는 복잡한 과정을 거쳐야 하기 때문에 클러스러에 큰 영향이 가게 된다.
레코드
- 레코드는 타임스탬프, 헤더, 메시지 키, 메시지 값, 오프셋으로 구성되어 있다.
- 프로듀서가 생성한 레코드가 브로커로 전송될 때, 오프셋과 타임스탬프(옵션에 따라)가 지정되어 저장된다.
- 브로커에 한번 적재된 레코드는 수정할 수 없고, 로그 리텐션 기간 또는 용량에 따라서만 삭제된다.
레코드-타임스탬프
- 레코드의 타임스탬프는 스트림 프로세싱에서 활용하기 위한 시간을 저장하는 용도로 사용된다.
- 카프카 0.10.0.0 이후 버전부터 추가된 타임스탬프는
Unix timestamp
가 포함되며, 프로듀서에서 따로 설정하지 않으면 기본값으로ProducerRecord
생성 시간이 들어간다. - 브로커 적재 시간(
LogAppendTime
)으로 설정할 수도 있다.
레코드-오프셋
- 레코드의 오프셋은 프로듀서가 생성한 레코드에는 존재하지 않고, 프로듀서가 전송한 레코드가 브로커에 적재될 때 지정된다.
- 오프셋은 0부터 시작되어 1씩 증가한다.
- 컨슈머는 오프셋을 기반으로 처리가 완료된 데이터와 앞으로 처리해야할 데이터를 구분한다.
- 각 메세지는 파티션별로 고유한 오프셋을 가지므로 컨슈머에서 중복 처리를 방지하지 위한 목적으로도 사용한다.
레코드-헤더
- 레코드의 헤더는 0.11부터 제공된 기능이다.
key/value
데이터를 추가할 수 있으며, 레코드의 스키마 버전이나 포맷과 같이 데이터 프로세싱에 참고할만한 정보를 담아서 사용할 수 있다.
레코드-메시지 키
- 메시지 키는 처리하고자 하는 메시지 값을 분류하기 위한 용도로 사용되며, 이를 파티셔닝이라고 한다.
- 파티셔닝에 사용하는 메시지 키는 파티셔너(
Partitioner
)에 따라 토픽의 파티션 번호가 정해지는데, 메시지 키는 필수 값이 아니며, 지정하지 않으면null
로 설정된다. - 메시지 키가
null
인 레코드는 특정 토픽의 파티션에 라운드 로빈으로 전달된다. null
이 아닌 메시지 키는 해쉬값에 의해서 특정 파티션에 매핑되어 전달된다.
레코드-메시지 값
- 레코드의 메시지 값은 실질적으로 처리할 데이터가 담기는 공간이다.
- 메시지 값의 포맷은 제네릭으로
Float
,Byte[]
,String
(대부분String
사용)등 사용자에 의해 다양한 형태로 지정 가능하며, 필요에 따라 사용자 지정 포맷으로 직렬화/역직렬화 클래스를 만들어 사용할 수도 있다. - 브로커에 저장된 레코드의 메시지 값은 어떤 포맷으로 직렬화되어 저장되었는지 알 수 없기 때문에 컨슈머는 미리 역직렬화된 포맷을 알고 있어야 한다.
토픽 이름 제약 조건
- 빈 문자열 토픽 이름은 지원하지 않는다.
- 토픽 이름은 마침표 하나(
.
) 또는 마침표 둘(..
)로 생성할 수 없다. - 토픽 이름의 길이는 249자 미만으로 생성되어야 한다.
- 토픽 이름은 영어 대/소문자와 숫자 0~9, 마침표(
.
) 언더바(_
), 하이픈(-
) 조합으로 생성할 수 있고, 그 외의 문자열이 포함된 토픽 이름은 생성할 수 없다. - 카프카 내부 로직 관리 목적으로 사용되는 2개 토픽(
__consumer_offsets
,__transaction_state
)과 동일한 이름으로 생성 불가능하다. - 카프카 내부적으로 사용하는 로직으로 인해 토픽 이름에 마침표(
.
)와 언더바(_
)를 동시에 사용해서는 안 된다. 생성은 가능하지만 사용시 이슈가 발생할 수 있기 때문에 마침표(.
)와 언더바(_
)가 들어간 토픽 이름을 사용하면WARNING
메시지가 발생한다.
클라이언트 메타데이터
- 카프카 클라이언트는 통신하고자 하는 리더 파티션의 위치를 알기 위해 데이터를 주고(프로듀서) 받기(컨슈머) 전에 메타데이터를 브로커로부터 전달받는다.
- 메타데이터는 다음과 같은 옵션을 통해 리프레쉬(
refresh
) 된다.metadata.max.age.ms
: 메타데이터를 강제로 리프레쉬하는 간격, 기본값은 5분metadata.max.idle.ms
: 프로듀서가 유휴상태일 경우 메타데이터를 캐시에 유지하는 기간(예를 들어 프로듀서가 특정 토픽으로 데이터를 보낸 이후 지정한 시간이 지나고 나면 강제로 메타데이터를 리프레쉬), 기본값은 5분
클라이언트 메타데이터가 이슈가 발생한 경우
- 카프카 클라이언트는 반드시 리더 파티션과 통신해야 한다.
- 메타데이터가 현재의 파티션 상태에 맞게
refresh
되지 않은 상태에서 잘못된 브로커로 데이터를 요청하면LEADER_NOT_AVAILABLE Exception
이 발생한다. LEADER_NOT_AVAILABLE Exception
은 클라이언트(프로듀서 또는 컨슈머)가 데이터를 요청한 브로커에 리더 파티션이 없는 경우 나타나며, 대부분의 경우 메타데이터refresh
이슈로 발생한다. 이 에러가 자주 발생한다면, 메타데이터refresh
간격을 확인하고 클라이언트가 정상적인 메타데이터를 가지고 있는지 확인해야 한다.
'Apache Kafka' 카테고리의 다른 글
[Apache Kafka] 프로듀서 (Producer) (0) | 2023.04.24 |
---|---|
[Apache Kafka] 주키퍼(Zookeeper) & 브로커(Broker) (0) | 2023.04.11 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 문자열
- 데이터베이스
- 구현
- 인프런
- mysql 8.0
- 파이썬
- Spring
- webflux
- kotlin
- 리팩토링
- 알고리즘
- Algorithm
- 릿코드
- MySQL
- leetcode
- 스프링 부트
- 김영한
- 노마드코더
- 스프링
- Refactoring
- 노마드
- 백준
- 코테
- 코틀린
- spring boot
- 정렬
- 자료구조
- 그리디
- 북클럽
- Real MySQL
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함