InfraGuard

세션 (Redis)

내부망 대표 수집기가 적재한 노드별 Redis 세션·캐시 상태(수용률·처리량·적중률·메모리 관리·키스페이스)를 직접 연결 없이 읽어 관제합니다.

개요 — 무엇을 하나

Service ▸ Sessions(Redis) 는 등록된 Redis 노드의 세션·캐시 저장소 상태를 한 화면에서 관제합니다. Service ▸ 데이터베이스 화면과 동일한 서사를 Redis 로 옮긴 것으로, 두 축을 중심으로 읽습니다.

  1. 수용 최대한도 + 현재 상태 — 메모리 수용률 링 게이지(used_memory ÷ 수용 상한), 클라이언트 연결(connected / maxclients), 블록된 클라이언트.
  2. 처리량 — 초당 명령 수(instantaneous_ops_per_sec), 최근 창 적중률(Δhits / Δ(hits+misses)), 네트워크 I/O(in/out kbps).

그리고 접이식 상세에서 메모리 관리 시계열(수용 상한 overlay + 축출 에피소드 핀)과 키스페이스/세션 분석을 제공합니다.

이 화면은 Redis 에 직접 접속하지 않습니다. 내부망 대표 수집기(scripts/infr_redis_vts_collector.cjs, pm2 cron 매분)가 각 노드에서 redis-cli INFO 를 떠 중앙 MySQL infr_redis_metric 테이블에 이미 적재한 데이터를 앱이 읽기만 합니다. 앱에는 Redis 크리덴셜도, 상주 데몬도 없습니다(연결 누수·하드코딩 크리덴셜 트랩 회피).


언제 쓰나


화면 구성

상단 KPI

KPI 의미
노드 수 최근 창(30분)에 표본이 있는 Redis 노드 카드 수
정상 / 주의 / 중단 up / degraded / down 노드 집계
총 ops/s 전 노드 instantaneous_ops_per_sec 합
총 키 전 노드 keyspace_keys 합

노드 카드 (2대 지표)

각 노드는 카드 하나입니다. 헤더에 인스턴스 이름/alias·Redis 버전·역할(master/replica), 본문에 위 두 축의 지표가 들어갑니다.

① 수용 · 여유 (좌측 링 게이지) — 중앙값 = used_pct(사용량 ÷ 수용 상한). 아래 지표 스트립:

지표 필드 설명
클라이언트 connected_clients / maxclients 연결 수·상한. 상한 근접 시 신규 연결 거부 위험
블록 blocked_clients BLPOP·BRPOP·WAIT 대기 클라이언트(0 이 정상)

② 처리량 (우측) — 스파크라인 + 스트립:

지표 필드 설명
ops/s instantaneous_ops_per_sec 초당 처리 명령 수
적중률 Δhits / Δ(hits+misses) 최근 창 캐시 적중률(표본 부족 시 누적값 폴백)
net I/O instantaneous_input_kbps + output_kbps 초당 네트워크 입출력

효율 점수 (카드 풋)

단편화 점수(frag_score)는 used_memory 가 64MB 이상일 때만 계산합니다. 작은 인스턴스는 고정 오버헤드가 비율을 지배해 오탐이 나기 때문입니다(그 미만은 점수·상태 판정에서 제외).

세션 수명 흐름 스트립

카드 풋 전체폭에 만료 예정 → 흐름 → 누적 만료 를 표현합니다. 왼쪽 = 지금 TTL 을 가진 키(keyspace_expires, 곧 자연 소멸), 오른쪽 = 가동 이후 만료 누적(expired_keys, 세션 회전량). 채움이 ≈100% 면 순수 세션 저장소입니다.

상세 (펼치기)

접이식으로 두 블록을 엽니다(masonry 가 높이 변화를 자동 재배치).

교육용 popover (edu)

지표 옆 아이콘에 마우스를 올리면 원인·개선법을 설명하는 디자인된 popover 가 뜹니다(자세한 개념은 Redis 튜닝 배우기):

