홈/인프라/Redis OOM 에러(used memory > maxmemory) 5분 응급처치 가이드
인프라Redis OOMmaxmemory

Redis OOM 에러(used memory > maxmemory) 5분 응급처치 가이드

Redis "OOM command not allowed when used memory > maxmemory" 에러를 INFO memory 진단부터 maxmemory 증설, allkeys-lru eviction 정책, TTL 재발 방지까지 복붙 명령어로 단계별 해결합니다.

Redis OOM 에러(used memory > maxmemory) 5분 응급처치 가이드
목차
  1. 1. 30초 현황 파악: INFO memory 읽는 법
  2. 2. 즉시 복구: maxmemory 조정과 정책 선택
  3. 3. 원인 진단: OOM을 부르는 5가지 시나리오
  4. 4. 재발 방지 체크리스트
  5. 참고: 공식 문서
  6. 자주 묻는 질문 (FAQ)
  7. 출처 · 확인일 2026-10-04

Redis OOM 에러(used memory > maxmemory) 5분 응급처치 완벽 가이드

배포도 안 했는데 갑자기 운영 로그에 이런 메시지가 도배되기 시작합니다.

CODE
(error) OOM command not allowed when used memory > 'maxmemory'.

읽기는 되는데 SET, INCR, LPUSH 같은 쓰기 명령만 전부 거부되는 상황. 세션 저장소나 캐시로 Redis를 쓰고 있다면 그대로 서비스 장애로 직결됩니다. 이 글은 "지금 장애 중"인 분을 위해 응급 처치를 앞에, 원인 분석을 뒤에 배치했습니다. 아래 로드맵대로 따라오면 5분 안에 쓰기를 복구할 수 있습니다.

CODE
[1] INFO memory 로 현황 파악 (30초)
[2] maxmemory 늘리거나 / eviction 정책 바꿔 즉시 복구 (1분)
[3] CONFIG REWRITE 로 영구 저장 (10초)
[4] TTL · 모니터링으로 재발 방지 (이후)

1. 30초 현황 파악: INFO memory 읽는 법

가장 먼저 지금 Redis가 어떤 상태인지 봐야 합니다.

Bash
redis-cli INFO memory
CODE
# Memory
used_memory:2147483648
used_memory_human:2.00G
used_memory_rss:2415919104
used_memory_rss_human:2.25G
maxmemory:2147483648
maxmemory_human:2.00G
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.12
mem_allocator:jemalloc-5.3.0

핵심 지표 4개만 봅니다.

지표의미판별 기준
used_memoryRedis가 논리적으로 쓰는 메모리maxmemory에 근접/도달하면 위험
used_memory_rssOS가 실제로 점유한 물리 메모리(RSS)used_memory보다 과도하게 크면 단편화
mem_fragmentation_ratiorss ÷ used_memory1.0~1.4 정상 / 1.5↑ 단편화 / 1.0 미만 스왑 의심
maxmemory_policy한계 도달 시 동작noeviction이면 쓰기 거부의 직접 원인

위 예시는 used_memory == maxmemory이고 정책이 noeviction입니다. 즉, 메모리가 꽉 찼고 비울 정책도 없으니 쓰기를 거부하는 전형적 상황입니다.

보조 명령도 알아두면 좋습니다.

Bash
redis-cli MEMORY DOCTOR          # Redis가 직접 진단 코멘트를 줌
redis-cli MEMORY STATS           # peak.allocated, dataset.bytes, overhead.total 등 상세 분해
redis-cli --memkeys              # 메모리를 가장 많이 쓰는 키 샘플링 (redis-cli 6.2+)
redis-cli MEMORY USAGE mykey     # 특정 키가 차지하는 바이트

2. 즉시 복구: maxmemory 조정과 정책 선택

상황은 둘 중 하나입니다. (A) 메모리를 더 줄 수 있다 또는 (B) 캐시라서 일부 버려도 된다.

(A) 메모리 여유가 있으면 한계만 올린다

서버 RAM에 여유가 있다면 maxmemory를 무중단으로 늘립니다.

Bash
redis-cli CONFIG SET maxmemory 4gb

이 명령은 즉시 적용되고, 직후부터 쓰기가 다시 동작합니다.

💡 컨테이너 환경 주의: 도커/쿠버네티스에서 maxmemory를 0(기본값, 64비트에서는 제한 없음)으로 두면 Redis는 이 OOM 에러를 내지 않고 계속 메모리를 쓰다가, 컨테이너 메모리 limit에 닿는 순간 커널이 컨테이너를 OOMKill합니다. 증상이 전혀 다르니 컨테이너에서는 limit보다 충분히 낮게 maxmemory를 명시하세요(fork·버퍼 여유 확보).

(B) 순수 캐시라면 eviction 정책을 켠다

