반응형
카프카를 운영하면서 딱 하나의 지표만 모니터링해야 한다면 그것은 단연코 '랙'입니다. 랙이 쌓인다는 것은 공장에 원재료(데이터)는 계속 들어오는데, 물건을 만드는 속도(컨슈머)가 못 따라가서 창고가 터지기 직전이라는 위험 신호거든요.
랙의 정체가 무엇인지, 그리고 이를 해결하기 위한 5단계 특수 처방전을 낱낱이 공개하겠습니다!

📈 컨슈머 랙(Consumer Lag)의 정체: "이상과 현실의 간극"
컨슈머 랙은 '프로듀서가 넣은 마지막 데이터의 오프셋(Log End Offset)'과 '컨슈머가 마지막으로 읽은 데이터의 오프셋(Current Offset)' 사이의 차이를 말합니다.
- Lag = (최신 데이터 번호) - (내가 읽은 데이터 번호)
- 랙이 '0'에 가깝다면 실시간 처리가 아주 잘 되고 있다는 뜻이고, 랙이 수만, 수십만으로 늘어나고 있다면 시스템에 병목 현상이 발생했다는 뜻입니다.
🛠️ 컨슈머 랙을 줄이기 위한 5단계 정밀 처방전
1단계: 컨슈머 스케일 아웃 (The Power of Numbers)
가장 빠르고 확실한 방법입니다. 일꾼이 부족하면 더 뽑는 것이죠.
- 방법: 컨슈머 그룹 내의 컨슈머 프로세스(인스턴스) 수를 늘립니다.
- 비밀 조건: 앞서 공부했듯이, 컨슈머만 늘린다고 해결되지 않습니다. 파티션 개수(Partition Count)가 컨슈머 수보다 많거나 같아야 합니다.
- 전략: 만약 파티션이 10개인데 컨슈머가 2명뿐이라 랙이 생긴다면, 컨슈머를 10명까지 늘리세요. 만약 이미 10명인데도 랙이 생긴다면? 파티션과 컨슈머를 동시에 20개로 늘려야 합니다.
2단계: 컨슈머 로직 최적화 및 멀티스레딩
컨슈머가 데이터를 한 번 가져와서(Poll) 처리하는 시간이 너무 길면 랙이 생깁니다.
- 비즈니스 로직 최적화: DB에 하나씩 넣고(Insert) 있지는 않은지 확인하세요. 데이터를 모아서 한꺼번에 넣는 배치 인서트(Batch Insert)를 적용하면 처리 속도가 수십 배 빨라집니다.
- 멀티스레드 활용: 카프카 컨슈머는 단일 스레드 기반으로 동작하는 경우가 많습니다. 데이터를 가져오는 스레드와 실제로 계산/저장하는 워커 스레드(Worker Thread)를 분리하여 CPU 자원을 극한으로 활용하세요.
3단계: 가져오는 양 조절 (Fetch Tuning)
한 번에 너무 조금씩 가져오면 네트워크 통신 횟수가 많아져 비효율적입니다.
fetch.min.bytes: 브로커로부터 한 번에 가져올 최소 데이터 양을 키웁니다. 데이터가 찰 때까지 기다렸다가 뭉텅이로 가져오게 합니다.max.poll.records: 한 번의poll()호출로 가져올 최대 레코드 수를 조절합니다. 이 값이 너무 크면 컨슈머가 처리하다가 지쳐서 '나 죽었소' 하고 리밸런싱을 유발할 수 있으니 적절한 값을 찾아야 합니다.
4단계: 리밸런싱 지옥 탈출하기
컨슈머가 너무 바빠서 브로커에게 "나 살아있어!"라고 보내는 하트비트(Heartbeat)를 놓치면, 브로커는 컨슈머가 죽은 줄 알고 리밸런싱을 시작합니다. 리밸런싱 중에는 데이터 소비가 멈추므로 랙이 폭발적으로 늘어납니다.
max.poll.interval.ms: 컨슈머가 데이터를 처리하는 데 걸리는 최대 시간을 넉넉하게 늘려주세요.session.timeout.ms: 컨슈머와 브로커 간의 연결 유지 시간을 조절하여 불필요한 리밸런싱을 방지합니다.
5단계: 하드웨어 및 인프라 체크
기술적인 설정 외에 물리적인 한계도 체크해야 합니다.
- 네트워크 대역폭: 카프카 서버와 컨슈머 서버 사이의 네트워크가 꽉 찼는지 확인하세요.
- 디스크 I/O: 컨슈머가 데이터를 쓴 후에 결과를 DB나 파일에 저장한다면, 그 타겟 시스템의 I/O 속도가 병목의 원인일 수 있습니다.
🔍 랙 모니터링, 어떻게 하나요?
랙은 카프카 브로커나 컨슈머 내부 지표로도 볼 수 있지만, 가장 추천하는 도구는 'Burrow(버로우)'나 'Prometheus + Grafana' 조합입니다.
- Burrow (LinkedIn 개발): 별도의 대시보드 없이 HTTP API로 랙 상태를 알려줍니다. 특히 "단순히 숫자가 높은 건지, 아니면 진짜 처리가 안 되고 있는 건지"를 판단하는 컨슈머 상태(Status)를 알려주는 것이 아주 영리합니다.
- Grafana 대시보드: 파티션별로 랙을 시각화하면 특정 파티션에만 데이터가 몰리는 '데이터 치우침(Data Skew)' 현상까지 한눈에 잡아낼 수 있습니다.
💡 실전 비유: "고속도로 톨게이트"
- 로그 엔드 오프셋: 고속도로 끝에 도착한 자동차 수.
- 컨슈머 오프셋: 톨게이트를 통과한 자동차 수.
- 컨슈머 랙: 톨게이트 앞에서 대기 중인 차량 정체 행렬.
- 해결책 1 (스케일 아웃): 톨게이트 문(컨슈머)을 더 많이 엽니다. (단, 도로 차선인 파티션이 그만큼 있어야 함)
- 해결책 2 (로직 최적화): 하이패스(배치 처리)를 도입해서 차 한 대당 통과 시간을 줄입니다.
- 해결책 3 (튜닝): 통행료 받는 속도가 너무 느리면 도로 전체가 마비(리밸런싱)되니, 직원 교육(설정 최적화)을 다시 시킵니다.
🏆 핵심 요약: 랙 줄이기 체크리스트
| 우선순위 | 조치 사항 | 기대 효과 |
|---|---|---|
| 1순위 | 컨슈머 및 파티션 추가 | 처리 용량 비례 증설 (가장 확실함) |
| 2순위 | 배치 처리(Bulk Write) 적용 | 개별 데이터 처리 시간 단축 |
| 3순위 | max.poll.records 조절 |
컨슈머 처리 부하 최적화 |
| 4순위 | 리밸런싱 방지 설정 | 불필요한 서비스 중단 제거 |
| 5순위 | 데이터 치우침(Skew) 확인 | 특정 파티션에만 랙이 쌓이는 문제 해결 |
반응형
'1. 개발 > 1.4. 데이터 분석' 카테고리의 다른 글
| Kafka Streams는 일반 Consumer랑 뭐가 다를까? (1) | 2026.02.06 |
|---|---|
| Kafka - '최소 한 번(At-least-once)' vs '딱 한 번(Exactly-once)' (0) | 2026.02.06 |
| Kafka - Cleanup Policy: Delete vs Compact (0) | 2026.02.06 |
| Kafka는 어떻게 부하를 분산할까? (Consumer Group) (1) | 2026.02.05 |
| Kafka - ack 옵션(0, 1, all) (0) | 2026.02.05 |