popover 내용
SLOWLOG 느린 명령 누적 원인 7종(O(N) 명령·big key·메모리 압박·fork 지연·Lua·파이프라인·대형 DEL)
적중률 keyspace hit ratio 근거·향상법(작업셋 상주·TTL 조정·스탬피드 완화)
단편화 RSS / used 건강 대역(1.0~1.5)·activedefrag·스왑(<1.0) 경고
논리 DB Redis 번호 DB(0~15) 개념·용도별 분리·Cluster 이식성
만료·축출 만료(정상 수명) vs 축출(메모리 압박) 구분·읽는 법

사용법

  1. 폴링 — 진입 후 /service/session/live 를 30초 주기로 폴링해 KPI·카드를 갱신합니다(서버는 대시보드를 20초 캐시).
  2. 카드 재정렬 — 카드를 드래그해 우선순위대로 배치합니다(SortableJS · 순서 localStorage 영속).
  3. 상세 펼치기 — 카드의 [펼치기]로 메모리 관리·키스페이스 블록을 엽니다.
  4. edu 학습 — 각 지표 아이콘 hover 로 원인·개선법 popover 를 봅니다.
  5. 전체화면 — 헤더 LIVE 옆 전체화면 버튼으로 상단 네비를 숨기고 대시보드 모드로 전환(ESC 해제)합니다.

카드가 하나도 없다면 아직 Redis 노드가 등록·수집되지 않은 것입니다. Administration ▸ Collectors 에서 redis_vts 수집기의 redis_host 노드를 등록하고, 대표 시스템에 수집기를 pm2 로 배치하세요.


데이터 소스

read-model infr_redis_metric

앱은 이 테이블을 읽기 전용 Legacy 스타일 모델(App\Models\Infr\InfrRedisMetric, $timestamps=false)로 매핑합니다. 마이그레이션은 두지 않습니다 — 테이블은 수집기가 CREATE TABLE IF NOT EXISTS 로 자체 프로비저닝하므로 앱이 Schema::create 하면 충돌합니다.

빌더 App\Services\Redis\RedisMetricService::dashboard() 규율:

-- 개념 예시(실제는 Eloquent). 최근 창 배치 조회 → PHP 그룹.
SELECT * FROM infr_redis_metric
 WHERE sampled_at >= (NOW() - INTERVAL 30 MINUTE)
 ORDER BY sampled_at;

수집기 — scripts/infr_redis_vts_collector.cjs

내부망 대표 시스템 1대가 pm2 cron 으로 주기 실행되며, 여러 노드의 Redis(redis-cli -h {ip} INFO)와 nginx vts 를 1회 순회 수집해 중앙 MySQL 에 직접 적재하고 종료합니다(상주 아님 → 매 실행 새 프로세스, 누수 없음). 설정은 파일 상단 CONFIG 블록만 편집(env·하드코딩 크리덴셜 금지).

# 대표 시스템 배포(매 분 순회 · 상주 아님)
npm i mysql2                 # 유일한 npm 의존(적재용). redis-cli 는 OS 패키지로 설치.
pm2 start infr_redis_vts_collector.cjs --name infr-collector \
  --no-autorestart --cron-restart "* * * * *"
pm2 save

인스턴스 조인 (alias / int FK)

수집기는 write 시점에 infr_instance 에서 노드 alias→id 를 조회해 instance_id(int) 를 직접 기록합니다. 앱은 metric.instance_id = infr_instance.id 정수 비교를 1차 조인으로 씁니다(collation 무관·PK 인덱스). 미등록/늦게 등록된 인스턴스는 node_alias(소문자) → infr_instance.alias 폴백으로 매칭하며, infr:link-metrics(리더 게이팅, 5분) 백필이 나중에 instance_id 를 채웁니다.

수용 상한(cap) 계산

링 게이지·메모리 차트의 100% 기준은 다음 순서로 정합니다.

