- 토픽은 메세지를 받을 수 있도록 논리적으로 묶은 개념
- 파티션은 토픽을 구성하는 데이터 저장소로서 수평 확장이 가능한 단위
카프카 클러스터는 토픽(topic)
이라 불리는 곳에 데이터를 저장합니다. 토픽은 메일 주소(토픽)라고 생각하면 쉽습니다.
카프카에서는 데이터를 구분하기 위한 단위로 토픽
이라는 용어를 사용합니다.
카프카에서 파티션이란 토픽을 분할한 것입니다.
하나의 토픽을 파티셔닝 하는 이유에 대해 알아보겠습니다.
위의 그림은 하나의 프로듀서가 카프카의 A 토픽으로 4개의 메세지를 보내는 그림인데요. 하나의 메세지를 보낼 때 1초가 걸린다면 4개의 메세지를 보낼 때는 4초가 걸리게 됩니다.
즉, 여러 개의 쓰레드로 동작하고 싶은데, 하나의 쓰레드로 4번 움직이는 느낌입니다.
만약에 프로듀서만 여러개이고, 파티션은 하나라면 성능이 올라갈 것 같지만, 메세징 큐 시스템의 경우 메세지의 순서가 보장되어야 하기 때문에, 이전 메세지 처리가 완료된 후 다음 메세지를 처리하게 됩니다.
결국 카프카에서 효율적인 메세지 전송과 속도를 높이려면 토픽의 파티션 수를 늘려줘야 합니다.
위에서 토픽의 파티션 수를 늘리면 속도가 빨라진다는 것을 보았는데요. 그러면 파티션 수를 무조건 많이 늘려주는 것이 좋을지에 대해 생각해보면 정답은 아니다 입니다.
- 파일 핸들러의 낭비
- 각 파티션은 브로커의 디렉토리와 매핑되고, 저장되는 데이터마다 2개의 파일이 있습니다. 카프카에서는 모든 디렉토리의 파일들에 대해 파일 핸들을 열게 됩니다. 결국 파티션의 수가 많을수록 파일 핸들 수 역시 많아지게 되어 리소스를 낭비하게 됩니다.
- 장애 복구 시간 증가
- 카프카는 높은 가용성을 위해 리플리케이션을 지원합니다. 브로커에는 토픽이 이고 토픽은 여러 개의 파티션으로 나뉘어 있으므로, 브로커에는 여러 개의 파티션이 존재 하니 ......
토픽의 파티션 수를 정할 때 원하는 목표 처리량을 기준을 잡아야 합니다. 프로듀서 입장에서 4개의 프로듀서를 통해 각각 초당 10개의 메세지를 카프카의 토픽으로 보낸다고 하면, 카프카의 토픽에서 초당 40개의 메세지를 받아줘야 합니다.
카프카에는 컨슈머도 있기 때문에 컨슈머의 수와 파티션 수를 동일하게 해서 예상 목표치의 성능이 나오는지 확인해보면 됩니다.
참고로 카프카에서 파티션 수의 증가는 필요한 경우 아무때나 변경이 가능하지만, 반대로 파티션의 수를 줄이는 방법은 제공하지 않습니다.
즉, 너무 과도하게 파티션 수를 늘려놓고 난 후에 파티션 수를 줄이고 싶은 상황이 생기면, 토픽을 삭제하는 방법 말고는 다른 해결책이 없습니다.
적은 파티션으로 운영해보고, 프로듀서 또는 컨슈머에서 병목현상이 발생하게 될 때 조금씩 파티션 수와 프로듀서 또는 컨슈머 수를 늘려주는 방법으로 파티션 수를 정할 수 있습니다.
카프카에서는 각 파티션마다 메세지가 저장되는 위치를 오프셋(offset)
이라고 부르고, 오프셋은 파티션 내에서 유일하고 순사적으로 증가하는 숫자(64비트 정수) 형태로 되어 있습니다.
카프카는 분산 애플리케이션으로 서버의 물리적 장애가 발생한 경우에도 높은 가용성을 보장합니다. 이를 위해 카프카는 리플리케이션(Replication)
기능을 제공합니다. 카프카의 리플리케이션은 토픽 자체를 리플리케이션 하는 것이 아니라 토픽을 이루는 각각의 파티션을 리플리케이션하는 것입니다.
카프카에서는 리플리케이션 팩터(Replication Factor)
라는 것이 있습니다. 즉, 브로커에게 리플리케이션 팩터 수 만큼 토픽 파티션들을 복제하는 것입니다.
리더와 팔로워는 각자의 역할이 나뉘어 있는데 가장 중요한 핵심은 모든 읽기와 쓰기가 리더를 통해서만 읽어납니다. 즉, 팔로워는 리더의 데이터를 그대로 리플리케이션만 하고 읽기와 쓰기에는 관여하지 않습니다.
리플리케이션 기능이 정말 중요하고 필요한 기능인 것은 맞는데 단점도 존재합니다. 만약 토픽의 사이즈가 100GB라면 브로커마다 100GB를 사용하기 때문에 복제수 x 용량
이 되게 됩니다.
리더는 모든 데이터의 읽기 쓰기에 대한 요청에 응답하면서 데이터를 저장해나가고, 팔로워는 리더를 주기적으로 보면서 자신에게 없는 데이터를 리더로부터 주기적으로 가져오는 방법으로 리플리케이션을 유지합니다.
그런데 만약에 리더와 팔로워 모두 주어진 역할에 맞게 잘 동작하고 있다면 전혀 문제가 되지 않지만 팔로워에 문제가 있어 리더로부터 데이터를 가져오지 못하면서 정합성이 맞지 않게 된다면 어떻게 될까요?
그러면 리더에 문제가 생겨서 팔로워가 리더로 승격되어도 데이터 정합성이 맞지 않기 때문에 문제가 발생하게 됩니다. 카프카에서는 이러한 현상을 막기 위해 ISR(In Sync Replica)
라는 개념을 도입했습니다.
ISR
이라는 것은 현재 리플리케이션되고 있는 리플리케이션 그룹입니다. ISR에는 중요한 규칙이 하나 있는데 그 규칙은 ISR에 속해 있는 구성원만이 리더의 자격을 가질 수 있습니다.
ISR에는 중요한 규칙이 하나 있는데 그 규칙은 ISR에 속해 있는 구성원만이 리더의 자격을 가질 수 있습니다.
카프카에서는 리더가 자신의 역할을 하지 못하게 되는 경우 팔로워가 그 역할을 대신해야 하기 때문에 리더와의 데이터 동기화 작업을 매우 중요하게 처리하고 있으며 이것을 유지하는 것이 바로 ISR입니다.
ISR의 하나의 예시를 보겠습니다.
- 프로듀서는 A 메세지를 토픽의 리더에게 보냅니다.
- 프로듀서가 보내는 A 메세지는 토픽의 리더만이 읽고 쓰기를 할 수 있기 때문에 프로듀서의 요청을 받고 저장합니다. 팔로워들은 매우 짧은 주기로 리더에 새로운 메세지가 저장된 것이 없는지 확인하는데, 팔로워 1은 잘 동작하지만, 팔로워 2는 잘 동작하지 않는 상황입니다. 리더는 팔로워들이 주기적으로 데이터가 있는지 확인하고, 만약 설정된 일정 주기만큼 확인 요청이 오지 않는다면 리더는 해당 팔로워의 이상을 감지하고 해당 팔로워는 더 이상 리더의 역할을 대신할 수 없다고 판단해 ISR 그룹에서 해당 팔로워를 추방시키게 됩니다.
- 리더가 팔로워 2를 ISR 그룹에서 추방시키자 ISR 그룹 구성원은 3에서 2로 축소 되었습니다. 팔로워 1은 리더에게 새로운 메세지가 있음을 확인하고 컨슈머들이 메세지를 가져가는 방법처럼 리더의 메세지를 가져와 저장합니다.
- 카프카 클러스터는 3대의 브로커로 구성되어 있음
- 토픽은 리플리케이션 팩터 3 옵션으로 생성했음
- 프로듀서가 데이터를 보내는 중 브로커가 1대씩 다운됨
- 최종적으로 카프카 클러스터내 모든 브로커가 다운된 상황이 발생함
위와 같은 최악의 시나리오가 발생했다고 가정하겠습니다.
- 프로듀서가 A 메세지를 전송했고, 리더와 팔로워들은 모두 A 메세지를 저장했습니다.
- 프로듀서가 B 메세지를 전송하기 직전에 급작스럽게 팔로워 2가 있는 브로커가 다운되었고, 리더는 팔로워 2를 ISR에서 제외했습니다. 프로듀서는 B 메세지를 전송하고, 리더와 팔로워 1은 B 메세지를 저장합니다.
- 프로듀서가 C 메세지를 전송하기 직전에 급작스럽게 팔로워 1이 있는 브로커가 다운되었고, 리더는 팔로워 1를 ISR에서 제외합니다. 프로듀서는 C 메세지를 전송하고 리더는 C 메세지를 저장합니다.
- 프로듀서가 D 메세지를 전송하기 직전에 급작스럽게 리더가 있는 브로커 역시 다운되면서 클러스ㅓ 내 모든 브로커가 다운되었고, 프로듀서는 더 이상 리더가 존재하지 않기 떄문에 메세지를 보낼 수 없습니다.