Foundry
캐시/Redis
기초
핵심

캐시 교체 정책 (LRU/LFU)

메모리가 꽉 찼을 때 무엇을 먼저 버릴 것인가

캐시 교체 정책

주요 정책

정책버리는 대상잘 맞는 상황
LRU가장 오래 안 쓴 키최근 접근이 재접근을 예측할 때
LFU가장 드물게 쓴 키인기 키가 꾸준히 고정적일 때
Random무작위접근 빈도가 대체로 균등할 때
TTL 우선남은 TTL이 짧은 키만료 후보를 직접 관리할 때

Redis 설정

maxmemory 4gb
maxmemory-policy allkeys-lru
  • allkeys-*: 모든 키가 제거 후보
  • volatile-*: TTL이 설정된 키만 후보 (해당 키가 없으면 쓰기가 오류)
  • noeviction: 제거하지 않고 쓰기 명령에 오류를 반환

실무 포인트

  • Redis의 LRU/LFU는 정확한 구현이 아니라 표본 기반 근사다(maxmemory-samples). 실무 체감 차이는 작다
  • 캐시 전용 인스턴스에 noeviction을 두면 메모리가 차는 순간 쓰기가 실패한다
  • 캐시와 영구 보관 키를 한 인스턴스에 섞지 않는다. 섞으면 지워지면 안 되는 키가 제거될 수 있다
  • evicted_keys가 계속 늘면 메모리 증설 또는 TTL 단축을 검토한다
면접에서 이렇게 나옵니다

Q.LRU와 LFU의 차이는 무엇이고 어떤 상황에 각각 유리한가요?

최근성을 보는지 빈도를 보는지가 다릅니다.

항목LRULFU
기준가장 오래 안 쓴 것을 버린다가장 적게 쓴 것을 버린다
잘 맞는 경우최근 접근이 곧 다시 올 때인기 항목이 꾸준할 때
약점한 번 훑고 지나가는 조회에 캐시가 밀린다옛 인기 항목이 계속 남는다

각자 불리한 상황을 구체적으로 보면 이렇습니다.

정책불리한 상황
LRU배치가 전체 데이터를 한 번 스캔하면 캐시가 전부 교체된다
LFU지난달 인기 상품이 이번 달에도 자리를 차지한다

LFU 의 문제를 줄이려고 시간이 지나면 횟수를 감쇠시키는 방식을 씁니다.

흔한 실수: 둘 중 하나를 고르는 문제로 보는 것. Redis 의 LFU 는 감쇠를 포함하고, 리눅스 페이지 캐시는 최근성과 빈도를 함께 봅니다. 실제 구현은 대개 혼합입니다.

Q.Redis에서 maxmemory-policy를 어떻게 정하나요?

캐시 전용인지, 잃으면 안 되는 데이터가 섞여 있는지로 갈립니다.

정책동작언제
noeviction쓰기를 거부한다캐시가 아니라 저장소로 쓸 때
allkeys-lru모든 키 중 오래 안 쓴 것순수 캐시. 가장 흔하다
allkeys-lfu모든 키 중 적게 쓴 것인기 편중이 뚜렷할 때
volatile-lru만료가 설정된 키만 대상캐시와 영속 데이터가 섞여 있을 때
allkeys-random무작위접근 패턴이 고를 때. 계산이 가장 싸다

기본값은 noeviction 입니다. 캐시로 쓰면서 이 값을 그대로 두면 메모리가 차는 순간 쓰기가 전부 실패합니다.

흔한 실수: 캐시 용도인데 기본값을 그대로 두는 것. 배포 후 며칠 뒤 메모리가 차면서 갑자기 쓰기 오류가 터집니다. 캐시로 쓸 것이면 명시적으로 축출 정책을 정해야 합니다.

Q.volatile-lru를 쓸 때 주의할 점은?

만료가 설정된 키만 축출 대상이라, 만료 없는 키가 쌓이면 축출할 것이 없어집니다.

상황결과
만료 있는 키가 충분하다정상 동작
만료 없는 키가 메모리를 채웠다축출할 대상이 없어 쓰기가 거부된다

이 정책을 쓰는 이유는 캐시와 영속 데이터를 한 인스턴스에 섞어 두었을 때 영속 데이터가 지워지는 것을 막기 위해서입니다. 목적은 맞지만 전제가 있습니다. 캐시 키에 반드시 만료를 걸어야 합니다.

점검할 것입니다.

확인방법
만료 없는 키 비율샘플링해 확인한다
축출 실패쓰기 오류와 메모리 상한 도달을 함께 본다
분리 검토캐시와 영속 데이터를 다른 인스턴스로 나누는 것이 근본

흔한 실수: 만료를 빠뜨린 캐시 키가 생기는 것. 코드 경로마다 만료 설정을 반복하면 놓치기 쉬우니, 캐시 접근을 감싸는 함수에서 만료를 필수 인자로 만드는 편이 안전합니다.

Q.캐시 메모리가 부족하다는 신호를 어떤 지표로 판단하나요?

지표부족 신호
축출 건수0 이 아니고 계속 늘어난다
사용 메모리상한에 붙어 있다
히트율떨어진다. 담기 전에 밀려나기 때문
평균 TTL 잔여만료 전에 축출되는 비율이 높다
쓰기 오류noeviction 정책이면 쓰기가 거부된다

축출 건수가 가장 직접적입니다. 만료로 사라지는 것과 자리가 없어 밀려나는 것은 다른 지표이고, 후자가 늘면 용량 문제입니다.

메모리 단편화도 함께 봅니다. 실제 데이터보다 운영체제가 잡은 메모리가 훨씬 크면 단편화가 심한 것이고, 재시작이나 활성 조각 정리 설정으로 다룹니다.

대응순서
1큰 값과 불필요한 키를 찾아 정리한다
2TTL 을 줄여 회전을 빠르게 한다
3직렬화 형식을 줄인다
4증설하거나 샤딩한다

흔한 실수: 히트율만 보고 메모리 문제를 놓치는 것. 히트율 하락의 원인이 키 설계인지 용량인지는 축출 지표로 갈립니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

더 깊이 공부하기

읽었으면 문제로 확인해보세요

캐시/Redis 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.