cap 종류 조건 상한 예상 여유(est_free)
maxmemory maxmemory > 0 maxmemory 설정값(하드 상한) maxmemory − used
budget maxmemory 미설정 총 RAM − DB 버퍼풀 − OS 예비 예산 − used

상태 판정 & 임계값

statusOf() 는 노드를 up / degraded / down 으로 판정합니다.

상태 조건
down 수집 실패(ok=0) 또는 stale(마지막 샘플이 redis_stale_min 초과)
degraded 아래 사유 중 하나 이상
up 사유 없음

degraded 사유와 임계값(Administration ▸ 운영 정책 infr_setting group=ops):

사유 조건 임계 키 기본값
메모리 수용 임박 used_pct ≥ redis_mem_pct 85
메모리 단편화 frag_score ≥ redis_frag_ratio 1.6
블록된 클라이언트 blocked_clients ≥ redis_blocked 1
복제 링크 끊김 master_link_status = down — —
RDB 저장 실패 rdb_last_bgsave_status = err — —

적중률은 상태 축이 아닙니다. 세션 저장소는 신규 로그인·만료·로그아웃마다 miss 가 나 40~60% 적중률이 정상입니다(예: 44.75% 인 멀쩡한 세션 노드). 과거에는 redis_hit_rate_min(기본 50) 미만이면 degraded 로 오탐(false-red)했으나, 지금은 적중률을 카드 KPI·등급 게이지·edu popover 로 표시만 하고 노드를 빨갛게 칠하지 않습니다. 진짜 캐시 문제(메모리 포화·축출·단편화)는 mem_saturation/fragmentation 이 워크로드와 무관하게 잡습니다.


권한

이 화면 자체에는 파괴적 작업이 없어 별도 감사 로그를 남기지 않습니다(수집기·정책 변경은 각 관리자 화면에서 감사).


문제해결 · FAQ

카드가 하나도 없어요("수집된 Redis 노드가 없습니다")

infr_redis_metric 에 최근 표본이 없는 경우입니다. (1) Administration ▸ Collectors 에서 redis_vts 수집기에 redis_host 노드를 등록했는지, (2) 대표 시스템에 infr_redis_vts_collector.cjs 가 pm2 로 돌고 있는지, (3) 대표 시스템에서 각 노드의 Redis 포트에 redis-cli 로 도달 가능한지 확인하세요.

노드가 "중단(stale)" 로 뜹니다

마지막 샘플이 redis_stale_min(기본 5분)보다 오래됐습니다. 대표 수집기 pm2 프로세스가 죽었거나 cron 주기가 멈춘 것입니다. pm2 list / pm2 logs infr-collector 로 점검하세요.

링 게이지 상한이 이상합니다 / 여유공간이 크게 나옵니다

maxmemory 를 설정하지 않은 노드는 가용 예산(budget) 을 상한으로 씁니다(총 RAM − DB 버퍼풀 − OS 예비 20%). 하드 상한을 원하면 Redis 에 maxmemory 를 설정하세요 — 그러면 그 값이 곧 상한이 됩니다.

키스페이스/세션 블록이 비어 있어요

per-db 상세(raw.keyspace)·세션 DB 지표는 확장된 수집기가 채웁니다. 구버전 수집기라면 재배포(total_system_memory·keyspace_keys·per-db raw 컬럼 멱등 추가) 후 표시됩니다. 미수집이면 섹션이 graceful 하게 숨습니다.

적중률이 낮은데 문제인가요?

세션 워크로드라면 아닙니다(위 경고 참조). 순수 캐시 용도인데 적중률이 낮다면 작업셋이 메모리에 상주하지 못하거나 TTL 이 너무 짧은 것일 수 있습니다 — Redis 튜닝 배우기의 적중률 항목을 참고하세요.

단편화 점수가 표시되지 않아요

used_memory 가 64MB 미만이면 단편화 비율이 고정 오버헤드에 지배돼 무의미하므로 점수·상태 판정에서 제외합니다.


관련 항목

Redis 세션 관제 — 수용률·처리량·적중률
Redis 세션 관제 — 수용률·처리량·적중률