4.1 토픽과 파티션

문법식·2023년 2월 8일
0

토픽은 카프카의 시작과 끝이다. 그만큼 토픽은 카프카에서 중요한 역할을 한다. 그러므로 토픽을 사용함에 있어 발생하는 여러 가지 운영상 고려사항을 알아본다.

적정 파티션 개수

토픽의 파티션 개수는 카프카의 성능과 관련이 있다. 그렇기 때문에 토픽을 운영함에 있어 적절한 파티션 개수를 설정하고 운영하는 것이 매우 중요하다. 토픽 최초 생성 시 파티션의 개수를 정하는 데에 고려해야 할 점은 3가지다.

  • 데이터 처리량
  • 메시지 키 사용 여부
  • 브로커, 컨슈머 영향도

파티션은 카프카의 병렬처리의 핵심이다. 파티션이 많아지면 1:1 매핑되는 컨슈머 개수가 늘어나기 때문이다. 그래서 파티션의 개수를 정할 때는 데이터 처리량을 측정하여 정하는 것이 중요하다.

데이터 처리량

데이터 처리 속도를 올리는 방법은 2가지다.

컨슈머의 처리량을 늘리는 것

컨슈머의 처리량을 늘리기 위해 컨슈머가 실행되는 서버의 사양을 Scale Up하거나 GC 튜닝을 할 수 있다. 그러나 컨슈머 특성상 다른 시스템들(S3, 하둡, 오라클 등)과 연동되기 때문에 일정 수준 이상 처리량을 올리는 것은 매우 어렵다.

컨슈머를 추가해서 병렬처리량을 늘리는 것

파티션 개수를 늘리고 파티션 개수만큼 컨슈머를 추가하는 방법은 데이터 처리량을 늘리는 가장 확실한 방법이다. 그러므로 프로듀서가 보내는 데이터양과 컨슈머의 데이터 처리량을 게산해서 파티션 개수를 정하면 된다.

프로듀서 전송 데이터량 < 컨슈머 데이터 처리량 * 파티션 개수

전체 컨슈머 데이터 처리량이 프로듀서 전송 데이터량보다 적다면 컨슈머 랙이 생기고, 데이터 처리 지연이 발생한다. 그렇기 때문에 컨슈머 전체 데이터 처리량이 프로듀서 전송 데이터량보다 많아야 한다.

컨슈머의 데이터 처리량을 구하는 방법은 상용에서 운영 중인 카프카에서 더미 데이터로 테스트를 해보는 것이다. 컨슈머는 카프카 클러스터와 다른 시스템(S3, 하둡, 오라클 등)과 연동되는 특성이 있다. 그래서 로컬 또는 테스트 환경에서 진행한 데이터 처리량과 상용환경에서 진행한 데이터 처리량은 차이가 날 확률이 높다. 그러므로 상용환경에서의 테스트를 권장한다.

파티션 개수를 무조건 늘리는 것만이 능사가 아니다. 파티션 개수를 늘리게 됨에 따라 컨슈머, 브로커의 부담이 있기 때문이다. 그렇기 때문에 데이터 처리 지연 발생에 따른 서비스 영향도를 같이 고려해서 파티션 개수를 정하는 것이 중요하다.

메시지 키 사용 여부

메시지 키를 사용함과 동시에 데이터 처리 순서를 지켜야 하는 경우에 대해 고려해야 한다. 메시지 키를 사용하면 프로듀서가 토픽으로 데이터를 보낼 때 메시지 키를 해시 변환하여 메시지 키를 파티션에 매칭시킨다. 만약 파티션 개수가 달라지면 이미 매칭된 파티션과 메시지 키의 매칭이 깨지고 다른 파티션에 데이터가 할당된다. 그러므로 파티션 개수가 달라지는 순간 메시지 키를 사용하는 컨슈머는 특정 메시지 키의 순서를 더는 보장받지 못한다.
메시지 키를 사용하고 컨슈머에서 메시지 처리 순서가 보장되어야 한다면 최대한 파티션의 변화가 발생하지 않는 방향으로 운영해야 한다. 만약에 파티션 개수가 변해야 하는 경우 기존에 사용하던 메시지 키의 매칭을 그대로 가져가기 위해 커스텀 파티셔너를 개발하고 적용해야 한다. 이러한 어려움 때문에 메시지 키별로 처리 순서를 보장하기 위해서는 파티션 개수를 프로듀서가 전송하는 데이터양보다 더 넉넉하게 잡고 생성하는 것이 좋다. 그러나, 메시지 키를 사용하지만 데이터 처리 순서를 지키지 않아도 된다면 파티션 개수를 처음부터 넉넉하게 잡지 않아도 된다.

