개요 — 무엇을 하나
이 문서는 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 에 마우스를 올려 확인하세요.
언제 쓰나
- 세션 카드가 주의(degraded)/중단(down) 으로 바뀌었는데 그 사유(
mem_saturation·fragmentation·blocked_clients·replica_link_down·rdb_save_failed·stale)의 의미를 알고 싶을 때. - 적중률이 낮게 표시되는데 노드는 멀쩡해 보일 때(세션 저장소의 정상 특성인지 판단).
- 메모리 단편화 비율이 1.5 를 넘거나 1.0 아래로 떨어졌을 때 원인·대응을 알고 싶을 때.
- 축출(eviction) 이 0 보다 커지기 시작해 세션 유실을 우려할 때.
- slowlog 가 계속 늘어 어떤 명령 패턴을 고쳐야 하는지 찾을 때.
화면 구성
세션 카드 한 장은 노드 하나(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% 기준(예산)은 다음 순서로 결정됩니다.
maxmemory가 설정돼 있으면 그것이 곧 하드 상한입니다(Redis 가 강제). 예상 여유 =maxmemory − used.- 미설정(무제한)이면 가용 예산 =
총 RAM − DB 버퍼풀 − OS/기타 예비(%). 예비율 기본 20%(Operations Policyredis_reserve_pct), DB 버퍼풀은 같은 노드의access=database수집기에서 차감합니다.
maxmemory 0(무제한) 노드는 카드에 "maxmemory 미설정 — OS/서버 RAM 대비로 표시" 안내가 붙습니다. 세션 전용 인스턴스라면 OS RAM 의 일정 비율로maxmemory를 명시적으로 잡아 축출 정책이 예측 가능하게 동작하도록 하는 편이 좋습니다.
사용법
1) slowlog — 왜 늘어나는가 (7대 원인 요약)
Redis 는 단일 스레드라 느린 명령 하나가 서버 전체를 막습니다. slowlog_len 은 slowlog-log-slower-than(기본 10ms)을 초과한 명령의 누적 수입니다. 흔한 순서:
- O(N) 명령 —
KEYS *·SMEMBERS·HGETALL·LRANGE 0 -1등 컬렉션 전체 스캔. 가장 흔함. - 큰 값(big key) 조작 — 수 MB String·큰 Hash/Set/ZSet 직렬화·전송 비용.
- 메모리 압박·스왑 — used 가 상한 근접 시 할당 지연.
- 지속성 fork 지연 — RDB
bgsave·AOF rewrite 의latest_fork_usec. - 느린 Lua/함수 스크립트 — 무거운
EVAL이 실행 동안 블록. - 대량 파이프라인·MULTI — 수천 명령 일괄 투입으로 뒤 명령 대기.
- 대형 키 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% 도 정상입니다(예:
blue44.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 을 넘어 지속되면 유효 세션이 버려지는 중입니다. 대응:
- 축출 rate > 0 → RAM/
maxmemory증설. - 축출 정책 확인:
allkeys-lru는 세션까지 버리고,volatile-*는 TTL 있는 키만 버립니다. rejected_connections가 함께 늘면maxclients와 메모리 한계에 동시에 닿은 것입니다.
# 축출 정책 확인·변경
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 하게 숨겨집니다("수집기 재배포 후 표시").
권한
- 읽기(세션 화면 조회): Service 역할 영역
min_req 1— 로그인한 모든 사용자(demo=1 이상). 이 화면은 읽기 전용이라 쓰기 게이트가 없습니다(Redis 직접 접속·저장 커맨드 없음). - 임계값 편집: Operations Policy 에서
redis_*값을 조정 — 관리자level≥5(admin=10,infr.level게이팅). - 수집기 등록: redis_vts 수집기의 redis_host 노드 등록은 Collectors 에서
level≥5.
문제해결 · 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)이 아니라면 걱정할 필요가 적습니다.
관련 항목
- 세션 (Redis) 화면 — 이 개념을 적용하는 라이브 관제 콘솔
- 데이터베이스 부하 관제 — 같은 서사를 따르는 DB 관제(연결·QPS·slow query)
- DB 튜닝 개념 (교육) — 락·캐시·인덱스 등 DB 측 대응
- 운영 정책 —
redis_*임계값·예비율 편집 - 수집기 관리 — redis_vts 수집기·노드 등록
- 서비스 관제 개요 — 세션 카드를 보드에 큐레이션
