pile·
DB / 데이터·마켓컬리마켓컬리 Hello World·

DevOps 엔지니어의 Redis 테스트 분투기 1편

Look-Aside Cache에 넣은 키를 읽지 못해 RDS로 부하가 몰린 장애를 계기로 Redis 사용 패턴과 적정 크기를 검증한 실험이다. ElastiCache 제약과 실제 장애 흐름을 반영하기 위해 Node.js·Express 테스트 API와 nGrinder를 만들었다. 1,500 가상 사용자가 만료된 한 키를 동시에 확인하고 반복 SET하는 조건에서 오류와 CPU 급증을 재현하고, 데이터 구조와 장애 시 우회 전략이 인스턴스 크기보다 먼저라는 결론에 도달한다.

핵심 포인트
  • Redis 키를 가져오지 못하자 Look-Aside Cache의 요청이 AWS RDS로 쏠려 장애가 발생했다.
  • ElastiCache는 일부 성능 영향 명령을 막고 있어 redis-benchmark만으로 실제 애플리케이션 문제를 재현하기 어려웠다.
  • Node.js API와 nGrinder로 1,500 vUser가 만료된 동일 키를 확인하고 GET·SET하는 부하를 만들었다.
  • 키가 없거나 만료된 초반에 TPS가 급락하고 오류가 집중됐으며, 200명 이상이 동시에 접근할 때 Primary CPU가 25% 이상 올랐다.
  • 반복 루프를 제거하자 긴 문자열을 넣어도 CPU 사용과 오류가 줄고 평균 TPS가 높아졌다.
상세 정리
  • 계기: API 업데이트 뒤 Redis에 적재된 키를 가져오지 못했다. 캐시 미스가 DB 조회로 이어지는 구조라 RDS가 직접 부하를 받아 장애가 났다.
  • 검증 질문: 왜 Key/Value가 저장되지 않았는지, 현재 ElastiCache 크기가 서비스 부하에 적절한지 확인해야 했다. 사내 표준 사이징 사례도 없었다.
  • 기본 도구: redis-benchmark는 PING, SET, GET, List·Set·Hash 계열 명령을 기본 10만 회 실행하고 연결 수, 스레드, 요청 수, payload 크기를 바꿀 수 있다.
  • 도구 한계: 운영은 AWS ElastiCache이고 외부 benchmark 접근과 위험 명령이 제한됐다. 단순 명령 성능보다 장애 시 애플리케이션 동작을 재현할 필요도 있었다.
  • Redis 이해: String, List, Set, Sorted Set, Hash의 저장 구조와 Pub/Sub, Streams의 동작을 구분했다. Pub/Sub은 메시지를 보관하지 않아 전통적인 Queue와 다르다.
  • 운영 주의: 물리 메모리를 넘으면 swap으로 성능이 떨어질 수 있어 RSS를 봐야 한다. Cluster와 Failover는 용도에 따라 선택하고, 전체 키 조회 같은 느린 명령은 피해야 한다.
  • 테스트 환경: cache.m5.large ElastiCache Failover, c5.large EC2 두 대, nGrinder, Node.js 테스트 API를 구성했다.
  • 클라이언트 구성: NodeRedis로 Primary와 Read Endpoint를 나누고 get을 Promise 형태로 감쌌다.
  • 테스트 로직: data:icon 키를 조회해 없으면 긴 JSON String을 넣고 TTL을 60초로 설정했다. 요청 파라미터만큼 같은 확인·갱신을 반복하도록 고의로 부담을 만들었다.
  • 첫 결과: 1,500 vUser 부하 시작 시 TPS가 바닥을 치고 오류가 대량 발생했다. redis-cli --stat와 --latency로 요청·메모리·지연을 함께 봤다.
  • 발생 시점: 키가 없거나 expire된 직후 다수 요청이 동시에 SET하고 값을 확인하는 구간에 문제가 집중됐다. 값이 정상 저장된 뒤에는 호출이 성공했다.
  • 자원 변화: 존재 확인은 Read Endpoint CPU를 올렸고, 200명 이상이 GET·SET을 동시에 수행하면 Primary CPU도 25% 이상 사용했다.
  • 비교 실험: 루프를 없애고 미스일 때 한 번만 SET하도록 단순화한 뒤 같은 1,500 vUser를 넣었다. CPU가 덜 오르고 평균 TPS가 훨씬 높았다.
  • 설계 결론: 같은 키를 많은 클라이언트가 자주 바꾸는 데이터라면 file cache나 더 적합한 Collection을 고려해야 한다. Redis가 실패했을 때 DB로 전부 밀려가지 않는 대책도 필요하다.
  • 다음 과제: 1편은 장애 재현과 기본 사용 패턴에 집중했고, 후속 실험에서 Redis 사이징과 모니터링 기준을 다루기로 했다.
왜 읽나Redis 캐시 미스가 DB 장애로 증폭되는 구조를 부하 테스트로 재현하고 데이터 구조·동시 갱신·폴백 위험을 점검하려는 백엔드·DevOps 엔지니어에게 유용하다.
마켓컬리
마켓컬리 Hello World 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. DB / 데이터·spotify-engSpotify Engineering·

    데이터 레이크 온라인 포인트 쿼리 인덱싱 — RAP

    Spotify 엔지니어링이 페타바이트 규모 데이터 레이크(GCS)에 저장된 Parquet 파일에서 한 자릿수 밀리초 레이턴시로 포인트 쿼리를 수행하는 RAP(Random Access Parquet) 방식을 공개했다. Trino·BigQuery 같은 분산 SQL 엔진은 단일 행 조회도 스케줄링·플래닝 비용으로 수 초가 걸리지만, RAP는 외부 인덱스로 키→(파일, 행 번호)를 직접 매핑해 의존적 read chain을 병렬화함으로써 이 문제를 해결했다. 기존 KV 스토어(Bigtable)와 달리 GB당 비용이 클라우드 스토리지 read 수준에 불과해 장기 이력 데이터나 롱테일 피처도 인터랙티브 조회 대상이 된다.

    #data-engineering#indexing#data-lake+2
  2. DB / 데이터·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    데이터 통합— MongoDB 원칙으로 document를 통합하고 동기화를 재설계하다 (3/3)

    여기어때 전시개발팀은 ES 단일 대문서 → MongoDB v1 RDB 1:1 파편화 → v2 도메인 단위 통합이라는 세 차례 구조 전환을 거쳐 전체 동기화 시간을 약 1시간에서 10분으로 단축했다. 이 글은 3부작의 마지막으로, v2 통합 문서 구조에 맞춰 "$set/$unset 필드 단위 부분 갱신 + 이벤트 발행" 기반 동기화를 어떻게 재설계했는지 구체적인 MongoDB 패턴과 함께 설명한다.

    #denormalization#data-sync#mongodb+2
  3. DB / 데이터·pinterest-engPinterest Engineering·

    Pinterest 차세대 DB 수집 프레임워크의 자동화된 스키마 진화

    Pinterest의 CDC 기반 DB 수집 파이프라인은 MySQL에서 Kafka, Flink, Spark, Iceberg를 거치는 다층 구조다. 스키마 변경이 생기면 모든 계층을 동시에 업데이트해야 해 드리프트, 배포 실패, 데이터 불일치가 반복됐다. Pinterest 엔지니어링 팀은 이를 해결하기 위해 가산적 변경만 자동화하는 스키마 진화 프레임워크를 구축하고, PR 기반 롤아웃과 SLA 기반 일관성 모델을 도입했다.

    #data-pipeline#apache-flink#cdc+2