메모리가 한계에 닿았을 때 어떤 항목을 내보낼지 고르는 동작(축출). TTL이 시간으로 지우는 것이라면 eviction은 공간 부족으로 지우는 것이다.
Redis의 정책
maxmemory에 도달하면 maxmemory-policy에 따라 동작한다.
| 정책 | 대상 | 기준 |
|---|---|---|
noeviction | — | 안 지우고 쓰기에 에러 반환 (기본값) |
allkeys-lru | 전체 키 | 가장 오래 안 쓰인 것 |
volatile-lru | TTL 있는 키만 | 가장 오래 안 쓰인 것 |
allkeys-lfu | 전체 키 | 사용 빈도가 낮은 것 |
volatile-ttl | TTL 있는 키만 | 만료가 임박한 것 |
allkeys-random | 전체 키 | 무작위 |
함정 ① — 기본값이 noeviction이다
기본 설정에서는 메모리가 차면 지우지 않고 쓰기를 거부한다.
OOM command not allowed when used memory > 'maxmemory'
캐시로만 쓸 거라면 allkeys-lru로 바꿔 두어야 한다. 세션 저장소처럼 잃으면 안 되는
용도라면 오히려 noeviction이 맞다 — 용도에 따라 다르다.
함정 ② — volatile-* 는 TTL 없는 키를 절대 안 지운다
volatile-lru인데 TTL을 안 걸어 둔 키가 메모리를 채우면, 지울 대상이 없어
결국 쓰기 에러가 난다. 정책과 TTL 설정이 짝을 이뤄야 한다.
LRU vs LFU — 어느 쪽인가
- LRU(Least Recently Used) — 최근에 안 쓰인 것. 시간 지역성이 있을 때 유리
- LFU(Least Frequently Used) — 적게 쓰인 것. 일시적으로 몰린 요청에 강하다
배치 작업이 대량의 키를 한 번씩 훑고 지나가면, LRU는 그것들이 "최근"이라며 남기고 정작 자주 쓰이던 인기 키를 내보낸다(캐시 오염). LFU가 이 상황에 강하다.
Redis의 LRU는 정확한 LRU가 아니다
모든 키의 접근 시각을 정렬해 관리하면 비용이 너무 크다. 그래서 표본을 뽑아 그중 가장 오래된 것을 지운다.
maxmemory-samples 5 # 기본값. 5개 뽑아서 그중 최선
maxmemory-samples 10 # 정확도↑ CPU↑
축출이 잦다는 신호
작업 집합이 메모리보다 크다는 뜻이다. 정책을 바꾸기 전에 메모리를 늘리거나
캐시 대상을 좁히는 것이 먼저다. INFO stats의 evicted_keys와 히트율
(keyspace_hits / (hits + misses))을 함께 본다.