Kafka Streams 토폴로지 설정 중에 문서에 유독 굵게 강조된 경고가 하나 있습니다. StreamsBuilder와 StreamsConfig 양쪽 Javadoc에 똑같이 반복해서 적혀 있길래 실제로 자주 걸리는 함정인가 싶어 확인해봤습니다.
topology.optimization은 설정만으로 동작하지 않는다
topology.optimization(REUSE_KTABLE_SOURCE_TOPICS, MERGE_REPARTITION_TOPICS, SINGLE_STORE_SELF_JOIN 등)을 properties에 넣어도, StreamsBuilder.build()를 인자 없이 호출하면 이 설정이 반영되지 않습니다. 최적화가 적용되려면 반드시 StreamsBuilder.build(Properties)로 설정 객체를 함께 넘겨야 합니다.
Properties props = new Properties();
props.put(StreamsConfig.TOPOLOGY_OPTIMIZATION_CONFIG, StreamsConfig.OPTIMIZE);
StreamsBuilder builder = new StreamsBuilder();
// ... 토폴로지 구성 ...
Topology topology = builder.build(props); // build()가 아니라 build(props)
설정값만 넣어두고 build()를 그대로 호출하는 코드가 컴파일도 되고 실행도 되기 때문에, 최적화가 빠졌다는 사실을 알아채기 어렵습니다. 리파티션 토픽이 예상보다 많이 생기거나 리소스 사용량이 기대와 다르다면 이 지점부터 의심해볼 만합니다.
max.task.idle.ms의 기본값 0은 "기다리지 않는다"가 아니다
max.task.idle.ms 기본값 0을 "대기 없이 즉시 처리"로 읽기 쉬운데, 실제 의미는 다릅니다. 브로커에 이미 도착해 있는 데이터 범위 안에서는 타임스탬프 순서를 지키기 위해 기다린다는 뜻입니다. 조인이나 머지에서 순서를 완전히 무시하고 로컬에 있는 데이터만 즉시 처리하려면 -1로 설정해야 하는데, 이 경우 조인 결과가 타이밍에 따라 달라질 수 있습니다. 기본값을 건드릴 때는 이 차이를 알고 바꾸는 게 안전합니다.
exactly_once_v2를 켜면 강제로 고정되는 것들
processing.guarantee는 at_least_once(기본)와 exactly_once_v2 두 값만 허용합니다. EOS를 켜면 사용자가 따로 지정해도 무시되고 내부적으로 강제 고정되는 설정이 있습니다.
- 컨슈머
isolation.level→read_committed - 프로듀서
enable.idempotence→true commit.interval.ms기본값이 30초(at_least_once)에서 100ms(exactly_once_v2)로 바뀜
EOS는 브로커 3대 이상 클러스터가 기본 전제입니다. 트랜잭션 로그 복제 안전성 때문인데, 로컬 개발 환경에서 단일 브로커로 EOS를 테스트하려면 브로커의 transaction.state.log.replication.factor와 min.isr을 낮춰야 합니다. 이 값을 낮춘 채로 운영 배포까지 그대로 가져가면 안 됩니다.
상태 저장소 복구, transactional statestores로 재빌드를 피한다
상태 저장소는 기본적으로 RocksDB이고, 변경 로그 토픽으로 백업되어 장애 시 재생으로 복구됩니다. 트렁크에 있는 enable.transactional.statestores를 켜면 상태 저장소 쓰기가 트랜잭션 버퍼에 버퍼링되었다가 대응하는 카프카 변경 로그 트랜잭션이 커밋될 때 함께 커밋됩니다.
이게 왜 중요하냐면, 예전에는 EOS 환경에서 에러가 나면 상태 저장소를 통째로 지우고 처음부터 재빌드해야 했습니다. 이 설정을 켜면 마지막 성공 커밋 이후의 쓰기만 유실되고 재생되는 방식으로 바뀌어서, 상태가 큰 애플리케이션의 복구 시간이 크게 줄어듭니다. 신규로 EOS 파이프라인을 설계한다면 기본 활성화를 검토해볼 만합니다.
정리
리밸런싱 중 처리가 멈추는 시간을 줄이려면 acceptable.recovery.lag, num.standby.replicas, max.warmup.replicas, probing.rebalance.interval.ms 네 가지를 세트로 봐야 합니다. 상태 저장소 복구가 1분을 넘기지 않는 선에서 acceptable.recovery.lag를 잡는 게 문서가 권하는 기준입니다. 여기에 토폴로지 최적화 설정과 build(Properties) 호출을 짝지어 코드 리뷰 체크리스트에 넣어두면, 위에서 말한 함정에 걸릴 일이 줄어듭니다.