AI Briefing

DynamoDB를 진정시켜라! Kafka와 Redis로 구현한 실시간 역압력 아키텍처 구축기

·2025.12.02 10:43

CloudWatch와 Redis Stream으로 DynamoDB 부하를 감지해 Kafka 소비를 pause/resume했다.

새벽 시간대 배치성 Kafka 작업이 DynamoDB를 과도하게 사용하면서, 실시간 API까지 throttling 피해를 입었다. 트래픽이 적은 시간인데도 장애가 난 이유는 배치와 실시간 작업이 같은 DB 자원을 놓고 경쟁했기 때문이다.

정적 제어인 consumer concurrency 제한이나 RateLimiter는 간단하지만 한계가 분명했다. DB가 한가할 때는 자원을 낭비하고, 반대로 실시간 트래픽이 급증하면 고정값이 오히려 장애를 키울 수 있어, DB 상태에 따라 스스로 조절하는 중앙 제어가 필요해졌다.

해결책은 실시간 역압력(backpressure) 아키텍처였다. 구조는 세 부분으로 나뉜다.

  • 모니터링 & 지표: CloudWatch에서 DynamoDB의 provisioned capacity 대비 실제 사용량 비율을 감시
  • 알림 전파: 임곗값 초과 시 SNS가 Webhook을 호출하고, 메시지를 Redis Stream으로 fan-out
  • 제어 서비스: 알람을 구독한 Spring 애플리케이션이 배치성 Kafka Consumer를 pause 또는 resume

제어 지표는 DynamoDB의 Provisioned throughput과 실제 처리량의 비율로 잡았다. CloudWatch의 수집 주기가 읽기/쓰기 지표는 1분, provisioned 지표는 5분이라서, LAST 함수를 사용해 주기 차이를 보정했다.

배치성 작업은 @KafkaBackpressure 같은 전용 애노테이션으로 명확히 구분했고, Spring Kafka의 KafkaListenerEndpointRegistry를 활용해 대상 컨테이너를 관리했다. 컨슈머는 런타임에 리밸런싱될 수 있으므로, ConsumerRebalanceListeneronPartitionsAssigned에서 다시 알람 상태를 확인해 새로 할당된 파티션도 즉시 pause되도록 만들었다.

이 방식으로 지난 6개월 동안 새벽 배치 작업을 제어한 결과, 글에서는 읽기/쓰기 처리량이 각각 11%, 47.5% 감소했다고 밝혔다. 다만 CloudWatch의 1분 단위 집계는 짧은 스파이크를 놓칠 수 있고, 현재 방식이 on/off 스위치처럼 동작해 거칠다는 한계도 있어, 향후에는 더 세밀한 지표와 Global RateLimiter 도입을 검토하고 있다.

이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.

요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.