567. 레디스 만료 데이터 키 삭제 정책 (Eviction Policy)
⚠️ 이 문서는 한정된 크기의 메인 메모리(RAM)를 사용하는 인 메모리 캐시 시스템(Redis 등)에서, **메모리가 100% 꽉 찼을 때 시스템 붕괴를 막고 새로운 데이터를 받아들이기 위해 기존 데이터 중 어떤 것을 골라 강제로 삭제(방 빼기)할 것인지 결정하는 '메모리 교체(Eviction) 알고리즘'**을 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 디스크가 아닌 비싼 RAM을 창고로 쓰기 때문에 용량 한계에 직면하는 것은 숙명이다. 메모리가 가득 찼을 때 발생하는 'OOM(Out Of Memory)' 에러를 피하기 위한 자동 청소 규칙이다.
- 가치: 캐시의 본질인 '자주 찾는 데이터를 빠르게'라는 목적에 맞게, 앞으로 가장 안 찾을 것 같은 쓰레기 데이터를 똑똑하게 예측하여 버림으로써 캐시 적중률(Cache Hit Ratio)을 극대화한다.
- 기술 체계: 가장 오랫동안 안 쓴 것을 버리는 LRU, 가장 적게 쓴 것을 버리는 LFU, 유통기한(TTL)이 임박한 것을 버리는 Volatile, 그리고 무작위로 버리는 Random 등 비즈니스 성격에 맞는 6가지 정책(Maxmemory-policy)을 선택해야 한다.
Ⅰ. 메모리 한계와 OOM의 공포
레디스는 마법의 주머니가 아니다. 가득 차면 누군가 희생해야 한다.
- Maxmemory 설정의 중요성:
- Redis를 설치하고 메모리 제한(
maxmemory)을 설정하지 않으면, 서버의 전체 물리적 RAM을 다 잡아먹다가 OS가 Redis 프로세스를 강제 종료(OOM Killer)시켜 버린다. 보통 전체 RAM의 60~70%로 설정한다.
- Redis를 설치하고 메모리 제한(
- 가득 찼을 때의 딜레마:
- 메모리가 꽉 찼는데 클라이언트가 새로운 데이터(예:
SET key value)를 쓰려고 한다. - 방을 비워주지 않으면 에러(
OOM command not allowed)를 뱉어내고 멈춘다(NoEviction 정책). 시스템을 멈추지 않으려면 캐시 엔진이 자체 판단하에 낡은 데이터를 골라서 가차 없이 버려야 한다.
- 메모리가 꽉 찼는데 클라이언트가 새로운 데이터(예:
📢 섹션 요약 비유: 작은 옷장(캐시 메모리)에 옷을 꽉 채워 넣었는데, 오늘 쇼핑해서 새 옷(새 데이터)을 하나 샀습니다. 옷장이 터지는 것을 막으려면 반드시 안 입는 헌 옷 하나를 끄집어내 의류 수거함에 버려야만 새 옷을 걸어둘 수 있습니다. 어떤 옷을 버릴지 결정하는 규칙이 바로 Eviction Policy입니다.
Ⅱ. 대세 알고리즘: LRU vs LFU
가장 널리 쓰이는 두 가지 천재적인 예측 방법이다.
- LRU (Least Recently Used - 가장 오래전에 사용된 것):
- **"최근에 안 입은 옷은 앞으로도 안 입을 것이다"**라는 철학.
- 각 데이터가 마지막으로 조회된 시간(Timestamp)을 기록해 둔다. 메모리가 꽉 차면, 마지막으로 본 지 가장 오래된(가장 옛날에 본) 데이터를 쫓아낸다.
- 장점: 쇼핑몰 최신 상품이나 최근 뉴스 기사처럼, 트렌드(시간)에 민감하게 소비되는 데이터를 캐싱할 때 가장 이상적인 표준 정책이다 (
allkeys-lru).
- LFU (Least Frequently Used - 가장 적게 사용된 것):
- **"한 번 반짝 입고 안 입는 옷보다는, 꾸준히 일주일에 두세 번 입는 낡은 옷을 남기자"**라는 철학. (Redis 4.0 도입)
- 데이터가 조회될 때마다 조회수(Frequency Counter)를 올린다. 메모리가 차면 누적 조회수가 가장 낮은 데이터를 쫓아낸다.
- 장점: 시간이 지났어도 1년 내내 꾸준히 찾는 '회사 로고 이미지', '스테디셀러 상품' 같은 캐시를 절대 지우지 않고 방어해 낸다.
📢 섹션 요약 비유: LRU는 "이 겨울 코트 마지막으로 입은 게 5년 전 겨울이네? 버려!"라고 '시간'을 기준으로 버리는 것이고, LFU는 "이 후드티는 5년 전에 샀지만 한 달에 10번씩 입는 최애템이니까 남기고, 어제 샀는데 1번 입은 불편한 옷을 버려!"라고 '활용 빈도수'를 기준으로 버리는 차이입니다.
Ⅲ. 휘발성(Volatile) 튜닝과 Random의 활용
어떤 데이터를 대상으로 규칙을 적용할 것인가?
- Allkeys vs Volatile:
- Allkeys: 캐시에 들어있는 '모든' 데이터를 대상으로 LRU나 LFU를 가차 없이 적용한다. 보통 캐시 전용 서버로 쓸 때 세팅한다.
- Volatile: 개발자가 명시적으로 만료 시간(TTL)을 세팅해 둔 데이터들 사이에서만 버릴 놈을 고른다. 영구 보관용(TTL 없음) 데이터는 절대 건드리지 않고 보호한다.
- Volatile-TTL 정책:
- 어차피 버릴 거라면, 유통기한(TTL)이 가장 적게 남은(곧 자연사할) 놈부터 먼저 등 떠밀어 쫓아내는 가장 합리적인 방식이다.
- Random (무작위 추출):
- 가장 오래된 것을 찾는 연산(CPU/메모리 오버헤드)조차 아깝고, 데이터의 중요도가 모두 똑같아서 아무거나 버려도 상관없을 때 쓴다. 무식하지만 속도는 제일 빠르다.
📢 섹션 요약 비유: Allkeys는 옷장의 모든 옷(속옷, 양복 포함)을 대상으로 버릴 것을 찾는 무자비한 방식이고, Volatile은 처음부터 "이 옷은 버려도 됨(TTL)"이라고 태그가 붙은 옷들 안에서만 버릴 것을 고르는 방식입니다. Random은 눈 감고 옷장에 손을 넣어 아무거나 잡히는 대로 쓰레기통에 던져버리는 극단적 귀차니즘 방식입니다.