Apache Kafka는 대용량의 실시간 데이터를 처리할 수 있는 분산형 메시징 시스템으로, 시스템 성능을 최적화하기 위해서는 파티션(Partition)의 개수를 적절히 설정하는 것이 매우 중요합니다. 파티션은 Kafka가 병렬 처리를 가능하게 하는 핵심 요소 중 하나입니다. 그렇기 때문에 파티션의 개수에 따라 데이터 처리 성능이 크게 달라질 수 있습니다.
Kafka의 토픽(Topic)은 여러 개의 파티션으로 나누어집니다. 각 파티션은 독립적으로 처리될 수 있으며, 그 덕분에 여러 개의 컨슈머(Consumer)가 병렬로 데이터를 소비할 수 있습니다. 즉, 파티션 개수가 늘어나면, 병렬로 처리할 수 있는 범위가 넓어져 시스템의 데이터 처리량이 증가하게 됩니다.
컨슈머는 각 파티션과 1:1로 매핑되며, 이를 통해 하나의 토픽을 여러 개의 컨슈머 그룹이 동시에 소비할 수 있습니다. 이러한 방식으로 시스템의 처리량을 늘리는 것이 Kafka의 중요한 특징 중 하나입니다. 따라서, 파티션의 개수는 데이터 처리 성능에 직접적인 영향을 미칩니다.
파티션의 개수를 결정할 때는 몇 가지 요소를 고려해야 합니다:
파티션 개수를 설정할 때 가장 먼저 고려해야 할 것은 시스템이 처리해야 하는 데이터의 양입니다. 대규모 데이터를 빠르게 처리하려면 파티션을 많이 설정하여 병렬 처리를 극대화할 수 있습니다. 예를 들어 초당 수십만 건의 메시지를 처리해야 하는 경우, 충분히 많은 파티션을 설정해 컨슈머가 병렬로 데이터를 처리할 수 있도록 해야 합니다.
Kafka에서는 메시지를 파티션에 분배할 때 메시지 키를 기준으로 할당할 수 있습니다. 메시지 키가 동일한 경우, 해당 키에 해당하는 모든 메시지가 동일한 파티션에 저장됩니다. 이러한 특성을 고려할 때, 메시지 키를 사용하여 특정 파티션에 데이터가 몰리지 않도록 파티션 개수를 조정하는 것이 중요합니다.
파티션 개수가 증가하면 각 파티션을 처리하는 브로커와 컨슈머의 부담도 늘어납니다. 브로커는 더 많은 파티션을 관리해야 하고, 컨슈머는 더 많은 파티션에서 데이터를 소비해야 하기 때문입니다. 이 때문에 브로커의 성능이나 컨슈머의 처리 능력에 따라 적절한 파티션 개수를 결정해야 합니다.
Kafka에서 데이터 처리 속도를 높이기 위한 두 가지 주요 방법이 있습니다:
컨슈머의 처리량을 높이는 방법은 컨슈머 자체의 성능을 개선하는 것입니다. 컨슈머가 데이터를 처리하는 데 걸리는 시간을 줄이거나, 더 효율적인 데이터 처리 방식을 도입하는 등의 방법을 생각해볼 수 있습니다. 하지만 이 방법은 컨슈머가 연동되는 다른 시스템의 성능에도 영향을 받기 때문에, 한계가 있을 수 있습니다.
컨슈머를 추가해서 병렬 처리의 양을 늘리는 방법은 데이터 처리량을 확실히 높일 수 있는 방법입니다. 컨슈머 수가 늘어나면 각 컨슈머는 개별 파티션에서 데이터를 병렬로 처리할 수 있기 때문에, 전체 처리 성능이 크게 향상됩니다. 이를 위해서는 파티션 개수가 충분히 확보되어 있어야 하며, 각 컨슈머가 1:1로 매핑되어 병렬 처리가 원활하게 이뤄질 수 있도록 설계해야 합니다.

