4. 프로듀서
send()가 리턴됐다고 브로커에 닿은 것이 아니다 — 어디까지를 성공으로 칠지는 설정이 정한다
이 장에서 처음 나오는 말4개
acksAcknowledgements- 브로커의 수신 확인을 어디까지 기다릴지 정하는 프로듀서 설정. 0(안 기다림) · 1(리더만) · all(ISR 전원)의 세 단계다.
멱등성Idempotence- 같은 요청이 두 번 가도 결과가 한 번과 같게 만드는 성질. 프로듀서 멱등성은 재시도로 인한 중복 저장을 브로커가 걸러내게 한다.
배치Batch- 레코드를 한 건씩이 아니라 모아서 보내는 것. Kafka 처리량의 비결이고, 지연(latency)과 맞바꾸는 나사다.
핫 파티션Hot Partition- 특정 키에 트래픽이 쏠려 파티션 하나만 바쁜 상태. 키 설계가 만든 병목이다.
보내는 길 — send()는 비동기다
섹션 제목: “보내는 길 — send()는 비동기다”send()는 레코드를 클라이언트 내부 버퍼에 넣고 바로 리턴한다. 실제 전송은
백그라운드 스레드가 배치로 모아서 한다 — 브로커 응답은 콜백/Future로 나중에 온다.
batch.size(배치 크기)와linger.ms(모으려고 기다리는 시간)가 처리량 ↔ 지연의 손잡이다.linger.ms=5~20만 줘도 처리량이 크게 오르는 경우가 많다- 성공 여부는 콜백에서 확인해야 한다.
send()만 부르고 결과를 안 보는 코드는 유실을 눈치채지 못한다 — “쏘고 잊기(fire-and-forget)“는 그래도 되는 데이터에만 쓴다
acks — 어디까지를 성공으로 칠까
섹션 제목: “acks — 어디까지를 성공으로 칠까”ISR 전원이 받아야 성공. min.insync.replicas와 결합해 “성공 응답 = 최소 N부 저장”을
보장한다 (3장의 표준 조합). 3.0부터 기본값이다.
지연이 조금 늘지만, 유실이 아까운 데이터라면 고민할 것 없이 이것이다.
리더가 받으면 성공. 리더가 응답 직후, 팔로워가 복사하기 전에 죽으면 유실된다. “가끔 유실돼도 되는 대량 데이터”(메트릭 등)에서 지연을 아끼는 선택.
응답을 안 기다린다. 가장 빠르고, 유실을 감지할 방법도 없다. 손실이 무의미한 데이터(초당 수만 건 샘플링 지표 등)가 아니면 쓸 일이 없다.
멱등성 — 재시도의 중복을 지운다
섹션 제목: “멱등성 — 재시도의 중복을 지운다”acks를 조여도 남는 구멍이 있다 — 응답이 유실된 경우다. 브로커는 저장했는데 성공 응답이 네트워크에서 사라지면, 프로듀서는 실패로 알고 재시도한다 → 같은 레코드가 두 번 저장된다.
멱등성 프로듀서(enable.idempotence=true, 3.0부터 기본)가 이 구멍을 막는다 —
프로듀서마다 ID, 레코드 배치마다 시퀀스 번호를 붙여 브로커가 이미 받은 배치를 알아보고
버린다. 재시도가 아무리 겹쳐도 파티션에는 한 번만 남고, 순서도 유지된다.
키 선택 — 순서가 필요한 단위를 찾는다
섹션 제목: “키 선택 — 순서가 필요한 단위를 찾는다”2장에서 본 대로 같은 키 → 같은 파티션 → 순서 보장. 그래서 키 선택의 질문은 “무엇으로 분배할까”가 아니라 “어느 단위로 순서가 필요한가”다.
| 데이터 | 키 | 왜 |
|---|---|---|
| 주문 이벤트 (생성 → 결제 → 취소) | 주문 ID | 한 주문의 이벤트가 순서 없이 읽히면 상태가 꼬인다 |
| 사용자 행동 이벤트 | 사용자 ID | 한 사용자 안에서의 선후만 맞으면 된다 |
| 서버 로그 · 메트릭 | 키 없음 | 순서 무관 — 골고루 분배가 이득 |
실패는 어디로 — 재시도와 버퍼
섹션 제목: “실패는 어디로 — 재시도와 버퍼”- 일시 오류(리더 교체 중,
NotEnoughReplicas…)는 클라이언트가 알아서 재시도한다. 총 시한은delivery.timeout.ms(기본 2분) — 이 안에 못 보내면 그때 실패가 콜백으로 온다 - 버퍼가 가득 차면(브로커가 느리거나 다운)
send()자체가buffer.memory한도에서 막힌다(block) — 브로커 장애가 프로듀서 앱의 지연으로 번지는 경로이니, 콜백 오류와 버퍼 사용률에 알람을 건다 - 최종 실패한 레코드를 어디에 남길지(로그 · 대체 저장소)는 애플리케이션의 몫이다 — “Kafka에 못 쓰면 어떻게 할 것인가”는 설계 단계에서 정해 둔다
4장 요약
섹션 제목: “4장 요약”send()는 버퍼에 넣을 뿐 — 성공 확인은 콜백에서, 전송은 배치로- acks=all + 멱등성이 기본값이고, 끄지 않는 것이 설정의 절반이다
- 멱등성이 지우는 것은 프로듀서 재시도 중복까지 — 컨슈머 쪽 중복은 6장의 일
- 키는 “순서가 필요한 단위”로 잡되, 분포가 고른지 같이 본다 (핫 파티션)
- 실패의 종착지(
delivery.timeout.ms초과, 버퍼 만석)를 설계에 넣어 둔다