레이블이 Kafka인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Kafka인 게시물을 표시합니다. 모든 게시물 표시

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 모드는 못 써봄. 이게 트랜잭션 비용 많이 줄였다는데 성능 차이 궁금. 다음 달 스테이지에 올려보기로.

20190826

Kafka 2.3 Exactly-once 운영 메모

카프카 2.3 올리면서 exactly-once 기능을 프로듀서 쪽에서 제대로 설정했다. 2.1 때부터 multi-partition EoS 가능했는데 우린 그냥 at-least-once에 consumer 쪽에서 idempotent 처리하는 구조로 버티고 있었음. 이제 한 번 정리.

브로커 설정은 기존과 크게 안 바뀜. 프로듀서 쪽만.

acks=all
enable.idempotence=true
max.in.flight.requests.per.connection=5
retries=Integer.MAX_VALUE
transactional.id=order-service-1

스트리밍 앱 쪽은 이렇게.

props.put(StreamsConfig.PROCESSING_GUARANTEE_CONFIG, "exactly_once");

운영 포인트:

  • transactional.id는 인스턴스 유니크하게 줘야 한다. 컨테이너 재시작 시 같은 id면 괜찮지만 수평 확장시 인스턴스별로 달라야 함.
  • 트랜잭션 커밋 실패 시 ProducerFencedException 나오면 프로세스 종료하고 restart. 복구 시도하지 말 것.
  • commit interval 짧게 하면 throughput 떨어짐. 우리는 500ms로 잡고 있음.

성능 영향 — 기존 대비 write throughput 15~20% 감소. 근데 컨슈머 쪽 중복 제거 로직 없애니까 전체 코드 엄청 줄었다. 트레이드오프 괜찮음.

2.3 들어온 Incremental Cooperative Rebalancing도 같이 켬. 컨슈머 리밸런싱이 한 번에 전체 멈추는 게 아니라 점진적으로 바뀌어서 p99 latency 스파이크가 훨씬 덜함.