PaaS/MQ

Kafka 심화) 카프카 내부 알고리즘

armyost 2026. 1. 14. 23:00
728x90

클러스터 멤버쉽

카프카는 현재 클러스터의 멤버인 브로커들의 목록을 유지하기 위해 아파치 주키퍼를 사용한다. 각 브로커는 브로커 설정 파일에 정의되었거나 아니면 자동으로 생성된 고유한 식별자를 가진다. 

 

컨트롤러

컨트롤러는 일반적인 카프카 브로커의 기능에 더해서 파티션 리더를 선출하는 역할을 추가적으로 맡는다. 브로커가 컨트롤러가 되면, 클러스터 메타데이터 고나리와 리더 선출을 시작하기 전에 먼저 주키퍼로부터 최신 레플리카 상태 맵을 읽어온다. 브로커가 클러스터를 나갔다는 사실을 컨트롤러가 알아차리면, 컨트롤러는 해당 브로커가 리더를 맡고 있었던 모든 파티션에 대해 새로운 브로커를 할당해주게 된다. 컨트롤러는 새로운 리더가 필요한 모든 파티션을 순회해 가면서 새로운 리더가 될 브로커를 결정한다.(단순히 해당 파티션의 레플리카 목록에서 바로 다음 레플리카가 새 브로커가 된다.)

 

KRaft: 카프카의 새로운 래프트 기반 컨트롤러

2019년부터 아파치 카프카 커뮤니티는 야심찬 프로젝트를 시작했다. 바로 주키퍼 기반 컨트롤러로부터 탈피해서 래프트 기반 컨트롤러 쿼럼으로 옮겨가는 것이다. 'KRaft'라고 불리는 새로운 컨트롤러의 프리뷰 버전은 2.8에  포함되었으며 3.3부터는 실험적이라는 수식어를 떼고 정식으로 프로더거션 환경에서 사용 가능한 기능이 되었다. 래프트 알고리즘을 사용함으로써, 컨트롤러 노드들은 외부 시스템에 의존하지 않고 자체적으로 리더를 선출할 수 있게 될 것이다. 메타데이터 로그의 리더 역할을 맡고 있는 컨트롤러는 액티브 컨트롤러라고 부른다. 

 

컨트롤러는 다른 브로커에 변경사항을 밀어내지 않는다. 대신, 다른 브로커들이 새로 도입된 MetadataFetch API를 사용해서 액티브 컨트롤러로부터 변경 사항을 당겨온다.

 

복제

각 토픽은 1개 이상의 파티션으로 분할되며, 각 파티션은 다시 다수의 레플리카를 가질 수 있다. 각각의 레플리카는 브로커에 저장되는데, 대게 하나의 브로커는 수백 개에서 심지어 수천개의 레플리카를 저장한다. 

- 리더 레플리카 : 각 파티션에는 리더 역할을 하는 레플리카가 하나씩 있다. 

- 팔로워 레플리카 : 파티션에 속한 모든 레플리카 중에서 리더 레플리카를 제외한 나머지를 팔로워 레플리카라고 한다. 이들이 주로 하는 일은 리더 레플리카로 들어온 최근 메시지들을 복제함으로써 최신 상태를 유지하는 것이다. 만약 해당 파티션의 리더 레플리카에 크래쉬가 날 경우, 팔로워 레플리카 중 하나가 파티션의 새 리터 파티션으로 승격된다. 파티션이 처음 생성되던 시점에서는 리더 레플리카가 모든 브로커에 걸쳐 균등하게 분포되기 때문에 '선호'라는 표현이 붙었다. 결과적으로, 클러스터내의 모든 파티션에 대해 선호 리더가 실제 리더가 될 경우 부하가 브로커 사이에 균등하게 분배될 것이라고 예상할 수 있다. 카프카 에는 auto.leader.rebalance.enable=true 설정이 기본적으로 잡혀있다. 이 설정은 선호 리더가 현재 리더가 아니지만, 현재 리더와 동기화가 되기 있을 경우 리더 선출을 실행시킴으로써 선호 리더를 현재 리더로 만들어 준다. 

 

파티션 할당

- 레플리카들을 가능한 한 브로커 간에 고르게 분산시킨다.

- 각 파티션에 대해 각각의 레플리카는 서로 다른 브로커에 배치되도록 한다.

- 만약 브로커에 랙 정보가 설정되어 있다면가능한 한 각 파티션의 레플리카들을 서로 다른 랙에 할당한다. 

새 파티션을 저장할 디렉토리를 결정해야 한다. 이 작업은 파티션별로 독립적으로 수행되며, 규칙은 매우 간단하다. 즉, 각 디렉토리에 저장되어 있는 파티션의 수를 센 뒤, 가장 적은 파티션이 저장된 디렉토리에 새 파티션을 저장하는 것이다. 

 

인덱스

브로커는 오프셋 100에 해당하는 메시지가 저장된 위치르 ㄹ빠르게 찾아서 해당 오프셋에서 부터 메시지를 읽기 시작할 수 있어야 한다. 브로커가 주어진 오프셋의 메시지를 빠르게 찾을 수 있도록 하기 위해 카프카는 각 파티션에 대해 오프셋을 유지한다. 이 인덱스는 오프셋과 세그먼트 파일 및 그 안에서의 위치를 매핑한다.  

 

압착

카프카는 두 가지 보존 정책을 허용한다. 보존 정책에서는 지정된 보존 기한 보다 더 오래된 이벤트들을 삭제한다. 압착 보존 정책에서는 토픽에서 각 키의 가장 최근값만 저장하도록 한다. 

 

압착의 작동원리

파티션을 압착하기 위해서 클리너 스레드는 파티션의 더티 영역을 읽어서 인-메모리 맵을 생성한다. 클린 세그먼트들을 오래된 것부터 읽어들이면서 오프셋 맵의 내용과 대조한다. 키 값이 현재 오프셋 맵에 저장되어 있는지 확인한다. 

 

 

토픽은 언제 압착되는가?

삭제 정책이 현재의 액티브 세그먼트를 절대로 삭제하지 않는 것과 마찬가지로, 압착 정책 역시 현재의 액티브 세그먼트를 절대로 압착하지 않는다. 액티브 세그먼트가 아닌 세그먼트에 저장되어 있는 메시지 만이 압착의 대상이 된다.