InfraGuard

Redis 튜닝 개념 (세션 관제 교육)

Service ▸ Sessions 화면의 Redis 지표를 해석하는 개념 안내 — slowlog 7대 원인, 적중률, 메모리 단편화 건강 대역, 만료 대 축출.

개요 — 무엇을 하나

이 문서는 Service ▸ Sessions (Redis) 화면(/service/session)에서 보게 되는 지표를 어떻게 읽고 무엇을 조치하는지 배우기 위한 교육용 참조입니다. 화면 자체는 실시간 관제 콘솔이고, 이 글은 그 뒤에 있는 Redis 운영 개념 — slowlog·적중률(hit ratio)·메모리 단편화·만료(expiry) 대 축출(eviction) — 을 정리합니다.

InfraGuard 는 Redis 에 직접 접속하지 않습니다. 내부망 대표 수집기(scripts/infr_redis_vts_collector.cjs, pm2 cron 매분)가 각 노드에서 redis-cli INFO 스냅샷을 떠서 중앙 MySQL infr_redis_metric 에 적재하고, 앱은 그 테이블을 읽기만 합니다. 따라서 여기 나오는 모든 값은 표준 INFO 필드에서 유래합니다.

각 지표의 정확한 사전 정의·개선 팁은 세션 화면의 교육용 popover(hover) 에 단일 소스로 담겨 있습니다(resources/lang/{ko,en}/redis.php 의 edu.*). 이 문서는 그 개념을 요약·연결할 뿐, 어휘를 중복 정의하지 않습니다 — 세부는 라이브 popover 에 마우스를 올려 확인하세요.

언제 쓰나

화면 구성

세션 카드 한 장은 노드 하나(node_alias = infr_instance.alias 1:1)를 나타내며, Service ▸ Database 의 서사를 그대로 물려받습니다.

영역 무엇을 보여주나 유래 INFO 필드
① 수용 · 여유 메모리 수용률 링 게이지(used / cap) · 클라이언트(connected/max) · 블록 used_memory, maxmemory, total_system_memory, connected_clients, maxclients, blocked_clients
② 처리량 ops/s 스파크 · 최근 창 적중률 · net I/O instantaneous_ops_per_sec, keyspace_hits/misses, instantaneous_input/output_kbps
풋 효율 점수 적중률 등급 · 메모리(단편화) 등급 hit_rate, mem_fragmentation_ratio
세션 수명 흐름 만료 예정(TTL 보유) → 흐름 → 누적 만료 keyspace_expires, expired_keys
상세(접이식) 메모리 관리 시계열 + 수용 상한 overlay + 축출 에피소드 핀 · 키스페이스/세션 분석 used_memory 시계열, evicted_keys, INFO keyspace

상단 KPI: 노드 수 · 정상/주의/중단 · 총 ops/s · 총 키 · 클라이언트 합.

수용 상한(capacity)이 정해지는 방식

링 게이지·메모리 차트의 100% 기준(예산)은 다음 순서로 결정됩니다.

  1. maxmemory 가 설정돼 있으면 그것이 곧 하드 상한입니다(Redis 가 강제). 예상 여유 = maxmemory − used.
  2. 미설정(무제한)이면 가용 예산 = 총 RAM − DB 버퍼풀 − OS/기타 예비(%). 예비율 기본 20%(Operations Policy redis_reserve_pct), DB 버퍼풀은 같은 노드의 access=database 수집기에서 차감합니다.

maxmemory 0(무제한) 노드는 카드에 "maxmemory 미설정 — OS/서버 RAM 대비로 표시" 안내가 붙습니다. 세션 전용 인스턴스라면 OS RAM 의 일정 비율로 maxmemory 를 명시적으로 잡아 축출 정책이 예측 가능하게 동작하도록 하는 편이 좋습니다.

사용법

1) slowlog — 왜 늘어나는가 (7대 원인 요약)

Redis 는 단일 스레드라 느린 명령 하나가 서버 전체를 막습니다. slowlog_len 은 slowlog-log-slower-than(기본 10ms)을 초과한 명령의 누적 수입니다. 흔한 순서:

  1. O(N) 명령 — KEYS *·SMEMBERS·HGETALL·LRANGE 0 -1 등 컬렉션 전체 스캔. 가장 흔함.
  2. 큰 값(big key) 조작 — 수 MB String·큰 Hash/Set/ZSet 직렬화·전송 비용.
  3. 메모리 압박·스왑 — used 가 상한 근접 시 할당 지연.
  4. 지속성 fork 지연 — RDB bgsave·AOF rewrite 의 latest_fork_usec.
  5. 느린 Lua/함수 스크립트 — 무거운 EVAL 이 실행 동안 블록.
  6. 대량 파이프라인·MULTI — 수천 명령 일괄 투입으로 뒤 명령 대기.
  7. 대형 키 DEL — DEL 대신 비동기 회수 UNLINK 사용.

