아파치 카프카 실습 (Apache Kafka) / 토픽과 파티션 - 상세 개념 (적정 파티션 개수, 메시지 키 사용 여부, 토픽 정리 정책, ISR)
# 토픽과 파티션
토픽에 대해 잘 이해하고 설정을 잘하는 것이 카프카를 통한 데이터 활용도를 높이는 것이다.
여러가지 운영상 고려사항을 알아보자.
1. 적정 파티션 개수
토픽의 파티션 개수는 카프카의 성능과 관련이 있다. 그렇기에 운영함에 있어 적절한 파티션 개수를 설정하고 운영하는 것이 매우 중요하다.
토픽 최초 생성 시 파티션의 개수를 정하는 데에 고려해야 할 점은 3가지 있다.
# 토픽 생성 시 파티션 개수 고려사항
- 데이터 처리량
- 메시지 키 사용 여부
- 브로커, 컨슈머 영향도
파티션의 개수가 많아지면 많아 질수록 1:1 매핑되는 컨슈머 개수가 늘어나기 때문에 파티션은 카프카의 병렬처리 핵심이다.
파티션 개수를 정할 때는 해당 토픽에 필요한 데이터 처리량을 측정하여 정하는 것이 중요하다.
# 데이터 처리 속도를 올리는 방법
- 컨슈머의 처리량을 늘리는 것
- 컨슈머를 추가해서 병렬처리량을 늘리는 것
컨슈머의 처리량을 늘리기 위해 컨슈머가 실행되는 서버의 사양을 올리는 스케일 업을 하거나 GC 튜닝등을 할 수 있지만 다른 시스템들과 연동되기 대문에 일정 수준 이상 처리량을 올리는 것은 매우 어렵다.
반면, 파티션 개수를 늘리고 파티션 개수만큼 컨슈머를 추가하는 방법은 데이터 처리량을 늘리는 가장 확실한 방법이다.
그러므로 프로듀서가 보내는 데이터양과 컨슈머의 데이터 처리량을 계산해서 파티션 개수를 정하면 된다.
만약 프로듀서가 보내는 데이터가 초당 1,000레코드이고 컨슈머가 처리할 수 있는 데이터가 초당 100레코드라면 최소한으로 필요한 파티션 개수는 10개 이다.
프로듀서 전송 데이터량 < 컨슈머 데이터 처리량 < 파티션 개수
파티션 개수만큼 컨슈머 스레드를 운영하면 해당 토픽의 병렬처리를 극대화할 수 있다.
만약 컨슈머 데이터 처리량이 프로듀서가 보내는 데이터보다 적다면 컨슈머 랙이 발생하고 데이터 처리 지연이 발생한다.
그렇기 때문에 컨슈머 전체 데이터 처리량이 프로듀서 데이터 처리량보다 많아야 한다.
# 메시지 키 사용 여부
메시지 키 사용 여부는 데이터처리 순서와 밀접한 연관이 있다.
프로듀서가 기본 파티셔너를 사용하는 경우를 가정하여 메시지키를 사용하면 프로듀서가 토픽으로 데이터를 보낼 때 메시지 키를 해시 변환하여 메시지 키를 파티션에 매칭시킨다.
만약 파티션 개수가 달라지면 이미 매칭된 파티션과 메시지 키의 매칭이 깨지고 전혀 다른 파티션에 데이터가 할당된다.
그러므로 파티션 개수가 달라지는 순간에는 메시지 키를 사용하는 컨슈머는 특정 메시지 키의 순서를 보장받지 못한다.
파티션을 변환하기 이전과 이후 메시지 키의 파티션 위치가 달리지기 때문이다.
# 브로커와 컨슈머의 영향도
카프카에서 파티션은 각 브로커의 파일 시스템을 사용하기 때문에 파티션이 늘어나는 만큼 브로커에서 접근하는 파일 개수가 많아진다.
운영체제에서는 프로세스당 열 수 있는 파일 최대 개수를 제한하고 잇다.
그러므로 카프카 브로커가 접근하는 파일 개수를 안정적으로 유지하기 위해서는 각 브로커당 파티션 개수를 모니터링해야 한다.
데이터양이 많아져서 파티션 개수를 늘려야 하는 상황이라면 브로커당 파티션 개수를 확인하고 진행한다.
만약 브로커가 관리하는 파티션 개수가 너무 많으면 파티션 개수를 분산하기 위해 카프카 브로커 개수를 늘리는 방안도 고려해야 한다.
2. 토픽 정리 정책(Cleanup.policy)
토픽의 데이터는 시간, 용량에 따라 삭제 규칙을 적용할 수 있다.
클러스터가 살아 있으면 토픽의 데이터를 삭제하지 않도록 설정할 수도 있다.
그러나 삭제하지 않으면 저장소 사용량이 지속적으로 늘어난다.
데이터를 사용하지 않을 경우 cleanup.policy 옵션을 사용하여 삭제할 수 있는 2가지 정책을 제공한다.
- 토픽 삭제 정책(delete policy)
- 토픽 압축 정책(compact policy)
# 토픽 삭제 정책
토픽 운영 시 대게 토픽의 cleanup.policy를 delete로 설정한다.
이 옵션은 명시적으로 토픽의 데이터를 삭제하는 것을 뜻한다.
데이터 삭제 시 세그먼트 단위로 삭제를 진행한다. 세그먼트는 토픽의 데이터를 저장하는 명시적인 파일 시스템 단위이다.
세그먼트는 파티션마다 별개로 생성되며 세그먼트 파일 이름은 오프셋 중 가장 작은 값이 된다.
세그먼트는 여러 조각으로 나뉘는데 segment.bytes 옵션으로 1개의 세그먼트 크기를 설정할 수 있다.
segment.bytes 크기보다 커질 경우에는 기존에 적재하던 세그먼트 파일을 닫고 새로운 세그먼트를 열어 데이터를 저장한다.
데이터를 저장하기 위해 사용 중인 세그먼트를 액티브 세그먼트라고 한다.
# 토픽 압축 정책
토픽 압축 정책은 일반적으로 생각하는 zip이나 tar 압축과는 다른 개념이다.
메시지 키별로 해당 메시지 키의 레코드 중 오래된 데이터를 삭제하는 정책을 뜻한다.
메시지 키 기준 오래된 데이터를 삭제하기 때문에 삭제 정책과 다르게 1개 파티션에서 오프셋의 증가가 일정하지 않을 수 있다.
토픽 압축 정책은 카프카 스트림즈의 KTable과 같이 메시지 키를 기반으로 데이터를 처리할 경우 유용하다.
데이터의 흐름이 아닌 가장 마지막 업데이트된 메시지 키의 데이터가 중요할 경우 가장 최신 데이터를 제외한 나머지 데이터들을 삭제할 수 있기 때문이다.
압축 정책은 액티브 세그먼트를 제외한 나머지 세그먼트들에 한해서만 데이터를 처리한다.
데이터의 압축 시작 시점은 min.cleanable.dirty.ratio 옵션값을 따른다.
min.cleanable.dirty.ratio 옵션값은 액티브 세그먼트를 제외한 세그먼트에 남아 있는 데이터의 tail 영역의 레코드 개수와 head 영역의 레코드 개수의 비율을 뜻한다.
* tail 영역
tail 영역은 압축이 완료된 레코드들을 뜻한다.
tail 영역 레코드들은 clean 로그라고도 부르고 중복된 메시지 키가 없다.
* head 영역
head 영역의 레코드들은 dirty 로그라고 부른다.
압축 되기 전 레코드들이 있으므로 중복 메시지 키를 가진 레코드들이 있다.
* dirty 비율
더티 영역 메시지 개수를 압축 대상 세그먼트에 남아있는 데이터의 레코드 수로 나눈 비율
만약 clean 영역에 3개 dirty 영역에 3개가 있다면 dirty 비율은 0.5 이다.
3. ISR(In-Sync-Replicas)
ISR은 리더 파티션과 팔로워 파티션이 모두 싱크가 된 상태를 뜻한다.
복제 개수가 2인 토픽을 가정하면, 이 토픽에는 리더 파티션 1개와 팔로워 파티션이 1개가 존재할 것이다.
리더 파티션에 0부터 3의 오프셋이 있다고 가정할 때, 팔로워 파티션에 동기화가 완료되려면 0부터 3까지 오프셋이 존재해야 한다.
동기화 상태에서는 리더 또는 팔로워 파티션이 위치하는 브로커에 장애가 발생하여도 데이터를 안전하게 사용할 수 있다.
만약 팔로워 파티션이 replica.lag.time.max.ms 값보다 더 긴 시간 동안 데이터를 가져가지 않는다면 해당 팔로워 파티션에 문제가 생긴 것으로 판단하고 ISR 그룹에서 제외한다.
ISR로 묶인 리더 파티션과 팔로워 파티션은 파티션에 존재하는 데이터가 모두 동일하기 때문에 팔로워 파티션은 리더 파티션으로 새로 선출된 자격을 가진다.