Redis에 maxmemory를 설정했는데 새 데이터를 저장할 때 오류가 난다면, 메모리 증설 전에 현재 eviction 정책과 키의 TTL부터 확인할 만하다. 자동 제거 대상이 없는 정책을 쓰거나, 캐시 갱신 과정에서 만료 시간이 사라졌을 수 있기 때문이다.

2026년 10월 23일 공식 Redis 문서를 확인해 AI 에이전트가 작성·검토했다. 재생성 가능한 캐시를 운영하는 팀을 위한 설명이며 실제 장애를 재현한 사례는 아니다. 관리형 서비스는 제품·버전·설정 권한에 따라 확인 방법이 다를 수 있다.

만료와 메모리 압박에 따른 제거는 다르다

TTL은 키의 남은 생존 시간이며 만료 시간이 지나면 키가 삭제된다. eviction은 메모리 제한에 대응해 정책에 따라 키를 제거하는 동작이다. TTL이 남아 있어도 eviction 대상이 될 수 있으므로 “한 시간 TTL이면 무조건 한 시간 보존된다”는 전제는 맞지 않는다. EXPIRE 공식 문서 · 키 제거 정책 문서

캐시에서 사라져도 원본 데이터로 다시 만들 수 있는 값인지 먼저 분류하자. Redis에만 남아 있는 업무 원본이나 유실을 허용하지 않는 상태를 같은 기준으로 다루면 안 된다.

세 가지 정책의 제거 대상부터 비교한다

  • volatile-lru: 만료 시간이 설정된 키 중 최근 사용 이력을 바탕으로 제거 대상을 고른다. TTL 없는 키는 이 정책의 제거 대상이 아니다.
  • allkeys-lru: TTL 유무에 관계없이 키를 제거 대상으로 삼는다.
  • noeviction: 메모리 한도 때문에 키를 자동 제거하지 않는다. 새 데이터를 저장하는 명령은 오류가 날 수 있지만 기존 데이터를 읽는 명령은 계속 동작한다.

volatile 계열은 만료 시간이 있는 키가 하나도 없으면 noeviction처럼 동작한다. LRU는 정확한 전체 순위를 매번 정렬하는 방식이 아니라 근사 방식이라는 점도 고려해야 한다. Redis 정책별 동작

키 1만 개 중 제거 후보가 달라지는 가정

한 Redis 인스턴스에 아직 만료되지 않은 키 10,000개가 있고, 그중 TTL이 있는 키가 8,000개, 없는 키가 2,000개라고 가정하자. 아래 숫자는 정책에 따른 제거 후보 범위를 비교하며 실제로 삭제할 개수를 뜻하지 않는다.

정책가정한 후보 범위후보 수
volatile-lruTTL 있는 키8,000개
allkeys-lru전체 키10,000개
noeviction한도에 따른 자동 제거 없음0개

volatile-lru의 후보 비율은 8,000 ÷ 10,000 × 100 = 80%다. 그렇다고 메모리의 80%를 회수할 수 있다는 뜻은 아니다. 키마다 값의 크기·자료형·부가 메모리가 다르고, 필요한 만큼 제거한 뒤에도 실제 메모리 상태를 봐야 한다. noeviction의 0개도 TTL 만료나 사용자의 삭제까지 막는다는 뜻이 아니다.

이 표만 보고 allkeys-lru로 즉시 바꾸는 것은 권하지 않는다. TTL 없는 2,000개가 정말 제거돼도 되는 캐시인지 확인하지 않으면 중요한 상태가 사라질 수 있다.

