Kafka 동작 원리

AIVILLAIN·2022년 11월 29일
0

Kafka 구성 요소

Replication

message 복제하여 클러스터 내 브로커들에 분산시키는 동작
하나의 브로커가 종료되어도 안정성 유지 가능
토픽 생성 시 replication factor 지정 가능
환경에 따른 factor 기준선정 (개발, 운영 등)

Partition

하나의 Topic에 대한 처리량을 높이기위해 병렬 처리가 가능하게 만든것
Partition 수만큼 Consumer 연결 가능
늘리는건 가능하나 줄이는건 불가능
초기에 적게 설정 후 메세지 처리량, 컨슈머 LAG 모니터링하며 늘리는 것 권장

※ 컨슈머 LAG
Producer가보 낸 메세지 수 - Consumer가 가져간 메세지수

Segment

Producer에 의해 Broker로 보내진 메세지는Partition에 저장됨
각 메세지는 Segment 라는 로그 파일 형태로 저장됨

OS의 페이지 캐시 사용하여 디스크 I/O 접근 줄어듬
batch전송, 압축 전송 (gzip, snappy, lz4, zstd)

Offset

Partition 내 메세지가 저장되는위치
64bit 정수 형태
파티션 내 메세지 순서 보장 및 읽은 위치 확인

Replication

토픽 자체 복제가 아닌 토픽의 파티션 복제
원본과의 구분을 위해 Leader, Follower로 구분
Follower 수만큼 브로커 디스크 공간소비

Zookeeper

여러 대의 서버를 앙상블(클러스터)로 구성
살아있는 노드가 과반수 이상 유지된다면 지속적 서비스 가능 (홀수로 구성하는 이유)
znode를 이용하여 카프카 메타 정보가 zookeeper에 저장됨

znode를 통해 broker의 node 관리, Topic 관리, controller 관리
카프카 성장에 따라 zookeep와 성능 한계가 드러나 의존성 제거하려 하는 중

Producer

Topic으로 메세지 전송
Record는 Topic, Partition, Key, Value로 구성
send 메소드를 통해 serializer, partitioner 거침
Record의 Partition 지정하지 않은 경우 Key를 기준으로 Partition 선택
Round Robin 방식으로 동작 (default)
send 메소드 동작 이후 레코드들을 각 파티션별로 잠시 모아둠 (batch)

Consumer

Topic에 저장되어 있는 메세지를 가져오는 역할
컨슈머 그룹, 리밸런싱 등 동작도 수행
Producer가 아무리 빨라도 Consumer가 읽어오지 못하면 자연 발생

Consumer는 반드시 Group에 속함
Group은 각 파티션 리더에게 토픽에 저장된 메세지 가져오기 위한 요청
파티션 수, Consumer 수(Group 내) 일대일 매핑이 이상적
Consumer가 파티션보다 많다고 처리량이 높아지진 않음

Replication된 Topic에 대한 Partition 중 Leader가 모든 읽기, 쓰기 담당
= Producer는 Leader에게만 메세지 보내고 Consumer는 오직 Leader로부터 메세지 가져옴

Follower는 Leader문제 발생시 언제든 새로운 Leader가 될 준비
지속적으로 Partition Leader가 새로운 메세지 받았는지 확인 + 받았으면 복제

Leader와 Follower는 ISR (In Sync Replica)로 묶임
해당 그룹 내 Follower만 새로운 리더 자격
Follower는 Leader 데이터를 따라가고, Leader는 Follower들이 메세지 받음을 대기
Follower가 특정 주기 시간만큼 복제 요청을 하지 않는 경우 ISR그룹에서 추방당함
ISR 점검을 통해 Topic의 상태 확인 가능
ISR 내 모든 팔로워의 복제 완료 시 Leader는 내부적으로 commit 되었다는 표시를 함
마지막 커밋 오프셋 위치를 하이워터마크라고 함

Leader와 Follower 사이 ACK 없음 (성능↑)
Replication을 위한 메세지 요청은 알고 있으나 동작의 성공여부는 알 수 없음

Leader가 push하는 방식이 아닌 Follower가 pull 하는 방식으로 리더의 부하 줄임

Leader Epoch

Partition들이 복구 동작 시 메세지의 일관성 유지를 위함
Controller에 의해 관리되는 32 bit숫자
새로운 리더 선정된 후 변경된 리더 정보는 Follower에게 전달됨
복구 시 하이워터마크 대체 수단으로도 사용됨

  • 리더와 팔로워 간 하이워터마크 일치하지 않는 순간에 장애 발생 시
    복구 과정에서 리더 에포크 요청/응답을 통해 하이워터마크 일치시킴
  • 장애 복구전 새로운 리더가 이후 메세지 받았을때
    하이워터마크는 같으나 데이터가 다름
  • 뉴리더는 팔로워일 때의 하이워터마크와 뉴리더일때의 하이워터마크를
    알고 있음
  • 리더만 읽기/쓰기 권한 있으므로 복구 시점 기준의 Follower 메시지 삭제

Controller

리더 선출을 맡음
클러스터 중 하나의 브로커가 컨트롤러 역할
파티션 ISR중 리더 선출
ISR정보는 Zookeeper에 저장되어 있음
브로커의 실패를 감시, 실패 감지 시 ISR에서 새로운 리더 선출
새로운 리더 정보 Zookeep에 기록 및 모든 브로커에 전달
파티션 리더 다운 → 읽기/쓰기 실패 →클라이언트 재시도 횟수 만큼 재시도
재시도 시간 내에 리더 선출해야함

