효과적인 Redis Eviction 정책 선택 가이드
Redis는 인메모리 특성 덕분에 속도로 잘 알려져 있습니다. 하지만 데이터셋이 사용 가능한 물리적 메모리보다 커지면, Redis는 새로운 항목을 위한 공간을 확보하기 위해 오래되거나 덜 중요한 데이터를 능동적으로 제거해야 합니다. 이 과정은 Eviction 정책을 통해 관리되며, 이는 성능을 유지하고 캐시가 최적으로 작동하도록 보장하는 데 중요합니다. 올바른 정책을 선택하는 것은 캐시 적중률, 지연 시간 및 메모리 활용도에 직접적인 영향을 미칩니다.
이 가이드는 다양한 Redis 내장 Eviction 정책을 살펴보고, 각 정책이 어떻게 작동하는지 설명하며, 순수 캐싱 시나리오부터 시계열 데이터 관리까지 다양한 애플리케이션 워크로드에 가장 효과적인 전략을 선택하는 실용적인 조언을 제공합니다.
Redis Eviction 및 maxmemory 이해하기
Eviction 정책은 Redis 메모리 사용량이 maxmemory 설정 지시어로 설정된 한도를 초과할 때만 적용됩니다. maxmemory가 설정되지 않거나(또는 0으로 설정된 경우) Redis는 사용 가능한 모든 메모리를 사용하며, Eviction은 발생하지 않아 호스트 머신의 RAM이 부족해질 경우 시스템 불안정을 초래할 수 있습니다.
Eviction을 활성화하려면 redis.conf 파일에서 또는 CONFIG SET 명령을 통해 maxmemory를 구성해야 합니다.
# maxmemory를 2GB로 설정
CONFIG SET maxmemory 2gb
메모리가 제한되면 Redis는 쓰기 명령이 더 많은 메모리를 요구할 때 어떤 키를 버릴지 결정하기 위해 구성된 Eviction 정책을 사용합니다.
Redis 내장 Eviction 정책
Redis는 여러 가지 고유한 정책을 제공합니다. 이 정책들은 maxmemory-policy 지시어를 사용하여 구성됩니다. 정책은 일반적으로 두 가지 범주로 나뉩니다: 최소 최근 사용(LRU) 또는 최소 빈번 사용(LFU) 기반 정책과 TTL(Time To Live)이 설정된 키를 대상으로 하는 정책입니다.
1. TTL 요구 사항이 없는 정책
이 정책들은 만료 시간이 설정되어 있는지 여부와 관계없이 데이터베이스의 모든 키에 대해 작동합니다.
noeviction
이것이 기본 정책입니다. 메모리 제한에 도달하면 Redis는 SET, LPUSH 등과 같은 쓰기 명령을 거부하고 클라이언트에 오류를 반환합니다. 읽기(GET)는 여전히 허용됩니다. 이는 데이터 손실이 허용되지 않는 미션 크리티컬 데이터에 적합하지만, 높은 쓰기 압력 하에서 애플리케이션 오류를 유발할 수 있습니다.
allkeys-lru
maxmemory 한도 미만으로 메모리 사용량이 떨어질 때까지 데이터베이스의 모든 키 중에서 가장 적게 최근 사용된 키를 Eviction합니다. 이는 모든 데이터 항목이 동일하게 캐시될 수 있는 범용 캐시에 대한 표준 선택입니다.
allkeys-lfu
모든 키 중에서 가장 적게 사용된 키를 Eviction합니다. LFU는 최근에 액세스되지 않았더라도 자주 액세스되는 키를 유지하는 것을 우선시합니다. 이는 액세스 패턴이 변동성이 있을 때 효과적이지만, 매우 인기 있는 항목은 무기한으로 상주할 수 있습니다.
allkeys-random
메모리 제한이 충족될 때까지 무작위로 선택된 키를 Eviction합니다. 데이터 액세스 패턴이 완전히 균일하고 예측 불가능한 경우가 아니라면 프로덕션 캐시에는 거의 권장되지 않습니다.
2. TTL이 필요한 정책 (휘발성 키)
이 정책들은 명시적인 만료 시간(EXPIRE 또는 SETEX)이 설정된 키만 고려합니다. Eviction을 수행할 때 만료되지 않는 키는 무시합니다.
volatile-lru
만료가 설정된 키 중에서 가장 적게 최근 사용된 키를 Eviction합니다.
volatile-lfu
만료가 설정된 키 중에서 가장 적게 사용된 키를 Eviction합니다.
volatile-random
만료가 설정된 키 중에서 무작위 키를 Eviction합니다.
volatile-ttl
남은 TTL(Time To Live)이 가장 짧은 키를 먼저 Eviction합니다. 이는 세션 토큰 또는 임시 애플리케이션 상태와 같이 시간에 민감한 데이터에 이상적이며, 오래되었고 곧 만료될 데이터가 먼저 정리되도록 보장합니다.
워크로드에 적합한 정책 선택
최적의 Eviction 정책은 캐시하는 대상과 애플리케이션이 데이터를 사용하는 방식에 전적으로 달려 있습니다.
| 워크로드 유형 | 권장 정책 | 근거 |
|---|---|---|
| 범용 캐시 (가장 일반적) | allkeys-lru |
TTL과 관계없이 오래되고 사용되지 않는 데이터가 먼저 제거되어야 한다고 가정합니다. 간단하고 매우 효과적입니다. |
| 시간에 민감한 데이터 (예: 토큰, 단기 세션) | volatile-ttl |
만료에 가까운 키가 실제로 만료되기 전에 효율적으로 정리되도록 보장합니다. |
| 핫 데이터 캐시 (높은 액세스 편향) | allkeys-lfu 또는 volatile-lfu |
최근 비활성 상태로 인해 자주 액세스되는 항목이 Eviction되는 것을 방지합니다. |
| 필수 데이터 보존 (손실 허용 안됨) | noeviction |
쓰기에 오류를 발생시켜 데이터 손실을 방지하며, 수동 개입 또는 상위 애플리케이션 처리가 필요합니다. |
| 혼합 워크로드 (일부 데이터는 만료, 일부는 만료되지 않음) | volatile-lru 또는 volatile-ttl |
만료되지 않는 키가 필수적인 경우, 명시적으로 만료되는 키만 Eviction하여 보호하기 위해 volatile 정책을 사용합니다. |
실용적인 예시: 세션 스토어 구현
Redis가 주로 사용자 세션을 저장하는 데 사용된다면, 일반적으로 모든 세션 키에 명시적인 TTL(예: 30분)을 설정하고 TTL을 존중하는 정책을 사용합니다. volatile-ttl이 종종 더 우수합니다. 왜냐하면 세션이 많이 사용되는 경우, 몇 주 동안 건드리지 않은 다른 세션보다 약간 더 오래되었다는 이유만으로 Eviction되어서는 안 되기 때문입니다.
# 1. maxmemory 설정 (예: 10GB)
CONFIG SET maxmemory 10gb
# 2. TTL 데이터를 대상으로 하는 정책 선택
CONFIG SET maxmemory-policy volatile-ttl
실용적인 예시: HTTP 캐시 구현
전체 HTTP 응답을 캐싱할 때(항상 TTL이 설정되어 있지 않을 수 있음), 몇 시간 동안 건드리지 않았던 데이터라도 가장 자주 액세스되는 데이터를 유지하고 싶을 것입니다. allkeys-lru 또는 allkeys-lfu가 이상적입니다.
# 생성 시간과 관계없이 진정으로 '핫'한 객체를 유지하기 위해 LFU 사용
CONFIG SET maxmemory-policy allkeys-lfu
모니터링 및 튜닝
정책을 선택한 후에는 지속적인 모니터링이 필수적입니다. INFO 명령을 통해 다음 메트릭을 추적해야 합니다.
used_memory:maxmemory한도에 얼마나 가까운지.evicted_keys: Redis가 데이터를 버리는 속도. 지속적으로 높은 Eviction 비율은maxmemory설정이 워크로드에 비해 너무 낮거나 Eviction 정책이 지나치게 공격적이라는 것을 나타냅니다.- 애플리케이션 캐시 적중률: 성공의 궁극적인 척도. 메모리 압력이 증가할 때 적중률이 떨어진다면, 정책 선택 또는
maxmemory한도를 조정해야 합니다.
모범 사례:
maxmemory를 튜닝할 때는 항상 복제 버퍼링, 명령 버퍼링 및 Redis 내부 데이터 구조로 인한 잠재적 오버헤드를 고려하여 안전 버퍼(예: 10-20%의 여유 메모리)를 남겨두십시오.
결론
Redis Eviction 정책은 메모리 압력 하에서 캐시가 어떻게 동작하는지에 대한 세밀한 제어를 제공합니다. 단 하나의 '최고'의 정책은 없습니다. LRU, LFU 또는 TTL 기반 Eviction 중 선택은 데이터 액세스 패턴 및 비즈니스 요구 사항과 정확히 일치해야 합니다. allkeys-lru와 같은 일반 캐싱을 위한 적절한 정책 또는 세션 스토어를 위한 volatile-ttl을 신중하게 선택함으로써 캐시 효율성을 극대화하고 고속 데이터 작업에 대한 강력한 성능을 보장할 수 있습니다.