실제 어떤 명령이 걸렸는지는 노드에서 직접 확인합니다.

# 최근 느린 명령 10건 (redis-cli)
redis-cli SLOWLOG GET 10
# 임계·유지 개수 설정 (마이크로초 단위 · 예: 10ms)
redis-cli CONFIG SET slowlog-log-slower-than 10000
redis-cli CONFIG SET slowlog-max-len 128
redis-cli SLOWLOG RESET

프로덕션에서 KEYS * 는 절대 쓰지 마세요 — 전체 키 공간을 훑는 동안 다른 모든 명령이 대기합니다. 커서 순회 SCAN/HSCAN/SSCAN/ZSCAN 로 대체하세요.

2) 적중률(keyspace hit ratio) — 낮다고 결함이 아니다

최근 창 적중률 = Δkeyspace_hits / (Δhits + Δmisses) 입니다. 표본이 부족하면(delta 분모 < 20) 누적 hit_rate 로 폴백합니다. 등급: 우수 ≥99% · 양호 ≥95% · 보통 ≥80%.

적중률은 노드를 빨갛게 칠하는 상태 축이 아닙니다. 세션 저장소는 본질적으로 적중률이 낮습니다 — 신규 로그인·만료·로그아웃마다 miss 가 나므로 40~60% 도 정상입니다(예: blue 44.75% = 멀쩡한 세션 노드). 그래서 redis_hit_rate_min(기본 50) 임계가 있어도 판정에는 쓰지 않고 표시·해석용으로만 둡니다. 진짜 캐시 문제는 아래 메모리 포화·축출·단편화가 워크로드와 무관하게 잡습니다.

적중률을 실제로 올리려면: 작업셋을 메모리에 상주(RAM/maxmemory 여유), TTL 적정화, 캐시 스탬피드(동시 만료 폭주) 완화(지터 TTL), 미스 다발 접두 사전 워밍. 자세한 팁은 라이브 hit popover 참고.

3) 메모리 단편화 — 건강 대역 1.0 ~ 1.5

mem_fragmentation_ratio = used_memory_rss / used_memory — OS 가 Redis 에 실제 내준 물리 메모리 대비 Redis 가 쓰는 양의 비율입니다.

비율 의미 조치
1.0 ~ 1.5 건강 대역 정상
> 1.5 단편화(RAM 낭비) activedefrag yes(jemalloc 필요), 큰 값 잦은 생성/삭제 감소
< 1.0 스왑 발생(위험) 즉시 RAM 증설 또는 maxmemory 하향으로 스왑 중단 — 성능 급락 신호

등급: 우수 0.95~1.4 · 양호 ~1.6 · 보통 ~2.5. 판정 임계 redis_frag_ratio 기본 1.6.

used_memory 가 64MB 미만인 작은 인스턴스는 고정 오버헤드가 비율을 지배해 단편화 수치가 오탐이 됩니다. InfraGuard 는 이 경우 단편화 점수를 계산에서 제외(frag_score = null)합니다 — 값은 참고로 표시하되 노드를 빨갛게 칠하지 않습니다.

4) 만료(expiry) 대 축출(eviction) — 세션 수명의 핵심

구분 의미 신호
만료(expired_keys) TTL 이 지나 자연 소멸 = 정상 세션 수명 회전량 · 대개 정상
축출(evicted_keys) maxmemory 도달로 정책에 따라 강제 제거 메모리 압박 · 세션 유실 위험

세션 저장소에서 만료는 정상이지만 축출이 0 을 넘어 지속되면 유효 세션이 버려지는 중입니다. 대응:

# 축출 정책 확인·변경
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG SET maxmemory-policy volatile-lru
# 온라인 조각모음 (단편화 > 1.5 대응 · jemalloc 필요)
redis-cli CONFIG SET activedefrag yes

상세 시계열의 메모리 관리 차트는 used_pct 위에 수용 상한 100% 절취선을 겹치고, 축출 에피소드를 crit 핀으로 표시합니다 — 어느 시점에 상한에 닿아 세션을 버렸는지 시각적으로 되짚을 수 있습니다.

