Redis 메모리 폭증과 eviction 정책 미스매치 사례 분석 및 대응 가이드
사례 개요 — 어떤 상황에서 메모리가 급증했는가
운영 중인 Redis 클러스터(최대 메모리 32GB, eviction=volatile-lru)에서 특정 일자 오전 10:00~11:30 사이 메모리 사용률이 급격히 상승했다. 평소 오전 API 피크와 겹쳐 동시 쓰기 요청이 늘었다. 같은 시간대에 배치·집계 작업이 TTL 없이 결과를 캐시에 적재해 소멸되지 않는 키가 누적된 것이 주된 원인으로 확인됐다. 영향과 증상은 다음과 같다.- 서비스 영향: API 평균 응답시간이 50ms에서 400ms로 악화했다. 일부 요청은 503 또는 타임아웃을 반환했고, DB에서 롤백과 쿼리 폭증이 발생해 전반적인 서비스 지연이 초래됐다.
- 시간대·트래픽 패턴: 오전 피크에 동시 쓰기가 집중되는 가운데 배치 입력이 겹치며 쓰기 비중이 급증했다.
- 사용자 리포트·알림: 프론트엔드에서 느린 페이지와 연속 오류가 보고됐다. 모니터링에는 High Redis memory usage, 연결된 클라이언트 수 증가, slow commands 증가가 포착되었으나 eviction count는 기대만큼 오르지 않아 eviction 정책과 실제 동작 사이의 미스매치가 의심됐다.
초기 탐지와 핵심 진단 지표
메모리 이상 징후가 보이면 우선 Redis 내부 상태를 실시간으로 수집해 원인 범위를 좁히세요. 핵심 명령은 INFO MEMORY와 INFO STATS이며, 다음 항목을 먼저 확인합니다.
- evicted_keys: 강제 축출 발생 여부 — eviction 정책이 맞지 않을 때 급증합니다
- expired_keys: TTL 만료로 인한 키 감소 패턴
- used_memory_peak: 과거 피크 메모리와 현재 used_memory의 차이
진단 흐름은 다음과 같습니다.
- 초~분 단위로 INFO MEMORY와 INFO STATS를 수집해 메모리 타임라인을 만듭니다
- 타임라인에서 used_memory, used_memory_peak, evicted_keys의 증감 시점을 포착합니다
- 같은 시점의 애플리케이션 로그(배치·배포·트래픽 급증·GC 등)와 대조하며 상관관계를 분석하세요
- 큰 키 탐지(MEMORY USAGE 등)와 eviction 정책(maxmemory-policy) 설정을 점검합니다
메트릭 타임라인과 애플리케이션 로그를 함께 보면, 키 폭증과 정책 미스매치 문제를 빠르게 가려낼 수 있습니다. 실무 체크리스트: INFO 수집 → 큰 키(MEMORY USAGE) 확인 → maxmemory-policy 설정 검증. 특히 Redis 메모리 폭증과 eviction 정책 미스매치 사례에서는 이 순서로 점검하면 원인 파악 속도가 크게 빨라집니다.
Redis 메모리 관리와 eviction 정책의 작동 원리
Redis는 maxmemory로 프로세스가 사용할 메모리 한도를 설정합니다. 한계에 도달하면 maxmemory-policy가 어떤 동작을 할지 결정합니다. 주요 정책은 다음과 같습니다.
- allkeys-lru / volatile-lru: 근사 LRU(샘플링 기반)로 가장 오랫동안 사용되지 않은 키를 제거합니다. volatile-*는 TTL이 설정된 키만 대상으로 합니다.
- volatile-ttl: 만료 시간이 짧은 키부터 우선 삭제합니다.
- noeviction: 새로운 쓰기가 들어오면 OOM(메모리 부족) 오류를 반환합니다.
근사 LRU는 정확한 순서를 보장하지 않으므로 샘플링 결과에 따라 의도치 않게 키가 삭제될 수 있습니다. 또한 TTL 기반 정책은 만료된 키가 없으면 메모리 증가를 막지 못합니다. 따라서 읽기·쓰기 패턴과 TTL 사용을 함께 고려해 maxmemory와 정책을 설계해야 합니다. 실무 체크리스트: used_memory와 evicted_keys를 모니터링하고, TTL 전략을 점검하며, 샘플링 영향도를 테스트하세요. 특히 Redis 메모리 폭증과 eviction 정책 미스매치 사례를 염두에 두면 문제를 조기에 발견하기 쉽습니다.
미스매치 원인 분석 — 설정·데이터·운영 패턴의 상호작용
Redis의 eviction 미스매치는 단순한 정책 설정 실수로 끝나지 않는다. 설정, 데이터 특성, 운영 패턴이 복합적으로 맞물려 발생한다. 예컨대 maxmemory-policy를 volatile-*로 두더라도 대부분의 키에 TTL이 없다면 실제로는 거의 evict가 일어나지 않는다. 수백 MB에 이르는 큰 키나 대량 파이프라인·Lua 스크립트는 단일 스레드에서 일시적인 메모리 급증을 유발해, 정책이 있더라도 기대만큼 메모리가 해제되지 않는 경우가 많다. 또한 AOF/RDB 스냅샷과 rewrite 과정은 COW로 RSS를 키우고, lazyfree를 사용하지 않으면 큰 키 삭제가 블로킹되어 회복이 지연된다.
- 정책 불일치: volatile-*와 allkeys 중 선택이 실제 TTL 분포와 맞지 않음
- 데이터 특성: 수백 MB급 키, 긴 리스트·해시 집중으로 evict 후보가 부족함
- 운영 패턴: 대량 적재, 파이프라인, Lua 스크립트가 순간적 메모리 급증을 일으킴
- 퍼시스턴스 영향: AOF/RDB 재작성 시 COW와 IO로 메모리·성능 압박이 증가
- 비정형 전환 사례: 설정 변경이나 장애 복구 후 TTL·정책이 어긋나는 상황
따라서 정책을 고를 때는 TTL 전략, 키 크기 분포, 배치 처리 크기, COW 영향을 함께 검토해야 한다. 모니터링(used_memory, used_memory_rss, mem_fragmentation_ratio, eviction 관련 지표)을 통해 이상 징후를 빠르게 포착하고, lazyfree 활성화나 키 분할 등으로 실운영 충격을 줄여야 한다. 이런 점들은 Redis 메모리 폭증과 eviction 정책 미스매치 사례에서 공통적으로 관찰된다. 실무 체크리스트 예: TTL 비율과 큰 키 목록을 먼저 확인하고, 배치 처리 크기를 제한한 뒤 lazyfree 설정과 RSS/eviction 지표를 정기적으로 점검하라.
해결 과정과 즉각적 대응 방법
즉각 대응은 '메모리 완화 → 안정화 → 설정·복구' 순으로 진행한다. 먼저 영향 범위(INFO memory, connected_clients, big_keys)를 신속히 확인하고, 쓰기 트래픽을 제한해 추가 악화를 막는다. Redis 메모리 폭증과 eviction 정책 미스매치 사례에서는 이 순서가 특히 중요하다.
- 일시적 완화
- 레디스 재시작: 장애 상태를 빠르게 해소할 수 있으나, 재시작으로 인한 데이터 손실 위험을 반드시 확인한 뒤 진행한다.
- 스케일 아웃: 새 노드 추가 또는 읽기 전용 레플리카 투입으로 부하를 분산시킨다.
- 키 삭제: 대형 키는 DEL 대신 UNLINK로 비동기 삭제해 블로킹을 방지한다.
- 안전한 설정 변경 절차
- 스테이징 환경에서 maxmemory, maxmemory-policy 등 변경사항을 충분히 검증한다.
- 운영에서는 먼저 CONFIG SET으로 단계를 적용해 동작을 확인한 뒤, 문제가 없으면 CONFIG REWRITE로 영구화한다.
- 변경 전후에는 메모리 사용량과 evicted/expired 통계를 면밀히 관찰해 이상을 탐지한다.
- 복구 순서(권장)
- 우선 쓰기를 차단하고 읽기 위주로 전환한다.
- 용량 확충(스케일 아웃) 또는 대형 키 정리로 메모리 여유를 확보한다.
- 레플리카부터 순차적으로 롤링 재시작한 뒤 마스터를 재시작한다.
- 설정 영구화 후 성능과 데이터 무결성을 최종 확인한다.
모든 조치는 플레이스홀더 백업(스냅샷/AOF) 확보와 모니터링 알람을 켠 상태에서 수행한다. 실무 체크리스트 예: 1) 스냅샷/AOF 백업 완료, 2) 모니터링·알람 정상 동작 확인, 3) 변경사항은 스테이징에서 검증 후 적용.
재발 방지와 운영 가이드라인
모니터링·알림, 정책-워크로드 정합성 검증, 용량 계획·자동화·런북 정리를 중심으로, 실무에 바로 적용할 수 있는 항목들만 정리했다. 특히 Redis 메모리 폭증과 eviction 정책 미스매치 사례를 예방하는 데 초점을 맞췄다.
- 모니터링·알림:
used_memory/maxmemory비율이 80%에 도달하면 경고,evicted_keys가 증가하면 알림,memory_fragmentation_ratio가 1.5를 넘거나 RSS가 급변할 때도 경보를 설정한다. 지표는 Prometheus·Grafana로 수집하고 알림은 Slack 또는 PagerDuty에 연동한다. - 정책-워크로드 정합성 검증: TTL이 있는 캐시에는
volatile-*계열 정책을 적용하고, 무제한 키에는noeviction을 사용하지 않는다. 정기적으로 샘플 키 패턴과 TTL 분포, 접근 패턴(요청률·캐시 히트율)을 비교해 정책 불일치를 찾아낸다. - 용량 계획·자동화·런북: 평균·피크 사용량에 30%의 여유를 두고 용량을 산정한다. 오토스케일 스크립트(예: 구성 변경이나 샤딩/리샤딩 트리거)는 반드시 코드 리뷰와 권한 관리를 거쳐야 한다. 런북에는 '최초 탐지 → 임시 완화(예:
CONFIG SET maxmemory, 트래픽 셰이핑) → 영구조치(정책 수정, 노드 추가)'의 순서와 책임자, 롤백 절차를 명확히 적어 둔다. 실무 체크리스트 예: 경보 확인 → 원인 분류(정책/워크로드/버그) → 임시 완화 실행 → 근본 원인 수정.
경험에서 배운 점
Redis에서 메모리 폭증은 보통 몇 가지 단순한 설정 누락과 운영 패턴에서 발생합니다. 대표적으로 maxmemory를 설정하지 않거나(컨테이너·호스트 메모리 한계를 고려하지 않은 경우), eviction 정책이 실제 워크로드와 맞지 않아 "저장은 계속되지만 유효한 키가 없어" 메모리가 지속 증가하는 상황이 자주 발생합니다. 대형 키(예: huge lists, sets, hashes), 대량 일괄 쓰기, Lua 스크립트의 임시 버퍼, 그리고 BGSAVE/AOF rewrite 시 fork로 인한 COW 메모리 증가도 폭발의 원인이 됩니다. 이 요인들은 종종 복합적으로 작용해 단일 지표만으로는 사전 인지가 어렵습니다. Redis 메모리 폭증과 eviction 정책 미스매치 사례를 보면 운영 전반을 함께 점검해야 함을 알 수 있습니다.
실무에서는 다음 원칙을 우선 적용합니다. 첫째, 운영 환경에서는 반드시 maxmemory를 호스트(또는 컨테이너) 메모리보다 낮게 설정하고, 캐시인지 영속 데이터인지에 따라 eviction 정책을 선택합니다(예: 범용 캐시는 allkeys-lru, TTL로 관리하는 캐시는 volatile-lru). 둘째, used_memory, mem_fragmentation_ratio, evicted_keys, rejected_connections 또는 rejected_commands, instantaneous_ops 등 메모리 관련 지표를 세밀히 수집해 임계치를 정하고 알람을 구성합니다. 셋째, 대형 키와 대량 연산을 주기적으로 탐지하는 자동화를 도입합니다(MEMORY USAGE, MODULE·keyspace 검사, redis-cli --bigkeys 유사 검사). 백업이나 AOF rewrite 같은 작업은 트래픽과 메모리 상태를 고려해 스케줄링하거나 작은 인스턴스에서 실행하세요.
- 환경 설정: maxmemory를 반드시 지정하고, 호스트/컨테이너 메모리 대비 여유(예: 70~80%)를 확보하세요.
- 정책 선택: 워크로드에 맞는 eviction 정책을 적용합니다(allkeys-* vs volatile-*). 필요하면 maxmemory-samples도 조정하세요.
- 모니터링·알람: used_memory, used_memory_rss, mem_fragmentation_ratio, evicted_keys, rejected_commands 등 주요 지표에 임계치 알람을 설정합니다.
- 문제 탐지: 정기적으로 MEMORY USAGE, MEMORY STATS, --bigkeys 유사 검사를 실행하되, 서비스 영향에 주의하세요.
- 대형 연산 관리: SMEMBERS, LRANGE(대량 범위) 같은 블로킹 연산을 피하고 배치 또는 SSCAN 등 스캔 방식으로 대체합니다.
- 백업/복제: BGSAVE/AOF rewrite로 인한 COW 메모리 증가를 고려해 스케줄을 조정하고 리소스를 확보하거나 replica에서 작업하세요.
- 격리와 할당: 캐시와 영속 데이터를 분리해 별 인스턴스나 DB로 운영하고, 네임스페이스·팀 단위 용량 제한을 적용합니다.
- 운영 절차: 메모리 폭증 시 실행할 재발조치(읽기 전용 전환, 쓰기 차단, 장애 격리, 스냅샷 생성 순서 등)를 문서화한 런북을 준비하세요.
- 실무 체크리스트(간단): maxmemory 설정 여부, eviction 정책 적합성, 큰 키 존재 유무, 예정된 AOF/BGSAVE 작업, 임계치 알람 동작 확인.
댓글
댓글 쓰기