카프카는 분산 애플리케이션으로 서버의 물리적 장애가 발생하는 경우에도 높은 가용성
을 보장합니다. 이를 위해 카프카는 리플리케이션(Replication)
기능을 제공합니다. 여기서 리플리케이션은 토픽을 하는 것이 아닌 파티션을 리플리케이션 하는 것입니다.
카프카에서는 리플리케이션 팩터(Replication Factor)라는 것이 있습니다. 이 값은 각 토픽이 몇 개의 복제본을 복제해야 하는지를 나타내는 값입니다. 기본적으로 1로 설정되어 있으나 이를 변경하기 위해서는 카프카 설정 파일에서 수정할 수 있습니다. 설정 파일(usr/local/kafka/config/server.properties)
에 default.replication.factor
항목을 변경해주면 됩니다. 또한 각 토픽 별로 다른 리플리케이션 팩터 값을 설정할 수 있습니다.
이제 이 리플리케이션을 통해서 어떻게 높은 가용성을 가질 수 있는지 알아보겠습니다.
예를 들어보겠습니다. 1개의 토픽 peter
가 있으며, 3개의 파티션이 있다고 가정해봅시다.
replication 설정이 1일 경우 파티션 0번이 리더이며 프로듀서가 전송하는 메시지를 처리하게 됩니다. 만약 파티션 2번이 다운되었습니다. 이 경우 아무런 악영향이 없습니다. 하지만 여기서 파티션 0번이 물리적 장애가 발생되어 다운되게 되면 프로듀서는 데이터를 처리할 수 없으며, 카프카는 데이터를 전달받지 못하게 됩니다. 그래서 가용성이 떨어지게 되죠. 그래서 카프카는 replication이라는 기능을 추가하여 고가용성을 유지하도록 합니다.
위와 반대로 이번에는 replication 설정을 3으로 해보겠습니다. 이럴 경우 파티션 0번이 리더, 파티션 1,2번은 팔로워가 됩니다 (예를 든 것으로, 리더가 다른 파티션이 될 수 있습니다.).
여기서 리더와 팔로워는 각자 역할이 나뉘어 있는데 가장 중요한 핵심은 모든 읽기와 쓰기가 리더를 통해서만 일어난다는 점입니다. 즉 팔로워는 리더의 데이터를 그대로 리플리케이션만 하고 읽기와 쓰기에는 관여하지 않습니다. 리더와 팔로워는 저장된 데이터의 순서도 일치하고 동일한 오프셋과 메시지들을 갖게 됩니다.
이제 replication이 3이 되어서 왜 고가용성을 지원하는지 알아보겠습니다.
만약 파티션 0번(리더)이 다운되면 카프카는 끊김 없이 보내기 위해서 팔로워 중 새로운 리더를 선정하게 되고, 새로 선정된 파티션이 리더로서 카프카에서 데이터를 전달받게 됩니다. 파티션 1번이 리더가 되었다면 파티션 2번은 팔로워가 되는 것이죠. 관리자는 이제 파티션 0번이 문제가 생긴 이유를 확인하고 다시 돌아갈 수 있도록만 하면 됩니다. 카프카 입장에서는 끊김 없이 메시지를 전달만 하면 문제가 없기 때문에 위와 같은 문제가 생긴다 해도 문제가 발생되지 않아 고가용성을 지원할 수 있게 되는 것입니다.
하지만 단점이 존재합니다.
- 만약 리더의 파티션이 100GB의 디스크를 사용한다면 팔로워 파티션들도 같은 디스크를 사용해야 하기 때문에 더 많은 저장소가 필요하게 됩니다.
- 브로커의 리소스 사용량 증가입니다. 완벽한 리플리케이션을 보장하기 위해 우리가 알아차리지 못하는 사이에 비활성화된 토픽이 리플리케이션을 잘하고 있는지 비활성화된 토픽의 상태를 체크하는 등의 작업이 이뤄지기 때문에 리소스 사용량을 증가시키게 됩니다.
따라서 토픽에 저장되는 데이터의 중요도에 따라 리플리케이션 팩터를 설정해 운영하는 것이 효율적입니다.
리더는 모든 데이터의 읽기 쓰기에 대한 요청에 응답하면서 데이터를 저장해나가고, 팔로워는 리더를 주기적으로 보면서 자신에게 없는 데이터를 리더로부터 주기적으로 가져오는 방법으로 리플리케이션을 유지합니다.
만약 새로운 리더가 승격되어야 하는데, 데이터가 일치하지 않으므로 큰 문제가 발생되는 경우를 어떻게 방지하고자 하는지 알아보겠습니다.
카프카는 ISR(In Sync Replication)이라는 개념을 도입했습니다.
이 ISR이라는 것은 현재 리플리케이션되고 있는 리플리케이션 그룹입니다. 그중 중요한 규칙이 위와 같은 경우를 방지를 돕습니다. 이 규칙은 ISR에 속해 있는 구성원만이 리더의 자격을 가질 수 있다는 점입니다. 자세히 말씀드리면 예를 들어 파티션 0, 1, 2가 있다고 가정하겠습니다. 여기서 0은 리더, 1~2는 팔로워입니다. 시스템이 운영 중에 파티션 2번이 잠시 다운되었습니다. 이 파티션 2번이 잠시 다운되었다가 복구하는 과정에서 데이터 C를 파티션 0이 받아 파티션 1번도 repliaction 했으면, 파티션 2번만 데이터 C가 없어서 만약 차후에 새로운 리더가 파티션 2번이 되는 경우 데이터 C가 손실된 채 시스템이 가용되는 것입니다. 이는 문제가 발생될 수 있기 때문에 ISR에서 퇴출되어 파티션 0,1 만 ISR에 속해 새로운 리더를 선출할 때 선택받을 수 있도록해 위와 같은 문제를 방지하도록 하는 것입니다.
여기서 만약 최악의 장애 상황으로 모든 파티션이 다운된다면 어떻게 해야 할까요?
예를 들어 파티션 0, 1, 2가 있는데 순차적으로 다운되게 되면 새로 들어오는 메시지의 전송이 실패됩니다. 이 경우 우리가 선택할 수 있는 방법은 두 가지가 있습니다.
(1). 마지막 리더가 살아나기까지 대기
(2). ISR에서 추방되었지만 먼저 살아나면 자동으로 리더
1번의 경우 2 -> 1 -> 0번 순으로 다운되었다고 가정해보면 0번 파티션이 다시 복구될 때까지 카프카 시스템은 대기하며 있는 것입니다. 여기서 최악은 2번 1번은 복구되었는데 말이죠. 하지만 이 경우는 그래도 마지막으로 받은 메시지까지 보존할 수 있다는 점이 있어 모든 메시지를 순차적으로 빠짐없이 다시 재가동할 수 있다는 장점이 존재합니다.
2번의 경우 2 -> 1 -> 0번 순으로 다운되었다고 가정해보면 1번과 2번 중 먼저 복구되는 파티션을 리더로 선정하여 다시 재가동하는 방법입니다. 이 경우 빠르게 시스템을 복구할 수 있다는 장점이 존재하겠지만, 1번과 2번은 중간에 ISR에 퇴출되어 퇴출 기간 동안 리더가 새로운 메시지를 받고 있었다면 그 메시지는 없는 채 서비스가 재가동되어 모든 메시지를 빠짐없이 전달은 못한다는 단점이 존재합니다.
위 두 가지 방법을 설정하는 것은 설정 파일(usr/local/kafka/config/server.properties)
에 unclean.leader.election.enable option
입니다. ( false = 1번 , true = 2번 )
위 두 가지 방법 모두 뭐가 좋다 틀리다는 정답은 존재하지 않습니다. 가용성과 일관성 중 어느 쪽에 초점을 두느냐의 차이입니다.
이번 포스팅을 통해서 replication factor이 무엇이며, 이것이 토픽 별 파티션을 가용성 있게 유지하며 서버가 다운되었을 때 어떻게 리더와 팔로워가 선출되며 문제가 발생되었을 때 어떻게 처리되는지까지 알아보았습니다. 다음 포스팅을 통해서 카프카에 더욱더 자세한 면을 알아보겠습니다.
해당 글의 모든 레퍼런스는 "카프카, 데이터 플랫폼의 최강자" (고승범, 공용준 지음) 을 알립니다.
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."