567. 레디스 만료 데이터 키 삭제 정책 (Eviction Policy)

⚠️ 이 문서는 한정된 크기의 메인 메모리(RAM)를 사용하는 인 메모리 캐시 시스템(Redis 등)에서, **메모리가 100% 꽉 찼을 때 시스템 붕괴를 막고 새로운 데이터를 받아들이기 위해 기존 데이터 중 어떤 것을 골라 강제로 삭제(방 빼기)할 것인지 결정하는 '메모리 교체(Eviction) 알고리즘'**을 다룹니다.

핵심 인사이트 (3줄 요약)

  1. 본질: 디스크가 아닌 비싼 RAM을 창고로 쓰기 때문에 용량 한계에 직면하는 것은 숙명이다. 메모리가 가득 찼을 때 발생하는 'OOM(Out Of Memory)' 에러를 피하기 위한 자동 청소 규칙이다.
  2. 가치: 캐시의 본질인 '자주 찾는 데이터를 빠르게'라는 목적에 맞게, 앞으로 가장 안 찾을 것 같은 쓰레기 데이터를 똑똑하게 예측하여 버림으로써 캐시 적중률(Cache Hit Ratio)을 극대화한다.
  3. 기술 체계: 가장 오랫동안 안 쓴 것을 버리는 LRU, 가장 적게 쓴 것을 버리는 LFU, 유통기한(TTL)이 임박한 것을 버리는 Volatile, 그리고 무작위로 버리는 Random 등 비즈니스 성격에 맞는 6가지 정책(Maxmemory-policy)을 선택해야 한다.

Ⅰ. 메모리 한계와 OOM의 공포

레디스는 마법의 주머니가 아니다. 가득 차면 누군가 희생해야 한다.

  1. Maxmemory 설정의 중요성:
    • Redis를 설치하고 메모리 제한(maxmemory)을 설정하지 않으면, 서버의 전체 물리적 RAM을 다 잡아먹다가 OS가 Redis 프로세스를 강제 종료(OOM Killer)시켜 버린다. 보통 전체 RAM의 60~70%로 설정한다.
  2. 가득 찼을 때의 딜레마:
    • 메모리가 꽉 찼는데 클라이언트가 새로운 데이터(예: SET key value)를 쓰려고 한다.
    • 방을 비워주지 않으면 에러(OOM command not allowed)를 뱉어내고 멈춘다(NoEviction 정책). 시스템을 멈추지 않으려면 캐시 엔진이 자체 판단하에 낡은 데이터를 골라서 가차 없이 버려야 한다.

📢 섹션 요약 비유: 작은 옷장(캐시 메모리)에 옷을 꽉 채워 넣었는데, 오늘 쇼핑해서 새 옷(새 데이터)을 하나 샀습니다. 옷장이 터지는 것을 막으려면 반드시 안 입는 헌 옷 하나를 끄집어내 의류 수거함에 버려야만 새 옷을 걸어둘 수 있습니다. 어떤 옷을 버릴지 결정하는 규칙이 바로 Eviction Policy입니다.


Ⅱ. 대세 알고리즘: LRU vs LFU

가장 널리 쓰이는 두 가지 천재적인 예측 방법이다.

  1. LRU (Least Recently Used - 가장 오래전에 사용된 것):
    • **"최근에 안 입은 옷은 앞으로도 안 입을 것이다"**라는 철학.
    • 각 데이터가 마지막으로 조회된 시간(Timestamp)을 기록해 둔다. 메모리가 꽉 차면, 마지막으로 본 지 가장 오래된(가장 옛날에 본) 데이터를 쫓아낸다.
    • 장점: 쇼핑몰 최신 상품이나 최근 뉴스 기사처럼, 트렌드(시간)에 민감하게 소비되는 데이터를 캐싱할 때 가장 이상적인 표준 정책이다 (allkeys-lru).
  2. LFU (Least Frequently Used - 가장 적게 사용된 것):
    • **"한 번 반짝 입고 안 입는 옷보다는, 꾸준히 일주일에 두세 번 입는 낡은 옷을 남기자"**라는 철학. (Redis 4.0 도입)
    • 데이터가 조회될 때마다 조회수(Frequency Counter)를 올린다. 메모리가 차면 누적 조회수가 가장 낮은 데이터를 쫓아낸다.
    • 장점: 시간이 지났어도 1년 내내 꾸준히 찾는 '회사 로고 이미지', '스테디셀러 상품' 같은 캐시를 절대 지우지 않고 방어해 낸다.

📢 섹션 요약 비유: LRU는 "이 겨울 코트 마지막으로 입은 게 5년 전 겨울이네? 버려!"라고 '시간'을 기준으로 버리는 것이고, LFU는 "이 후드티는 5년 전에 샀지만 한 달에 10번씩 입는 최애템이니까 남기고, 어제 샀는데 1번 입은 불편한 옷을 버려!"라고 '활용 빈도수'를 기준으로 버리는 차이입니다.


Ⅲ. 휘발성(Volatile) 튜닝과 Random의 활용

어떤 데이터를 대상으로 규칙을 적용할 것인가?

  1. Allkeys vs Volatile:
    • Allkeys: 캐시에 들어있는 '모든' 데이터를 대상으로 LRU나 LFU를 가차 없이 적용한다. 보통 캐시 전용 서버로 쓸 때 세팅한다.
    • Volatile: 개발자가 명시적으로 만료 시간(TTL)을 세팅해 둔 데이터들 사이에서만 버릴 놈을 고른다. 영구 보관용(TTL 없음) 데이터는 절대 건드리지 않고 보호한다.
  2. Volatile-TTL 정책:
    • 어차피 버릴 거라면, 유통기한(TTL)이 가장 적게 남은(곧 자연사할) 놈부터 먼저 등 떠밀어 쫓아내는 가장 합리적인 방식이다.
  3. Random (무작위 추출):
    • 가장 오래된 것을 찾는 연산(CPU/메모리 오버헤드)조차 아깝고, 데이터의 중요도가 모두 똑같아서 아무거나 버려도 상관없을 때 쓴다. 무식하지만 속도는 제일 빠르다.

📢 섹션 요약 비유: Allkeys는 옷장의 모든 옷(속옷, 양복 포함)을 대상으로 버릴 것을 찾는 무자비한 방식이고, Volatile은 처음부터 "이 옷은 버려도 됨(TTL)"이라고 태그가 붙은 옷들 안에서만 버릴 것을 고르는 방식입니다. Random은 눈 감고 옷장에 손을 넣어 아무거나 잡히는 대로 쓰레기통에 던져버리는 극단적 귀차니즘 방식입니다.