캐시 용도인데 noeviction으로 운영했다면 이게 근본 문제입니다. LRU 기반으로 오래된 키를 자동으로 밀어내게 합니다.

Bash
redis-cli CONFIG SET maxmemory-policy allkeys-lru

정책을 바꾸는 순간 한계 초과분이 evict되며 쓰기가 즉시 복구됩니다.

maxmemory-policy 비교표

상황에 맞는 정책을 고르는 것이 핵심입니다. Redis 8.6부터는 쓰기 시점만 기준으로 삼는 LRM 정책 2개가 추가되어 공식 문서 기준 10종입니다(Redis 8.6 미만과 Valkey에는 LRM이 없습니다).

정책동작대상 키캐시용세션·영속용
noeviction한계 도달 시 쓰기 거부(에러)-✕◎(증설 전제)
allkeys-lru가장 오래 안 쓴 키 제거전체◎△
allkeys-lfu가장 적게 쓰인 키 제거전체◎△
allkeys-lrm가장 오래 수정되지 않은 키 제거(Redis 8.6+)전체○(읽기 위주)△
volatile-lruTTL 있는 키 중 LRUTTL 키만○○
volatile-lfuTTL 있는 키 중 LFUTTL 키만○○
volatile-lrmTTL 있는 키 중 LRM(Redis 8.6+)TTL 키만○○
allkeys-random무작위 제거전체△✕
volatile-randomTTL 키 중 무작위TTL 키만△△
volatile-ttl만료 임박 키 우선 제거TTL 키만○◎(TTL 혼재)

선택 가이드

  • 순수 캐시: allkeys-lru 또는 접근 빈도 편차가 큰 경우 allkeys-lfu
  • TTL 키와 영속 키가 섞인 환경: volatile-ttl 또는 volatile-lru (TTL 없는 키는 보호됨)
  • 데이터 유실이 절대 불가(세션·큐·영속 저장): noeviction 유지 + 메모리 증설이 정답. 정책으로 버티려 하지 마세요.

영구 저장

CONFIG SET은 재시작하면 사라집니다. 반드시 설정 파일에 반영합니다.

Bash
redis-cli CONFIG REWRITE

⚠️ CONFIG REWRITE는 Redis가 redis.conf를 직접 다시 씁니다. 손으로 단 주석이나 정리가 바뀔 수 있으니, Ansible·Helm 등으로 설정을 관리한다면 소스 설정을 고쳐 재배포하는 편이 안전합니다.

또는 redis.conf를 직접 수정해 둡니다.

Config
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 5

maxmemory-samples는 LRU/LFU가 제거 후보를 고를 때 표본 수입니다. 기본 5면 충분하고, 정밀도를 높이려면 10까지 올릴 수 있지만 CPU를 더 씁니다.

3. 원인 진단: OOM을 부르는 5가지 시나리오

복구했다면 이제 왜 터졌는지 봅니다. 증상→원인→확인 순서로 정리합니다.

① maxmemory 한계 도달

  • 증상: used_memory ≈ maxmemory, 쓰기 전면 거부
  • 원인: 데이터 증가량이 할당 메모리를 초과
  • 확인: INFO memory에서 두 값 비교

② 정책이 noeviction

  • 증상: 캐시인데도 키를 안 버리고 에러만 냄
  • 원인: 기본값 noeviction을 캐시에 그대로 사용
  • 확인: CONFIG GET maxmemory-policy

③ 메모리 단편화로 서버 메모리 부족

  • 증상: Redis의 OOM 에러는 없는데 서버 스왑이나 커널 OOMKill이 발생 (Redis의 OOM 에러는 used_memory 기준이라 단편화만으로는 나지 않음)
  • 원인: 잦은 키 생성/삭제로 할당자 단편화, RSS가 부풀어 OS 메모리 압박
  • 확인: mem_fragmentation_ratio 1.5 이상

④ RDB/AOF rewrite의 fork(COW) 압박

  • 증상: BGSAVE/AOF rewrite 시점에 메모리 급증, fork 실패 로그
  • 원인: fork 시 Copy-On-Write로 쓰기가 많으면 부모 메모리가 복제됨. 최악엔 2배까지 순간 점유
  • 확인: 로그의 Can't save in background: fork: Cannot allocate memory, INFO persistence의 rdb_last_bgsave_status

⑤ 키에 TTL 미설정으로 무한 누적

  • 증상: 시간이 갈수록 used_memory가 단조 증가
  • 원인: 캐시인데 만료를 안 걸어 영원히 살아있는 키
  • 확인: redis-cli --bigkeys, DBSIZE 추세 관찰

TTL 없는 키는 KEYS * 대신 SCAN으로 확인합니다. KEYS는 키 전체를 한 번에 훑어 다른 명령을 막습니다.

