KEDA를 활용한 로그 시스템 오토스케일링 경험담

우아한형제들은 KEDA를 활용하여 100만 TPS의 로그 시스템에 오토스케일링을 성공적으로 적용하였습니다. 이 경험을 통해 로그 처리의 변동성을 관리하며 비용 효율성을 높이는데 기여하게 되었습니다. 본 문서에서는 KEDA 도입 과정과 실제 운영 사례를 통한 운영 환경 개선 방안에 대해 설명합니다. KEDA 적용을 통한 로그 시스템 아키텍처 변화 KEDA를 도입하기 전, 우아한형제들은 기존 HPA를 이용하여 로그 시스템의 오토스케일링을 시도했습니다. 하지만 평균 CPU 및 메모리 사용량을 기준으로 스케일링이 진행되면서 한계에 봉착하게 되었습니다. KEDA의 도입 이후, 이벤트 기반으로 스케일링을 설정함으로써, 로그 시스템의 아키텍처를 유연하게 설계할 수 있었습니다. KEDA는 다양한 이벤트 소스를 지원하여 로그 시스템의 특성에 맞는 스케일링 기준을 설정할 수 있게 해줍니다. 예를 들어, Fluentd의 버퍼 사용률을 기준으로 스케일링 트리거를 설정함으로써, 시스템이 실제로 부하를 받기 시작하기 전에 프로세스를 조정할 수 있었습니다. 이는 로그 처리의 안정성을 크게 향상시켰고, 유연한 리소스 관리로 비용을 줄일 수 있는 기반을 마련하였습니다. 이러한 변화는 로그 시스템 아키텍처의 효율성을 높이고, 운영 환경을 개선하는 데에 결정적인 역할을 했습니다. 다양한 메트릭을 조합하여 스케일링 미세 조정이 가능해짐으로써, 시스템 부하가 예상되는 피크 시간대에도 원활하게 처리할 수 있는 역량을 갖추게 되었습니다. KEDA 도입을 통한 메트릭 기반 스케일링 효과 KEDA의 도입은 로그 시스템의 메트릭 기반 스케일링을 가능하게 하였습니다. 기존 HPA와 달리, KEDA는 프로메테우스를 이용해 다양한 지표를 직접적으로 활용할 수 있게 해줍니다. 이를 통해 CPU 및 메모리 사용량 외에도 Fluentd 버퍼와 같은 중요한 메트릭을 스케일링 기준으로 설정할 수 있었습니다. Fluentd의 버퍼가 일정 사용률을 초과할 경우 이를 위기 상황으로 간주하여 스케일 아웃을...

Redis 신규 연결 증가 원인 분석 및 해결방법




1. Redis 신규 연결 생성 원인 분석

Redis 신규 연결이 지속적으로 증가한 이유는 여러 요인에 기인했습니다. 먼저, Lettuce 기반의 파이프라이닝(Pipelining) 기능이 핵심 원인이었습니다. RedisTemplate의 executePipelined() 메서드는 여러 명령을 병렬로 처리하기 위해 별도의 커넥션을 생성합니다. 이 과정에서 기본 커넥션 풀이 존재하더라도, 파이프라이닝의 특성상 별도의 연결이 새로 열리게 됩니다.

특히 사용자 요청이 집중되는 자정 무렵에도 신규 커넥션 수가 급증한 이유는, 해당 파이프라이닝이 트래픽 피크 시간대에 반복적으로 실행되었기 때문입니다. 즉, 명령어를 일괄 처리하는 과정에서 기존 연결 재사용이 아닌 새로운 커넥션 생성이 계속 이어진 것입니다.

두 번째 요인은 커넥션 풀의 LIFO(Last In First Out) 전략이었습니다. LIFO는 최근 사용된 커넥션부터 재사용하기 때문에, 사용되지 않는 커넥션은 IDLE 상태로 남게 됩니다. 트래픽이 몰릴 경우 이 IDLE 커넥션은 제거되거나 새로운 커넥션 생성으로 이어질 수 있습니다.

AWS ElastiCache 환경에서는 기본적으로 100초 이상 IDLE 상태의 커넥션을 자동으로 제거합니다. 따라서, IDLE 커넥션이 폐기되고 새로운 연결이 반복적으로 생성되는 구조적 문제가 발생했습니다. 결과적으로 커넥션 끊김 및 재연결 현상이 지속되며, 신규 연결 수가 급격히 늘어나는 현상이 나타났습니다.