Kafka에서 파티션은 병렬 처리를 가능하게 하는 핵심 요소입니다. 파티션 개수만큼 컨슈머 스레드를 운영하면, 해당 토픽의 병렬 처리 성능을 최대한 끌어올릴 수 있습니다. 하지만 여기서 중요한 것은 컨슈머의 처리량이 프로듀서의 데이터 전송량을 초과해야 한다는 점입니다. 그렇지 않으면, 컨슈머가 데이터를 적시에 처리하지 못해 컨슈머 랙(Consumer Lag)이 발생하게 됩니다. 이로 인해 메시지 처리 지연이 생기고, 실시간 데이터를 처리해야 하는 시스템에서는 심각한 문제가 될 수 있습니다.
컨슈머 랙은 프로듀서가 데이터를 빠르게 보내는 것에 비해 컨슈머가 이를 제대로 처리하지 못할 때 발생합니다. 컨슈머 랙이 쌓이면 데이터 처리 지연이 발생하게 되고, 실시간 성능이 요구되는 시스템에서는 큰 병목이 됩니다. 따라서 컨슈머 전체의 데이터 처리량은 프로듀서가 전송하는 데이터 양보다 많아야 합니다. 이를 위해서는 컨슈머의 개수, 성능, 그리고 파티션의 개수를 적절히 조정하는 것이 중요합니다.
Kafka에서 메시지 키를 사용하여 데이터를 처리할 때는 처리 순서 보장이 중요한 경우가 많습니다. 이 경우, 파티션의 개수를 신중하게 설정해야 합니다. 메시지 키가 동일한 데이터는 반드시 동일한 파티션에 저장되며, 해당 파티션을 처리하는 컨슈머가 메시지의 순서를 보장하며 데이터를 처리하게 됩니다.
만약 메시지 처리 순서를 보장해야 하는 상황에서 파티션 개수가 변동되면, 데이터의 메시지 키와 파티션 매칭이 달라지기 때문에 처리 순서에 혼란이 발생할 수 있습니다. 이를 방지하기 위해, 만약 파티션 개수를 변경해야 한다면 기존 메시지 키와 파티션 간의 매칭을 유지할 수 있도록 커스텀 파티셔너(Custom Partitioner)를 개발해 적용하는 것이 필요합니다. 하지만 이 과정은 복잡할 수 있으며, 시스템에 추가적인 부담을 줄 수 있습니다.
따라서 메시지 처리 순서를 보장해야 하는 시스템에서는 처음부터 충분한 파티션을 설정하는 것이 바람직합니다. 이렇게 하면 파티션 개수의 변화를 최소화할 수 있으며, 데이터 처리 순서를 유지하는 데 유리합니다.
반면, 메시지 키를 사용하지만 처리 순서가 중요하지 않은 경우에는 처음부터 파티션 개수를 과도하게 설정할 필요는 없습니다. 이 경우에는 시스템의 데이터 처리량에 따라 파티션 개수를 유동적으로 늘리는 것이 가능합니다. 처음에는 적정한 개수의 파티션으로 시작하고, 데이터 처리량이 증가할 때 파티션을 늘려 병렬 처리 성능을 최적화하면 됩니다.
명시적으로 토픽의 데이터를 삭제
세그먼트 단위로 삭제 진행
segment.bytes -> 1개의 세그먼트의 크기 설정

시간: retention.ms 로 유지시간 설정
용량: retention.bytes 용량 넘어가면 삭제
압축: 메세지 키별로 해당 메세지 키의 레코드 중 오래된 데이터를 삭제하는 정책
압축 정책은 Ktable과 같이 메세지키를 기반으로 데이터를 처리할 경우 유용

액티브 세그먼트를 제외한 나머지 세그먼트들에 한해서 데이터 처리
압축시점은 min.cleanable.dirty.ratio
- 나머지 tail 영역의 레코드 개수와 head 영역의 레코드 개수의 비율

'더티 비율(dirty ratio)'은 더티 영역의 메시지 개수를 압축 대상 세그먼트에 남아있는 데이터 의 총 레코드 수(더티 영역 메시지 개수+클린 영역 메시지 개수)로 나눈 비율을 뜻한다. 만약
클린 영역에 3개의 레코드가 있고 더티 영역에 레코드가 3개가 있다면 더티 비율은。.5이다.