Bash
redis-cli --scan --pattern 'cache:*' --count 1000 | head -n 100   # 커서 기반 순회
redis-cli TTL cache:user:99      # -1이면 만료 없음, -2면 키 없음

실무 경험담: 실무에서 가장 자주 보고되는 원인은 ⑤번, TTL 누락입니다. 코드 리뷰에서 "이 SET에 EX 빠졌어요" 한 줄이면 막을 일을, 몇 달 뒤 새벽 장애로 되갚는 경우가 많습니다. 정책 튜닝보다 TTL 컨벤션 강제가 비용 대비 효과가 가장 큽니다.

4. 재발 방지 체크리스트

캐시 키엔 무조건 TTL을 건다. 쓰기 시점에 만료를 함께 지정하세요.

Bash
SET session:1234 "payload" EX 3600     # 1시간
SETEX cache:user:99 600 "..."          # 10분

단편화 대응. Redis 4.0+의 활성 디프래그를 켭니다. Redis에 포함된 jemalloc으로 빌드된 경우에만 동작하므로 INFO memory의 mem_allocator가 jemalloc인지 먼저 확인하세요.

Bash
redis-cli CONFIG SET activedefrag yes

단편화가 심해 RSS가 안 빠지면 마지막 수단으로 재시작 시 RSS가 회수됩니다(단, 데이터 영속화 후 진행).

모니터링 알람. redis_exporter + Prometheus + Grafana로 메모리 사용률 80%에서 알람을 겁니다.

YAML
groups:
  - name: redis-memory
    rules:
      - alert: RedisMemoryHigh
        expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.8
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis used_memory가 maxmemory의 80%를 초과했습니다"

이 알람 하나면 한계 도달 전에 증설·정리 시간을 벌 수 있습니다.

용량 산정 팁. 운영 데이터 기준 used_memory_rss에 fork/COW 여유로 1.3~1.5배를 곱해 maxmemory와 서버 RAM을 잡으세요. RDB를 쓴다면 더 보수적으로.

Redis 7.x에서는 maxmemory-clients로 클라이언트 버퍼까지 제한할 수 있습니다. 라이선스는 공식 라이선스 페이지 기준으로 7.2 이하 BSD-3, 7.4부터 RSALv2/SSPLv1(2024년 3월 변경), 8.0부터 AGPLv3가 선택지로 추가되었습니다. 이 과정에서 Valkey로 옮긴 팀도 있는데, Valkey 문서의 maxmemory 정책 8종과 명령은 이 글의 내용과 같습니다(LRM 정책 제외).

참고: 공식 문서

이 글에서 다루는 동작·설정·에러의 1차 출처는 다음 공식 문서입니다. 버전별 옵션과 정확한 동작은 여기서 확인하세요.

자주 묻는 질문 (FAQ)

Q. CONFIG SET maxmemory-policy를 바꾸면 데이터가 즉시 삭제되나요? A. 정책을 evict 계열로 바꾸고 used_memory가 maxmemory를 초과한 상태라면, 초과분만큼 키가 즉시 제거됩니다. TTL 없는 영속 데이터가 있다면 allkeys-* 대신 volatile-*를 쓰거나 maxmemory를 먼저 늘리세요.

Q. CONFIG SET으로 바꿨는데 재시작하면 원래대로 돌아갑니다. A. CONFIG SET은 메모리상 설정만 바꿉니다. redis-cli CONFIG REWRITE로 redis.conf에 반영하거나, 설정 파일을 직접 수정해야 재시작 후에도 유지됩니다.

Q. used_memory는 여유가 있는데 서버 메모리가 부족해지거나 OOMKill이 납니다. 왜죠? A. Redis의 OOM command not allowed 에러는 used_memory가 maxmemory를 넘을 때만 나므로, 이 경우는 Redis 밖의 메모리 압박입니다. mem_fragmentation_ratio를 확인하세요. 1.5 이상이면 단편화로 RSS가 부풀어 OS 메모리가 부족한 상태입니다. activedefrag yes를 켜거나, 영속화 후 재시작으로 RSS를 회수하면 해결됩니다.

출처 · 확인일 2026-10-04

확인 정보
✦ ✦ ✦
출처·검증 안내

글마다 출처와 확인 범위가 다릅니다. 아래에 확인일·확인 범위·출처가 기록된 글만 그 범위에서 확인된 것입니다. 기록이 없는 글은 적용 전 사용 중인 버전의 공식 문서로 직접 확인하고, 오류는 이메일로 알려주세요. 편집 정책 · 이메일로 제보

이 글에는 사람이 확인한 날짜·범위 기록이 아직 없습니다.

발행 · ·업데이트 ·
주제 관련 공식 문서(자동 연결 · 문장별 근거 아님)Redis 공식 문서 ↗

댓글

첫 번째 댓글을 남겨보세요.