본문으로 건너뛰기
개발 머꼬
개발 노트Redis
hohyeon.dev24

Redis 메모리가 가득 찼는데 계속 정상 동작한 것처럼 보인 이유

  • #DevOps
  • #Engineering Note
  • #Redis

문제 발생

세션 정보를 Redis에 저장하고 있었는데, 특정 시점부터 사용자들이 로그인 상태를 잃어버리는 문제가 간헐적으로 발생했습니다. 에러 로그는 없었습니다.

원인 분석

Redis에는 maxmemory-policy라는 설정이 있습니다. 메모리가 maxmemory로 설정한 한도에 도달했을 때 어떻게 동작할지를 정하는데, 기본값(또는 흔히 설정하는 값 중 하나)이 **allkeys-lru**나 유사한 정책이면, 메모리가 가득 찼을 때 가장 오래 안 쓰인 키를 자동으로 삭제하고 새 쓰기를 계속 허용합니다.

이건 "캐시"로 쓸 때는 합리적인 동작입니다 — 캐시는 원본이 따로 있고, 지워지면 다시 채우면 그만입니다. 하지만 세션 데이터처럼 Redis가 유일한 원본인 데이터를 이 정책으로 저장하면, 메모리 압박 상황에서 실제로 필요한 데이터(로그인된 세션)가 조용히 지워질 수 있습니다 — 에러 없이, 그냥 그 키가 없어진 것처럼 동작합니다. 정확히 세션이 사라지는 이번 문제입니다.

해결 방안

  1. Redis를 순수 캐시로만 쓰는지, 아니면 유일한 데이터 저장소로도 쓰는지부터 구분합니다. 이 판단이 정책 선택의 기준입니다.
  2. 순수 캐시 용도라면 allkeys-lru(또는 allkeys-lfu)가 적절합니다 — 메모리가 부족하면 자동으로 오래된 캐시를 비워가며 계속 동작합니다.
  3. 삭제되면 안 되는 데이터(세션, 큐, 진짜 저장소로 쓰는 데이터)라면 noeviction으로 설정합니다 — 이 정책은 메모리가 가득 차면 새로운 쓰기 요청을 에러로 거부합니다. 조용히 데이터를 지우는 대신 명시적인 에러를 내므로, 문제를 훨씬 빨리 발견할 수 있습니다.
# redis.conf
maxmemory 2gb
maxmemory-policy noeviction
  1. noeviction으로 바꾸면 메모리 부족 자체는 해결되지 않으므로, 실제 메모리 사용량을 모니터링하고 필요하면 maxmemory를 늘리거나 데이터의 TTL(만료 시간)을 적절히 설정해 오래된 데이터가 자연스럽게 정리되도록 설계해야 합니다.
  2. 세션처럼 원래 유효기간이 있는 데이터는 애초에 EXPIRE로 TTL을 명시적으로 설정하는 것이 정책과 무관하게 항상 필요한 안전장치입니다 — 로그아웃하지 않은 세션이 영원히 쌓이는 것 자체가 메모리 압박의 근본 원인이 될 수 있습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.