브로커와 컨슈머의 영향도

카프카에서 파티션은 각 브로커의 파일 시스템을 사용하기 때문에 파티션이 늘어나는 만큼 브로커에서 접근하는 파일 개수가 많아진다. 그런데 운영체제에서는 프로세스당 열 수 있는 파일 최대 개수를 제한하고 있다. 그러므로 카프카 브로커가 접근하는 파일 개수를 안정적으로 유지하기 위해서는 각 브로커당 파티션 개수를 모니터링해야 한다. 만약 브로커가 관리하는 파티션 개수가 너무 많다면 파티션 개수를 분산하기 위해 카프카 브로커 개수를 늘리는 방안도 같이 고려해야 한다.


토픽 정리 정책

토픽의 데이터는 시간 또는 용량에 따라 삭제 규칙을 적용할 수 있다. 또는 삭제를 원치 않는다면 카프카 클러스터가 살아있는 한 토픽의 데이터를 삭제하지 않도록 설정할 수 있다. 그러나 데이터를 삭제하지 않으면 카프카 운영 비용도 함께 늘어난다.
그러므로 데이터를 더는 사용하지 않을 경우 cleanup.policy 옵션을 사용하여 데이터를 삭제할 수 있는데, 옵션은 2가지 삭제 정책을 제공한다.

  • delete로 데이터의 완전 삭제
  • compact로 동일 메시지 키의 가장 최신을 제외한 데이터들의 삭제

토픽 삭제 정책(delete policy)

토픽을 운영하면 일반적으로 대부분의 토픽의 cleanup.policydelete로 설정한다. 이 옵션은 명시적으로 토픽의 데이터를 삭제하는 것을 뜻한다. 토픽의 데이터를 삭제할 때는 세그먼트 단위로 삭제를 진행한다. 세그먼트는 파티션마다 별개로 성생되며 세그먼트의 파일 일므은 오프셋 중 가장 작은 값이 된다. 세그먼트는 어려 조각으로 나뉘는데 segment.bytes 옵션으로 1개의 세그먼트 크기를 설정할 수 있다. segment.bytes의 크기보다 커질 경우에는 기존에 적재하던 세그먼트 파일을 닫고 새로운 세그먼트를 열어서 데이터를 저장하는데, 데이터를 저장하기 위해 사용 중인 세그먼트를 액티브 세그먼트라고 한다.
삭제 정책이 실행되는 시점은 시간 또는 용량이 기준이 된다. retention.ms는 토픽의 데이터를 유지하는 기간을 밀리초로 설정할 수 있다. retention.bytes는 토픽의 최대 데이터 크기를 제어한다. 삭제된 데이터는 복구할 수 없다.

토픽 압축 정책(compact policy)

토픽 압축이란 메시지 키별로 해당 메시지 키의 레코드 중 가장 최신의 데이터를 제외한 오래된 데이터들을 삭제하는 정책을 뜻한다. 메세지 키를 기준으로 데이터를 삭제하기 때문에 delete policy와 다르게 오프셋의 증가가 일정하지 않을 수 있다.
토픽의 압축 정책은 카프카 스트림즈의 KTable과 같이 메시지 키를 기반으로 데이터를 처리할 경우 유용하다.
압축 정책은 액티브 세그먼트를 제외한 나머지 세그먼트들에 한해서만 데이터를 처리한다. 데이터 합축의 시작 시점은 min.cleanable.dirty.ratio 옵션값을 따른다. min.cleanable.dirty.ratio 옵션값은 액티브 세그먼트를 제외한 세그먼트에 남아 있는 데이터의 테일(tail) 영역의 레코드 개수와 헤드(head) 영역의 레코드 개수의 비율을 뜻한다. 테일 영역은 브로커의 압축 정책에 의해 압축이 완료된 레코드들을 뜻한다. 테일 영역의 레코드들은 클린 로그라고 부른다. 헤드 영역의 레코드들은 더티 로그라고 부른다.