이 과정을 통해 Redis 관련 메트릭을 지속적으로 모니터링하고, 트래픽 특성에 맞는 커넥션 설정을 정교하게 조정해야 함을 인식하게 되었습니다.

2. Redis 신규 연결 문제 해결 방법

신규 연결 증가 문제를 해결하기 위해 두 가지 접근 방식을 적용했습니다.

첫 번째는 커넥션 풀 전략 변경입니다. 기본 LIFO 방식을 FIFO(First In First Out)로 전환하여, 이전에 반납된 커넥션을 우선 재사용하도록 구성했습니다. FIFO 방식은 오래된 커넥션부터 순차적으로 재사용하기 때문에, IDLE 상태로 장시간 남아 있는 연결이 최소화됩니다.

예를 들어, commons-pool2를 사용하는 경우 poolConfig.setLifo(false) 설정을 통해 FIFO 전략으로 동작하게 할 수 있습니다. 이 변경을 통해 커넥션이 자주 폐기되지 않고, 장기간 안정적으로 재사용되며, Redis 서버의 연결 요청 부하를 줄이는 효과가 확인되었습니다.

두 번째는 IDLE 커넥션 관리 설정입니다. 불필요하게 오래 유지되는 커넥션을 주기적으로 정리하기 위해, minEvictableIdleDurationtimeBetweenEvictionRuns 값을 조정했습니다. 예를 들어 두 값을 각각 30초로 설정하면, 30초 이상 사용되지 않은 커넥션은 자동으로 제거되어 풀의 효율성이 유지됩니다.

이 설정은 커넥션 풀 내부에 쌓이는 불필요한 IDLE 연결을 줄이고, Redis 서버 자원의 낭비를 방지하는 효과를 가져왔습니다. 또한, 애플리케이션에서 커넥션 재활용이 효율적으로 이루어져 클러스터의 응답 속도가 안정적으로 유지되었습니다.

요약하자면, LIFO → FIFO 전략 변경과 IDLE 커넥션 정리 설정을 병행하여 Redis 신규 연결 폭증 문제를 실질적으로 완화했습니다.

3. Redis 신규 연결 문제 해결의 성과

설정 변경 이후, 신규 커넥션 지표가 뚜렷하게 안정화되었습니다. 특히 트래픽 피크 시간대 이후에도 신규 연결이 급증하는 현상이 사라졌습니다. 서버 리소스 사용률이 개선되었고, 전체적인 커넥션 유지 비용이 크게 감소했습니다.

Redis 클러스터 모니터링 결과, 연결 수와 처리 지연이 이전 대비 약 30% 이상 감소했으며, 클라이언트 측 재연결 이벤트도 크게 줄어든 것으로 확인되었습니다.

또한, 본 문제 해결 과정을 통해 Spring Data RedisElastiCache 간의 세부 동작 차이를 깊이 이해할 수 있었습니다. Lettuce 커넥션의 특성과 AWS의 세션 유지 정책을 함께 고려해야 한다는 점이 명확해졌습니다.

앞으로는 Redis의 연결 관리와 자원 최적화를 위해 정기적인 모니터링과 세부 설정 검토를 지속할 예정입니다. 이번 경험은 동일한 문제를 겪는 개발자들에게 실질적인 참고 자료가 될 것입니다.

결론: 안정적 Redis 운영을 위한 교훈

Redis 신규 연결 증가는 단순한 설정 문제가 아닌, 커넥션 관리 전략의 구조적 이슈였습니다. FIFO 기반 풀 전략과 IDLE 관리 정책을 적용함으로써 시스템 안정성과 성능 모두를 개선할 수 있었습니다.

결국 Redis 성능 최적화는 ‘지속적인 관찰과 점진적 조정’에서 비롯됩니다. 각 환경의 트래픽 패턴을 분석하고, 적절한 풀 전략을 도입해 안정적 운영을 실현하는 것이 중요합니다.


이 블로그의 인기 게시물

우아한형제들의 실시간 알림 혁신: SSE(Server-Sent Events)로 이룬 효율성과 안정성

물어보새의 진화와 지식 공유 확장

우아한 디버깅 툴 개선으로 QA 업무 효율화