제어된 종료에 따른 리더 선출
브로커 종료 전 리더 선출 작업을 하게 되므로 파티션들의 다운타임이 줄고
로그를 디스크에 동기화한 이후 종료하므로 복구 시간 줄어듬

(Log) Segment

토픽으로 들어오는 메세지는 세그먼트 파일에 정해진 형식으로 저장됨
기본 최대 크기 1GB, 커지는 경우 rolling 전략
(하나의 세그먼트에 계속해서 덧붙이다가 해당 용량 도달하면 새로운
세그먼트 생성)
무한히 늘어나는 것을 대비하여 삭제, 컴팩션으로 관리

  • 삭제(default)
    브로커의 설정파일에 명시되어 있어야함
    세그먼트기본 보관기한 7일
  • 컴팩션
    삭제하지 않고 컴팩션하여 보관
    메세지 키 기준 마지막 데이터만 저장
    과거 정보가 필요 없는 경우에 사용
    키를 사용하기에 메세지 전송시 Key 필수
    빠른 장애 복구 가능
    로그 컴팩션 작업 자체에 대한 리소스도 고민필요

Partitioner

토픽으로 메세지를 보낼 때 어느 파티션으로 보낼 지 결정
메세지의 키를 해시 처리하여 파티션을 구함
메세지 키가 동일하면 동일 파티션에 저장됨
파티션 수를 늘렸을 때 메세지 키와 매핑된 해시 테이블도 변경됨

Round Robin

메세지의 키 값이 없는경우
파티셔너를 거친 후 레코드들은 배치 처리를 위해 프로듀서의 버퍼 메모리에
잠시 대기 후 카프카로 전송(batch)

배치 처리를 위해 메세지들이 대기하는 과정에서 라운드 로빈 전략은
효율성이 떨어짐

스티커 파티셔닝 전략 (Kafka 2.4 later)

하나의 파티션에 레코드 수를 먼저 채워 빠르게 전송
30% 이상의 지연시간 감소 및 CPU 사용량 감소
처리량, 지연없는 전송의 우선순위에 따른 배치 계획 수립 필요

Consumer offset

마지막까지 읽은 위치가 아닌 읽어야 할위치

그룹 코디네이터

Consumer는 그룹의 구성원에 속하고, 컨슈머 그룹의 각 컨슈머는 서로
자신의 정보를 공유하면서 공동체로 동작
언제든 그룹에서 떠날 수 있고 합류할 수 있음
컨슈머 그룹은 변화를 인지하고 각 컨슈머들에게 작업을 균등하게
분배해야 함(컨슈머 리벨런싱)
컨슈머 그룹이 구독한 토픽의 파티션들과 그룹의 멤버들 트래킹
브로커 중 하나에 위치
컨슈머 변경 감지를 위해 하트비트 주고받음
리밸런싱은 비용이 높으므로 자주 발생하지 않도록 주의

스태틱 멤버쉽

하드웨어 점검, 소프트웨어 업데이트 등을 이유로 컨슈머들을 순차적으로
재시작 필요할 수 있음
하트비트 주기, 세션 타임아웃 등으로 컨슈머 재시작시마다 전체 리밸런싱
컨슈머 그룹은 각 컨슈머 식별을 위해 엔티티 ID부여
이 ID는그룹 내에서 임시로 사용됨
재시작 시 새로운 ID 부여되어 리밸런싱 일어남
재시작 등으로 그룹에서 나갔다 들어와도 인식할수 있는 ID를 적용하여
리밸런싱 일어나지 않도록
컨슈머 그룹 리더가 정해진 파티션 할당 전략에 따라 컨슈머와 파티션 매칭

Range Assignor (default)

각 토픽 별로 할당 전략 사용
구독하는 토픽에 대한 파티션 순서대로 나열, 컨슈머 순서대로 정렬
전체 파티션 수를 컨슈머 수로 나눔
일치하면 균등하게, 그렇지 않을 경우 앞쪽 컨슈머들이 추가 파티션 할당 받음
동일한 메세지 키를 사용하고 하나의 컨슈머 그룹이 동일한 파티션 수를 가진
2개 이상의 토픽 컨슘 시 유리
컨슈머에 균등하게 파티션이 분배되지 않음

Round robin

컨숨이 필요한 모든 파티션과 컨슈머 나열 후 하나씩 파티션과 컨슈머 할당
레인지 방식에 비해 더 균등

Sticky

컨슈머 그룹 리밸런싱으로 인해 파티션 재할당 될 경우 위 방법들은 동일 파티션에
동일 컨슈머 매핑 기대할수 없음
균형 잡힌 파티션 할당+기존 할당 파티션 정보 보장
균등 분배가 우선

최초 배치 전략은 라운드 로빈과 흡사
리밸런싱 시 차이가 있음
기존 리밸런싱 전의 컨슈머에 할당됐던 파티션들은 유지

  • 컨슈머들 간 최대 할당 파티션 수 차이 1
  • 유효하지 않은모든파티션할당은 제거
  • 할당되지 않은파티션들을균형 맞춰할당

협력적 Sticky

컨슈머 그룹 내 리밸런싱 동작 고도화
일반적인 리밸런싱은 다운 타임에서 모든 파티션 컨슈머 연결 제거 후
컨슈머들 모두 멈춘 상태에서 진행
협력적 스티키는 파티션 재배치가 필요 없는 컨슈머는 계속 동작, 두 번의 리밸런싱

profile
소신있는 오픈마인드

0개의 댓글