Redis 메모리 폭증과 Eviction 정책 선택 가이드
문제 정의 — Redis 메모리 폭증이 운영에 미치는 영향
- 급격한 팽창: 키·값 수가 짧은 시간에 늘어나 메모리 점유가 급상승하고 RDB/AOF 스냅샷이나 동기화가 지연됩니다.
- OOM(Out Of Memory): 메모리가 한계에 이르면 Redis 프로세스가 종료되거나 커널의 OOM killer가 개입합니다.
- 지연 증가: 페이지 교체, 스왑, 블로킹 I/O로 p95/p99 응답 시간이 길어지고 처리량이 떨어집니다.
- Eviction 쓰래싱: 부적절한 정책이나 파라미터로 키 제거와 재생성이 반복되어 CPU와 네트워크 비용이 상승합니다.
원인 분석 — 메모리 폭증을 일으키는 흔한 패턴
메모리 폭증은 보통 단일 원인보다 여러 요인이 겹쳐 발생합니다. 예컨대 워크로드 변화 — 트래픽 급증이나 배치·백필(batch/backfill) 작업 — 는 키와 값의 수를 순간적으로 늘려 예기치 못한 피크로 메모리를 잠식합니다.
- 키 증가·누수: 유효기간이 설정되지 않은 고유 키(예: 요청별 임시 키)나 네임스페이스 설계 부재로 키 수가 꾸준히 증가합니다.
- TTL 미설정: 만료 시간을 지정하지 않은 캐시 항목은 계속 쌓여 캐시 효율을 떨어뜨리고 메모리를 점유합니다.
- 값 크기 변화: 이미지나 대형 배열 저장, 또는 직렬화 방식 변경으로 단건 데이터 크기가 급격히 커질 수 있습니다.
- 메모리 단편화: 작은 할당과 해제가 반복되면 단편화가 진행되어 실제 사용 가능한 메모리보다 빨리 한계에 도달할 수 있습니다.
탐지 포인트로는 키 증가율 추적, 평균값 크기 변화, INFO/MEMORY(예: used_memory, fragmentation_ratio) 지표, 그리고 AOF/RDB 쓰기 시점의 변화를 확인하세요. 실무 체크리스트 예: ① 키 증가 상위 N개 조사 ② 평균값 및 P95/P99 크기 확인 ③ 배치 작업 전후 AOF/RDB 쓰기량 비교. Redis 메모리 폭증과 eviction 정책 선택 기준을 검토할 때는 이런 탐지 포인트를 우선 확인하는 것이 좋습니다.
관찰성 및 알람 설계 — 어떤 메트릭을 어떻게 모니터링할 것인가
다음 핵심 메트릭을 기준으로 경보를 설계하라. 임계값은 운영 환경과 SLA에 맞춰 조정하되, 경보는 추세(트렌드), 급증, 그리고 지속성을 모두 반영해야 한다. 특히 Redis 메모리 폭증과 eviction 정책 선택 기준을 정할 때는 추세와 단기 스파이크를 동시에 살펴야 한다.
used_memory: 경고 = maxmemory의 70–80% 도달; 긴급 = 90% 이상이거나 단시간(5분 내) 20% 이상 급증.frag_ratio: 1.3 이상이면 경고. 지속적 상승 또는 1.5 이상일 때는 메모리 할당·단편화 원인을 조사한다.evicted_keys: 누적값이 0에 가까운 것이 정상. 초당·분 단위로 갑작스레 증가하면 즉시 긴급 알림을 발송하고 eviction 정책 불일치 여부를 확인한다.keyspace_hits/misses: miss 비율이 5–10%를 초과하거나 hit 비율이 급락하면 캐시 키 설계와 TTL 정책을 재검토한다.- 지연(
latency): p95/p99이 SLA를 초과하거나 순간적 spike가 발생하면 경고. 명령별(latency_histogram) 분석을 권장한다.
알람은 집계창(1m/5m/15m)과 반복·해제 조건을 명시하고, 각 경보마다 자동화된 진단(runbook)을 연결한다. 체크리스트 예시: 1) 현재 used_memory와 maxmemory 비교, 2) eviction 정책 확인, 3) TTL 분포 검토, 4) 네트워크 I/O 및 복제 지연 점검. 이렇게 하면 원인 파악과 복구가 빨라진다.
Eviction 정책 종류와 동작 원리 요약
- noeviction — 메모리 한계에 도달하면 쓰기 명령을 오류(OOM)로 응답합니다. 데이터 손실을 막을 수는 있지만, 애플리케이션 오류나 서비스 중단을 유발할 수 있습니다.
- allkeys-lru — 모든 키를 대상으로 가장 오랫동안 사용되지 않은 항목부터 제거합니다. 캐시 성격의 워크로드에 적합하지만, 영구 데이터가 섞인 환경에서는 중요한 항목이 먼저 삭제될 수 있습니다.
- allkeys-lfu — 사용 빈도가 낮은 키를 우선 제거합니다. 장기간 핫스팟을 유지해야 할 때 유리하나, 빈도 카운터로 인해 메모리와 CPU 오버헤드가 발생합니다.
- allkeys-random — 무작위로 키를 삭제합니다. 구현이 단순하고 CPU 부담이 적지만 캐시 히트율을 최적화하기엔 취약합니다.
- allkeys-ttl — 남은 TTL이 짧은 키부터 우선 제거합니다. 만료 기반 우선순위를 원할 때 유용합니다.
- volatile-* (lru/lfu/random/ttl) — TTL이 설정된 키만 삭제 후보로 고려합니다. 영구 데이터를 보호할 수 있지만, TTL을 잘못 설정하면 의도치 않은 데이터 손실이 발생할 수 있습니다. 실무 체크리스트: 메모리 증감 패턴, 데이터 영속성 요구, 그리고 CPU·메모리 오버헤드를 확인해 정책을 선택하세요(예: 캐시는 allkeys-lru, 장기 빈도 관리가 중요하면 allkeys-lfu).
정책 선택 기준 — 서비스 특성에 따른 의사결정 체크리스트 (Redis 메모리 폭증과 eviction 정책 선택 기준)
- 데이터 중요도 — 복구 비용이 크고 손실을 허용할 수 없다면 noeviction을 선택하고 모니터링과 알람 체계를 갖추세요. 반대로 캐시성 데이터라면 삭제를 허용하는 정책을 적용하는 것이 현실적입니다.
- 접근 패턴(Recency vs Popularity) — 최근 접근성이 핵심이면 allkeys-lru를, 장기간 누적된 인기 항목을 보존해야 하면 allkeys-lfu를 고려합니다.
- TTL 사용 가능성 — 대부분 키에 TTL을 부여할 수 있다면 volatile-ttl 또는 volatile-lru/lfu로 우선 공간을 확보하는 편이 관리가 수월합니다.
- 예측 가능성 — 접근 패턴을 예측하기 어렵다면 전역 정책(allkeys-*)이 안전합니다. 일부 키만 캐시로 운영한다면 volatile-*를 선택하세요.
- 레이턴시 요구 — 초저지연이 필수인 환경에서는 메타데이터 오버헤드가 적은 LRU 계열을 우선 검토하세요. LFU는 사용량 메타데이터 비용을 더 따져야 합니다.
- 운영 체크 — 정책 적용 후에는 OOM 발생 빈도, hit ratio, evicted 키 로그, TTL 분포 등으로 주기 검증을 실행하세요. 실무 체크리스트 예: 1) OOM/eviction 발생 여부 확인, 2) hit ratio 변화 추적, 3) 필요 시 정책·메모리 설정 조정.
운영 가이드 — 설정, 테스트, 롤아웃과 비상 대응 절차
설정(운영환경 기준): maxmemory를 현실적인 상한치로 설정하고, 액세스 패턴에 따라 eviction 정책을 선택한다. 캐시 전용이면 allkeys-lru, TTL이 많은 워크로드라면 volatile-lru를 권장한다. Redis 메모리 폭증과 eviction 정책 선택 기준을 고려해 우선순위를 정하라. 권장 설정 예시: maxmemory 16gb, maxmemory-policy allkeys-lru, maxmemory-samples 5. 실무 체크리스트 예: maxmemory 확인 → 스테이징 부하 테스트 수행 → 주요 지표 계측 및 임계값 설정 → 카나리로 점진 배포.
- 스테이징 부하 테스트: 프로덕션 트레이스를 재생하거나 합성 워크로드로 1.5–3배까지 램프업한다. 큰 키 검사는 필수(예:
redis-cli --bigkeys). - 계측·알림: 필수 지표 — used_memory, used_memory_rss, mem_fragmentation_ratio, evicted_keys, instantaneous_ops_latency. 알림 임계값 예: used_memory > 85% 또는 evicted_keys가 의미 있게 증가할 때.
- 점진적 롤아웃: 카나리(5–10%) 배포 후 30–60분 모니터링, 이후 25%로 확대하고 최종 전체 배포. 각 단계에서 eviction, latency, 오류율을 꼼꼼히 확인한다.
- 비상 대응 플레이북:
- 트래픽 분산(리드 레플리카 활용 또는 백엔드 캐시 우회).
- 신속한 eviction 정책 전환 또는 임시로 maxmemory 상향 적용.
- 큰 키 탐지 후 삭제하거나 TTL을 조정(
MEMORY USAGE key,DEL key). - 수평 확장(샤딩 또는 인스턴스 추가) 및 사후 분석(포스트모템) 실시.
경험에서 배운 점
운영 환경에서 Redis의 메모리 폭증으로 장애가 발생하는 가장 흔한 원인은 모니터링과 제한을 설정하지 않은 것, 그리고 서비스 특성에 맞지 않는 eviction 정책을 선택한 것입니다. 메모리 사용의 평균치·증가율·일시적 스파이크 같은 추세를 관찰하지 않으면 maxmemory를 넘을 때 갑작스러운 OOM이나 대량 evict로 응답 지연과 데이터 손실이 생깁니다. 또한 많은 조직이 모든 키를 동일하게 취급해 LRU·LFU를 무작정 적용하거나 TTL이 없는 중요한 데이터를 캐시처럼 다루는 실수를 반복합니다.
실무 체크리스트(간결):
- 측정: baseline 메모리, 성장률, 키 수·평균 크기, 키별 TTL 유무를 파악하고 SLI(used_memory, used_memory_rss, keyspace_hits/misses)로 알람을 설정
- 정책선택 기준: 임시 캐시이거나 재생성 가능하면 → allkeys-lru/lfu; TTL로 보호되는 항목만 보존해야 하면 → volatile-lru/lfu; 데이터 무결성이 중요하면 → eviction을 피하고 쓰기 차단이나 백프레셔 설계 고려
- 검증: maxmemory 설정 후 스테이징에서 실제 패턴으로 스파이크와 장기 부하를 시뮬레이션해 evict 로그와 지연 시간을 확인
- 운영기술: 중요한 키는 네임스페이스나 태깅으로 식별해 보호하고, 대형 객체는 분해하거나 외부 스토리지로 이전. 모니터(메트릭·알람·자동 스케일 트리거)를 준비
- 사례: 세션 테이블이 TTL 없이 축적되어 OOM이 발생한 사례가 있었음 — 네임스페이스별 TTL 정책 적용과 알람으로 문제를 방지함
재발 방지 팁: eviction 정책 자체보다 사전 검증과 지속적 모니터링이 더 중요합니다. maxmemory와 적절한 eviction 정책을 함께 설정하고, 선택 이유를 문서화하세요. 메모리 급증 시 자동으로 쓰기를 제어하는 회로차단(runbook)과 알람을 준비해야 합니다. 정책을 고를 때는 데이터 복구 가능성(재생성 가능 vs 영속성 필요), 접근 패턴(최근성 vs 빈도), 운영 리스크(예기치 않은 대량 evict로 인한 지연)를 우선 기준으로 삼고, 스테이징 검증·지속 모니터링·정기 리밸런싱 절차를 운영하면 재발 가능성을 크게 줄일 수 있습니다. 필요하면 'Redis 메모리 폭증과 eviction 정책 선택 기준'을 팀 내부 가이드로 정리해 공유하세요.
댓글
댓글 쓰기