토픽의 압축은 min.cleanable.dirty.ratio 값에 따라 결정되며, 이 값이 클수록 압축 빈도는 줄고 많은 데이터를 압축하지만, 용량 효율이 낮아집니다. 반면 값이 작으면 압축이 자주 발생해 최신 데이터만 유지할 수 있지만, 브로커에 부담이 생깁니다. 따라서 각 토픽의 데이터 특성에 맞게 적절한 min.cleanable.dirty.ratio 값을 설정하는 것이 중요합니다.
Kafka에서 ISR(In-Sync Replica)는 리더 파티션과 팔로워 파티션이 동일한 상태로 데이터를 유지하고 있음을 의미합니다. 즉, 리더 파티션에 새로운 데이터가 추가될 때, 팔로워 파티션도 빠르게 그 데이터를 복제하여 리더와 동기화된 상태가 되는 것이죠. 그러나 복제 과정에서 약간의 시간차가 발생할 수 있으며, 이를 관리하고 모니터링하는 것이 Kafka의 핵심 중 하나입니다.
Kafka에서 리더 파티션은 클러스터 내 다른 브로커에 위치한 팔로워 파티션으로부터 데이터를 복제 받습니다. 리더 파티션에 새로운 레코드가 추가되면, 팔로워 파티션이 이를 받아 복제하기까지 약간의 시간이 소요되는데, 이 시간 동안 리더와 팔로워 간에 오프셋 차이가 발생합니다.
Kafka는 이러한 오프셋 차이를 모니터링하기 위해 replica.lag.time.max.ms 값을 사용하여 팔로워 파티션이 데이터를 적시에 복제하는지 확인합니다. 만약 팔로워가 지정된 시간(replica.lag.time.max.ms) 내에 데이터를 복제하지 못하면, 해당 팔로워 파티션은 문제가 발생한 것으로 간주되어 ISR 그룹에서 제외됩니다. 이렇게 함으로써 Kafka는 데이터 손실을 최소화하고, 안정성을 유지합니다.
카프카에서 서비스 중단 없이 토픽을 지속적으로 사용할 수 있도록 하기 위해서는 리더 파티션의 장애에 대비하는 방법도 중요합니다. ISR 그룹에 속하지 않은 팔로워 파티션을 리더 파티션으로 선출하는 설정을 할 수 있습니다. 이 경우, 일부 데이터 유실이 발생할 수 있지만, 서비스는 지속됩니다.
이를 설정하려면 unclean.leader.election.enable 옵션을 조정해야 합니다. 이 옵션을 true로 설정하면, ISR에 포함되지 않은 팔로워 파티션도 리더로 선출될 수 있습니다. 반대로, false로 설정하면 ISR에 포함된 팔로워 파티션만 리더가 될 수 있습니다.

일부 데이터 유실이 발생하더라도 서비스를 중단하지 않고 지속적으로 토픽을 사용하고 싶다 면 ISR이 아닌 팔로워 파티션을 리더로 선출하도록 설정할 수 있다. ISIS] 아닌 팔로워 파티
션을 리더 파티션으로 선출 가능한지 여부를 선택하기 위해서는 unclean.leader.election. enable 옵션을 false 또는 true로 설정하면 된다. false로 설정할 경우에는 ISR이 아닌 팔로워 파티션을 리더 파티션으로 선출하지 않는다.




acks를 all 또는 -1로 설정할 경우 프로듀서는 보낸 데이터가 리더 파티션과 팔로워 파티션에
모두 정상적으로 적재되었는지 확인한다. 리더 파티션뿐만 아니라 팔로워 파티션까지 데이터
가 적재되었는지 확인하기 때문에 0 또는 1 옵션보다도 속도가 느리다. 그럼에도 불구하고 팔 로우 파티션에 데이터가 정상 적재되었는지 기다리기 때문에 일부 브로커에 장애가 발생하더 라도 프로듀서는 안전하게 데이터를 전송하고 저장할 수 있음을 보장할 수 있다.


min.insync.replicas> 설정할 때는 복제 개수도 함께 고려해야 한다. 왜냐하면 운영하는 카프카 브로커 개수가 min.insync.replicas의 옵션값보다 작은 경우에는 프로듀서가 더는 데
이터를 전송할 수 없기 때문이다

브로커 3대로 클러스터를 운영하면서 min.insync.
replicas 옵션을 3으로 설정하는 경우를 예로 들 수 있다. 이런 상황에서 카프카 클러스터의
버전 업그레이드와 같은 상황이 발생하면 브로커는 롤링 다운 타임이 생기는데, 브로커가 1대
라도 중단되면 프로듀서가 데이터를 추가할 수 없다. 왜냐하면 min.insync.replicas가 3일 경
우에는 최소한 브로커가 3대 이상 실행 중이여야 3개의 복제본(리더 파티션 1, 팔로워 파티션
2)이 생기는 것을 만족할 수 있기 때문이다. 그러므로 토픽별 min.insync.replicas 옵션값은 브로커 개수 미만으로 설정해서 운영해야 한다.

동일한 데이 터를 보내더라도 PID가 달라지면 브로커 입장에서 다른 프로듀서 애플리케이션이 다른 데이 터를 보냈다고 판단하기 때문에 멱등성 프로듀서는 장애가 발생하지 않을 경우에만 정확히 한 번 적재하는 것을 보장한다는 점을 고려해야 한다.
멱등성 프로듀서의 시퀀스 넘버는。부터 시작하여 숫자를 1씩 더한 값이 전달된다.

트랜잭션 프로듀서를 사용하려면 enable.iclempotence 를 true로 설정하고 transactional.id를 임의의 String값으로 정의한다. 그리고 컨슈머의 isolation.level을 read_committed로 설정하면 프로듀서와 컨슈머는 트랜잭션으로 처리 완료된 데이터만 쓰고 읽게 된다.