5) 논리 DB(keyspace) 읽기

INFO keyspace 는 번호가 매겨진 독립 키 공간(logical DB, 기본 16개 · 인덱스 0~15)의 키 수를 보고합니다.

# INFO keyspace 예시
db0:keys=48213,expires=48213,avg_ttl=1680000
db1:keys=126,expires=0,avg_ttl=0

키가 가장 많은 DB 가 주 세션 저장소이고, 그 DB 의 키 = 만료(TTL 보유) 이면 순수 세션 저장소입니다(만료로 자연 소멸). 위 예에서 db0 은 세션(전부 TTL), db1 은 캐시·락 등 다른 용도로 읽힙니다.

데이터 소스

항목 값
소스 테이블 infr_redis_metric(중앙 MySQL · 읽기 전용 read-model, $timestamps=false)
공급 수집기 scripts/infr_redis_vts_collector.cjs(pm2, 매분) — redis-cli INFO
프로비저닝 수집기가 CREATE TABLE IF NOT EXISTS 로 자체 생성(마이그레이션 없음)
조인 키 instance_id(정수 FK 1차) → 폴백 node_alias ↔ infr_instance.alias
빌더 App\Services\Redis\RedisMetricService(배치 1쿼리 · 20s 캐시)
최근 창 30분(WINDOW_MIN) · 차트 최대 60포인트 · 폴링 30s(/service/session/live)
임계 SOT App\Support\OpsPolicy::redisThresholds()

판정 임계값(Operations Policy infr_setting group=ops):

키 기본값 판정
redis_mem_pct 85 수용률(%) ≥ → 주의(mem_saturation)
redis_frag_ratio 1.6 단편화 비율 ≥ → 주의(fragmentation, used≥64MB 일 때만)
redis_blocked 1 블록 클라이언트 ≥ → 주의(blocked_clients)
redis_stale_min 5 마지막 샘플 N분 초과 → 중단(stale)
redis_hit_rate_min 50 표시·해석용(판정에 미사용)
redis_reserve_pct 20 예상 여유 계산 시 OS/기타 예비율(%)

master_link_status=down(복제 링크 끊김)·rdb_last_bgsave_status=err(RDB 저장 실패)도 주의 사유로 잡힙니다. per-DB 키스페이스 상세와 total_system_memory·키 총계는 수집기 확장 컬럼이라, 구버전 수집기면 해당 섹션이 graceful 하게 숨겨집니다("수집기 재배포 후 표시").

권한

문제해결 · FAQ

Q. "수집된 Redis 노드가 없습니다" 만 뜹니다. A. infr_redis_metric 이 비어 있습니다. Administration ▸ Collectors 에서 redis_vts 수집기에 redis_host 노드를 등록하고, 대표 시스템에 scripts/infr_redis_vts_collector.cjs 를 pm2 로 배치하세요. 수집기가 CREATE TABLE IF NOT EXISTS 로 테이블을 만들고 매분 적재합니다.

Q. 노드가 계속 중단(down)·사유 stale 입니다. A. 마지막 샘플이 5분(redis_stale_min)을 넘었습니다 — pm2 수집기가 죽었거나(pm2 ls), 노드로의 네트워크·redis-cli 접속이 막혔습니다. 수집기 로그를 확인하세요.

Q. 키스페이스/세션 분석·메모리 상한 섹션이 안 보입니다. A. total_system_memory·per-DB keyspace·키 총계 컬럼은 수집기 확장분입니다. 구버전 수집기면 이 값이 null 이라 섹션이 숨겨집니다 — 수집기를 최신본으로 재배포하면 표시됩니다.

Q. 적중률이 45% 인데 왜 주의가 아닌가요? A. 설계상 그렇습니다. 세션 저장소는 낮은 적중률이 정상이라 적중률로 노드를 degraded 처리하지 않습니다. 진짜 문제(메모리 포화·축출·단편화)는 별도 축으로 잡힙니다.

Q. 단편화가 3.0 인데 인스턴스가 작습니다. A. used_memory 가 64MB 미만이면 고정 오버헤드가 비율을 왜곡합니다. InfraGuard 는 이 경우 단편화를 점수에서 제외하니 값만 참고하세요. 실제 스왑(<1.0)이 아니라면 걱정할 필요가 적습니다.

관련 항목

세션 화면의 튜닝 교육 패널
세션 화면의 튜닝 교육 패널