20220324

Kafka Streams 실전 패턴

Kafka Streams를 실서비스에 넣은 지 3개월 정도. 2.8 쓰다 3.1로 올림. 사용하면서 굳어진 패턴 몇 개.

1. topic 이름은 엔티티_이벤트_상태 3단

order.created.v1, order.paid.v1 이런 식. 버전 suffix 꼭 넣음. 스키마 깨지면 v2로 포킹. 다운스트림이 v1/v2 전환 시간 가질 수 있게.

2. KTable 쓸 때 log compaction 필수

changelog topic 자동 생성되는데 retention 무제한 안 두면 state store 복원이 안 된다. 이거 모르고 retention 7d 걸어뒀다가 장애 한 번.

cleanup.policy=compact
min.cleanable.dirty.ratio=0.1
segment.ms=604800000

3. join 윈도우는 보수적으로

stream-stream join 할 때 window를 크게 잡으면 state store 폭증. 5분 짜리로 시작해서 필요 시 늘리는 방향. 처음에 "한 시간 정도 넉넉히"로 했다가 디스크 먹는 속도 보고 바로 5분으로 축소.

4. 예외 처리 전략 설정

기본은 DEFAULT_DESERIALIZATION_EXCEPTION_HANDLER_CLASS_CONFIG가 LogAndFail. prod에 그대로 두면 포이즌 메시지 하나에 앱 죽는다. LogAndContinue로 바꾸고 DLQ에 보내는 handler 직접 구현 권장.

public class DlqHandler implements DeserializationExceptionHandler {
    @Override
    public DeserializationHandlerResponse handle(
            ProcessorContext ctx, ConsumerRecord<byte[], byte[]> rec, Exception e) {
        dlqProducer.send(new ProducerRecord<>("deser-dlq", rec.key(), rec.value()));
        return DeserializationHandlerResponse.CONTINUE;
    }
}

5. topology.optimization 켜기

StreamsConfig.TOPOLOGY_OPTIMIZATION을 "all"로. default가 none이다. rekey 시 중복 topic 안 만들도록 해주는 옵션 포함.

6. state store 복원 시간 대비

인스턴스 재시작 시 changelog topic 끝까지 읽어서 복원함. 수백GB면 수십 분 걸릴 수 있음. standby.replicas를 1~2로 둬서 failover 즉시 가능하게.


아직 Exactly-once v2 모드는 못 써봄. 이게 트랜잭션 비용 많이 줄였다는데 성능 차이 궁금. 다음 달 스테이지에 올려보기로.