Redis 와 캐싱 · TTL 과 만료 정책 · 실습
TTL 과 만료 정책 다루기
목표
TTL 의 동작을 정확히 이해하고, TTL 이 조용히 사라지는 함정을 재현해 막고, 축출 정책의 차이를 실제 축출로 확인한다.
왜 중요한가
"Redis 메모리가 계속 자라는데 원인을 모르겠다"는 문의의 대부분은 TTL 을 안 건 키입니다. 그리고 그것이 눈에 안 띄는 이유는 코드가 SETEX 를 잘 쓰고 있는데도 어딘가에서 SET 으로 값만 갱신하면서 원래 있던 수명을 날려 버리기 때문입니다. 이 실습의 3번 스텝이 정확히 그 장면입니다. 또 하나 몸에 남겨야 할 것은 만료가 즉시가 아니라는 사실입니다. Redis 는 접근할 때 지우거나 백그라운드에서 표본을 뽑아 지웁니다. 그래서 만료 시각이 지난 키가 DBSIZE 에 남아 있을 수 있고, "만료됐는데 왜 메모리가 안 줄지"의 답이 여기 있습니다. 마지막 감사 스크립트는 운영에 그대로 가져가 쓸 수 있는 물건입니다.
단계
1. cache:a 를 값과 함께 60초 수명으로 넣고 /root/ttl/ttl1.txt 에 ttl=<남은초> 를 적는다. 값은 1 이상 60 이하이다.
2. cache:a 의 TTL 을 제거한다. /root/ttl/ttl2.txt 에 ttl=-1 이 적혀야 한다.
3. cache:b 를 60초 수명으로 넣은 뒤 SET cache:b <새값> 으로 값만 갱신한다. TTL 이 -1 이 되는 것을 /root/ttl/lost.txt 에 기록하고, KEEPTTL 로 다시 시도한 결과를 /root/ttl/kept.txt 에 ttl=<양수> 로 적는다.
4. cache:c 를 1초 수명으로 넣고 2초 기다린 뒤, 접근하지 않은 상태의 DBSIZE 와 접근 후의 DBSIZE 를 /root/ttl/lazy.txt 에 before=<n> after=<n> 으로 적는다.
5. maxmemory-policy 를 allkeys-lfu 로 설정한다. /root/ttl/policy.txt 에 maxmemory-policy allkeys-lfu 가 들어가야 한다.
6. maxmemory 를 8mb 로 낮추고 /root/ttl/fill.py 로 키를 충분히 넣어 축출을 일으킨다. /root/ttl/evicted.txt 에 evicted_keys=<n> 을 적고 n 은 0보다 커야 한다.
7. /root/ttl/audit.sh 로 SCAN 순회하며 TTL 이 -1 인 키를 /root/ttl/nottl.txt 에 적는다. 스크립트에 KEYS 문자열이 있으면 안 되고, 결과 파일에 최소 1개의 키가 있어야 한다.
참고
- 수명 조회:
TTL key— -1 은 만료 없음, -2 는 키 없음입니다. - TTL 유지 갱신:
SET key val KEEPTTL - 축출 통계:
redis-cli INFO stats | grep evicted_keys - TTL 지터:
ttl = base + random(-spread, +spread)로 동시 만료를 흩뜨립니다. - 흔한 실수:
volatile-lru정책에서 캐시 키에 TTL 을 빠뜨리는 것 — 그 키는 영원히 축출되지 않습니다.
단계 7개
- TTL 걸고 남은 수명 확인하기
- TTL 제거해 영구 키로 만들기
- SET 이 TTL 을 날리는 함정 재현하고 막기
- 만료가 즉시 메모리 반환이 아님을 관찰하기
- 축출 정책 설정하기
- 실제로 축출이 일어나게 만들기
- TTL 없는 키 감사 스크립트 만들기