1. Redis 메모리 관리의 핵심 원칙
정리 작업을 실행하기 전에 Redis 운영의 기본 규칙을 숙지해야 합니다. 메모리 문제는 일반적으로 보존 정책 관리의 실수에서 비롯됩니다. 프로덕션 환경에서는 KEYS * 명령어가 블로킹 특성 때문에 엄격히 금지됩니다. 대신 SCAN 명령어를 MEMORY USAGE와 함께 사용하여 대용량 키를 안전하게 식별해야 합니다. 또한, UNLINK는 이벤트 루프를 블로킹하지 않고 비동기적으로 메모리를 회수하므로 항상 DEL보다 UNLINK를 선호해야 합니다. 마지막으로, 데이터 복구 가능성을 보장하기 위해 RDB 스냅샷 없이 대량 삭제를 수행해서는 안 됩니다.
2. Kubernetes 불일치: 제한(Limits) vs. 최대 메모리(Maxmemory)
Kubernetes에서 Redis를 실행하면 고유한 장애 모드가 발생합니다. 흔한 실수는 K8s 파드 제한에만 의존하는 것인데, 이는 갑작스러운 OOMKills로 이어집니다. 컨테이너의 메모리 제한을 Redis 내부 설정과 동기화해야 합니다:
* maxmemory 설정: 파드의 제한보다 낮은 값으로 maxmemory를 명시적으로 정의하십시오 (예: 512mb).
* Eviction 정책: Redis가 충돌하는 대신 오버플로우를 정상적으로 처리하도록 안전망으로 maxmemory-policy allkeys-lru를 구성하십시오.
* 모니터링: 실제 데이터 증가와 시스템 수준의 메모리 오버헤드를 구분하기 위해 mem_fragmentation_ratio 및 used_memory_rss를 추적하십시오.
3. Sidekiq의 메모리 급증 방지 강화
Sidekiq은 Ruby 애플리케이션에서 Redis 메모리 증가의 주요 원인인 경우가 많습니다. 기본적으로 stat:* 키는 만료되지 않으며, 실패한 작업(dead jobs)은 무기한으로 누적될 수 있습니다.
#### A. 통계 데이터에 TTL 구현
무한한 증가를 방지하기 위해 서버 설정 내에서 Sidekiq 통계에 30일 TTL을 적용하십시오:
ruby
Sidekiq.configure_server do |config|
config.on(:startup) do
Sidekiq.redis { |conn| conn.scan_each(match: 'stat:*') { |k| conn.expire(k, 30.days.to_i) } }
end
end
#### B. 재시도 및 실패한 작업 튜닝
재시도 횟수를 제한하고 실패한 작업(dead set)에 엄격한 타임아웃을 설정하여 메모리 압력을 줄이십시오:
```ruby
# In Worker
sidekiq_options retry: 5
In Initializer
Sidekiq.configure_server do |config| config.options[:dead_timeout] = 30.days.to_i config.options[:dead_max_jobs] = 2000 end ```
4. 안전한 프로덕션 정리 패턴
대용량 키를 식별하고 제거할 때는 블로킹을 유발하지 않는 패턴을 사용하십시오. 성능에 영향을 주지 않으면서 특정 패턴과 일치하는 키를 삭제하려면 작은 sleep 간격을 가진 SCAN 루프를 사용하십시오:
bash
redis-cli --scan MATCH 'stat:*' | while read -r key; do
redis-cli UNLINK "$key"
sleep 0.01
done
이 접근 방식은 대규모 정리 중에도 Redis 이벤트 루프가 애플리케이션 요청에 계속 응답하도록 보장합니다.