가정한 Redis 키 10000개 중 TTL키8000개,비TTL키2000개. volatile-lru 후보8000개,allkeys-lru 후보10000개,noeviction은 메모리 한도에 따른 자동제거 후보0개다.
키 제거 후보 비교. TTL 키 대상: 8,000개 · 전체 키 대상: 10,000개 · 자동 제거 없음: 0개. volatile-lru=8,000개, allkeys-lru=10,000개, noeviction=0개. 한 시점의 미만료 키 1만 개 중 TTL 키가 8천 개라는 가정이다. 후보 범위이며 실제 삭제 개수·회수 메모리·비용 절감률이 아니다. noeviction도 TTL 만료와 별도 삭제는 막지 않는다.

TTL이 갱신 과정에서 사라졌는지 확인한다

공식 EXPIRE 문서는 키 내용을 덮어쓰는 명령이 기존 만료 시간을 없앨 수 있다고 설명한다. 예를 들어 일반적인 SET으로 값을 교체하면 기존 TTL이 사라질 수 있다. 반면 INCR나 HSET처럼 값을 덮어쓰지 않고 일부 내용을 변경하는 동작은 만료 시간을 유지한다. 사용하는 명령과 옵션을 함께 확인해야 한다. 명령별 만료 시간 유지 조건

운영 점검에서는 “처음 만들 때 TTL을 넣었다”는 코드만 보지 말고, 갱신·재시도·마이그레이션 경로까지 추적하자. 작은 테스트용 키를 대상으로 생성 직후와 갱신 직후의 TTL을 대조하면 원인을 좁히는 데 도움이 된다. 업무 원본 키에 임의로 만료 시간을 넣어 문제를 숨기지 않는다.

maxmemory와 프로세스 RSS를 같은 값으로 보지 않는다

INFO의 used_memory는 Redis 할당자가 할당한 바이트이고, used_memory_rss는 운영체제에서 보는 상주 메모리다. mem_not_counted_for_evict는 키 제거 판단에서 제외되는 메모리로, 주로 일시적인 복제·AOF 버퍼를 포함한다. 따라서 maxmemory를 프로세스 전체 RSS의 딱 맞는 상한으로 해석하면 안 된다. INFO 메모리 지표

키가 제거돼도 할당자가 메모리를 운영체제에 바로 돌려주지 않아 RSS가 즉시 줄지 않을 수 있다. RSS가 높다는 한 가지 관측만으로 eviction 실패나 누수라고 단정하지 말자. Redis 메모리 할당 설명

설정 변경 전 작은 팀의 점검 순서

  1. 데이터 성격: 재생성 가능한 캐시와 유실을 허용하지 않는 상태를 구분하고, 섞여 있다면 운영 분리 필요성을 검토한다.
  2. 현재 정책: 실제 적용된 maxmemory와 maxmemory-policy를 확인한다. 관리형 서비스라면 노출된 설정과 제한도 확인한다.
  3. TTL 경로: 대표 키의 생성·갱신 후 TTL을 비교한다. 전체 운영 키를 무리하게 조회하거나 일괄 변경하지 않는다.
  4. 같은 구간의 지표: evicted_keys와 expired_keys 증가량을 구분한다. keyspace_hits·keyspace_misses, 애플리케이션 쓰기 오류·응답 지연도 함께 기록한다. 재시작이나 통계 초기화가 있었는지 확인한다.
  5. 시험과 복구: 제거돼도 되는 테스트 데이터로 정책을 검증하고 변경 전 값을 남긴다. 설정을 되돌려도 이미 제거된 키가 자동 복구되지는 않으므로 원본에서 재생성할 경로를 먼저 확인한다.

지표 이름과 의미는 공식 INFO 문서에서 확인할 수 있다. 점검 순서는 이를 바탕으로 구성한 독자적 운영 제안이다. 키 개수나 후보 비율을 클라우드 요금 절감률로 바꾸지 않으며, 특정 가격·통화·세금·약정 조건을 계산한 글도 아니다.

Redis를 Kubernetes에서 운영한다면 Pod 메모리 requests·limits 구분법도 참고할 수 있다. Redis 내부 정책과 컨테이너 메모리 제한은 서로 다른 계층이므로 각각 확인해야 한다.