더티 비율=더티 레코드 개수/(더티 레코드 개수 + 클린 레코드 개수)

min.cleanable.dirty.ratio 옵션값을 0.5로 설정한 경우에 더티 비율이 0.5가 넘어가면 압축이 수행된다. min.cleanable.dirty.ratio 옵션값을 0.9와 같이 크게 설정하면 한번 압축을 할 때 많은 데이터가 줄어들므로 압축 효과가 좋다. 그러나 0.9 비율이 될 때까지 용량을 차지하므로 용량 효율이 좋지 않다. 반면 min.cleanable.dirty.ratio 옵션값을 0.1과 같이 작게 설정하면 압축이 더 자주 일어나기 때문에 계속해서 메시지 키의 최신 데이터만 유지할 수 있다. 하지만 압축이 자주 발생하는 만큼 브로커에 부담을 줄 수 있다.


ISR(In-Sync-Replicas)

ISR은 리더 파티션과 팔로워 파티션이 모두 싱크가 된 상태를 뜻한다. 복제 개수가 2인 토픽을 가정한다. 이 토픽에는 리더 파티션 1개와 팔로워 파티션 1개가 존재한다. 리더 파티션은 0~3의 오프셋이 있다고 가정할 때, 팔로워 파티션에 동기화가 완료되려면 0~3까지 오프셋이 존재해야 한다. 리더 파티션과 팔로워 파티션이 동기화된 상태에서는 리더 또는 팔로워 파티션이 위치하는 브로커에 장애가 발생하더라도 데이터를 안전하게 사용할 수 있다. 반면, 팔로워 파티션에 0~2까지 오프셋이 존재한다면 동기화가 완벽하게 된 상태가 아니다.
리더 파티션은 replica.lag.time.max.ms만큼의 주기를 가지고 팔로워 파티션이 데이터를 복제하는지 확인한다. 만약 팔로워 파티션이 replica.lag.time.max.ms값보다 더 긴 시간 동안 데이터를 가져가지 않는다면 해당 팔로워 파티션에 문제가 생긴 것으로 판단하고 ISR 그룹에서 제외한다.
ISR로 묶인 리더 파티션과 팔로워 파티션은 파티션에 존재하는 데이터가 모두 동일하기 때문에 팔로워 파티션은 리더 파티션으로 새로 선출될 자격을 가진다.
일부 데이터 유실이 발생하더라도 서비스를 중단하지 않고 지속적으로 토픽을 사용하고 싶다면 unclean.leader.election.enable 옵션으로 ISR이 아닌 팔로워 파티션을 리더로 선출하도록 설정할 수 있다.
unclean.leader.election.enablefalse로 설정할 경우 ISR이 아닌 파티션을 리더로 선출하지 않는다. 이 경우, 리더 파티션이 존재하는 브로커가 다시 시작되기까지 기다린다. 이는 토픽을 사용하는 서비스가 중단됨을 뜻한다. 대신 동기화되지 않은 팔로워 파티션이 리더로 선출되지 않기 때문에 데이터의 유실은 발생하지 않는다.
unclean.leader.election.enabletrue로 설정할 경우에는 ISR이 아닌 팔로워 파티션을 리더로 선출할 수 있다. 일부 데이터가 유실되는 대신 토픽을 사용하는 서비스의 중단은 발생하지 않는다. 서비스의 운영 정책에 따라 옵션값을 설정하면 된다.

profile
백엔드

0개의 댓글