서비스를 배포했는데 로그인 세션이 간헐적으로 끊기고, 검색 기능이 느립니다. Redis와 Elasticsearch를 사용하고 있다는 건 알겠는데 어디서 어떻게 확인해야 할지 모릅니다. "Redis OOM" 에러가 로그에 찍혔고, Elasticsearch API가 타임아웃 납니다.
관계형 DB 외에 서비스에 자주 붙는 보조 스토리지의 운영 기초를 익힙니다. Redis와 Elasticsearch의 상태 확인 방법과 흔한 장애 패턴을 정리합니다.
- 1redis-cli로 Redis 상태(ping, info, dbsize, memory)를 5단계로 확인할 수 있다
- 2maxmemory-policy의 역할과 allkeys-lru 설정 이유를 설명할 수 있다
- 3KEYS 대신 SCAN을 써야 하는 이유와 사용법을 설명할 수 있다
- 4Elasticsearch 클러스터 상태 API로 Green/Yellow/Red를 확인하고 대응할 수 있다
- 5Redis Sentinel과 Cluster의 차이를 설명할 수 있다
Redis 운영 기초
redis-cli — Redis 상태 확인 필수 명령어
Redis가 정상인지 확인할 때 막막하다면, 5가지 명령어 순서만 기억하면 됩니다. 연결 확인 → 메모리 → 키 수 → 키스페이스 → 느린 명령어 순서입니다.

# 1. 연결 확인 (가장 기본)
redis-cli ping
# PONG → 정상
# 원격 Redis 접속 (패스워드 있는 경우)
redis-cli -h redis-server -p 6379 -a yourpassword ping
# 환경변수 방식 (보안)
REDISCLI_AUTH=yourpassword redis-cli -h redis-server ping
# 2. 메모리 상태 확인
redis-cli info memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
# used_memory_human: 1.50G → 현재 사용 메모리
# maxmemory_human: 2.00G → 설정된 최대 메모리
# mem_fragmentation_ratio: 1.2 → 1.5 이상이면 단편화 심각
# 3. 전체 키 수 확인
redis-cli dbsize
# (integer) 1234567 → 키 수
# 4. 키스페이스 (DB별 키 수, 만료 키 수)
redis-cli info keyspace
# db0:keys=1234567,expires=45678,avg_ttl=3600000
# 5. 느린 명령어 로그 확인
redis-cli slowlog get 10
# 실행 시간이 긴 명령어 목록 (기본 10ms 이상)
redis-cli slowlog len # 느린 명령어 누적 수
메모리 관리 — maxmemory와 eviction 정책
Redis가 메모리 한계에 도달했을 때 어떻게 동작할지는 설정에 달려있습니다. 이 설정을 빠뜨리면 갑자기 쓰기 명령이 전부 실패하는 장애가 납니다.

# 현재 메모리 정책 확인
redis-cli config get maxmemory
redis-cli config get maxmemory-policy
# 설정 변경 (재시작 없이 적용)
redis-cli config set maxmemory 2gb
redis-cli config set maxmemory-policy allkeys-lru
# redis.conf에서 영구 설정
# maxmemory 2gb
# maxmemory-policy allkeys-lru
eviction 정책 선택 기준:
| 정책 | 동작 | 적합한 경우 |
|---|---|---|
| noeviction | 메모리 초과 시 쓰기 거부 | 데이터 손실 불가(세션, 락) |
| allkeys-lru | 전체 키 중 최근 미사용 순 제거 | 일반 캐시 (권장) |
| volatile-lru | TTL 있는 키 중 최근 미사용 순 제거 | TTL 없는 영구 키와 혼용 시 |
| allkeys-random | 전체 키 중 무작위 제거 | 균등 접근 패턴 캐시 |
캐시 용도 Redis 권장 설정:
# 캐시 전용 Redis 서버
redis-cli config set maxmemory-policy allkeys-lru
# 세션 저장 Redis 서버 (데이터 손실 불가)
redis-cli config set maxmemory-policy noeviction
# noeviction이면 메모리 여유를 넉넉히 확보해야 함
KEYS vs SCAN — 운영에서 절대 KEYS를 쓰면 안 되는 이유
개발 환경에서 redis-cli keys "*" 같은 명령어를 썼다가 운영에 그대로 적용하면 서비스 장애가 납니다. 이유와 대안을 확실히 이해해야 합니다.
# KEYS — 절대 운영 사용 금지
redis-cli keys "session:*"
# O(N) 연산, 단일 스레드 블로킹
# 키 100만 개 → Redis 수 초 응답 없음 → 서비스 장애
# SCAN — 운영 환경에서 사용할 키 조회 방법
# cursor 기반으로 점진적 스캔 (블로킹 없음)
redis-cli scan 0 MATCH "session:*" COUNT 100
# 반환값: [다음 cursor, [키 목록]]
# cursor가 0으로 돌아오면 전체 스캔 완료
# 쉘에서 반복 스캔 (전체 패턴 키 조회)
redis-cli --scan --pattern "session:*"
# 내부적으로 SCAN을 반복 호출하며 모든 결과 출력
# 특정 패턴 키 수 카운트 (대략적)
redis-cli --scan --pattern "session:*" | wc -l
redis-cli monitor 명령어 (운영 중 주의 사용):
# 실시간으로 모든 명령어를 출력 (디버깅용)
redis-cli monitor
# 출력 예시:
# 1717041600.123456 [0 127.0.0.1:52341] "GET" "session:abc123"
# 트래픽 많은 운영 환경에서는 성능에 영향 — 짧게만 사용
Redis Sentinel vs Cluster — 고가용성 구성 선택 기준
단일 Redis 서버가 다운되면 캐시 미스로 DB에 전체 부하가 몰립니다. 이를 막기 위해 Redis는 두 가지 고가용성 구성을 제공합니다. 어떤 것을 선택하느냐는 데이터 규모와 운영 복잡도에 따라 달라지므로, 인프라 엔지니어가 반드시 구분할 수 있어야 합니다.
Redis Sentinel — 단일 Master 고가용성(HA)
Master 1대 + Slave N대 구성에서 Sentinel 프로세스(최소 3개 권장)가 Master를 감시합니다. Master 장애 감지 시 Sentinel들이 과반수 투표로 Slave 중 하나를 자동으로 Master로 승격(Failover)시킵니다. 데이터는 Master 한 대에 집중되므로 데이터 용량이 서버 한 대 메모리를 초과하면 Sentinel은 한계에 부딪힙니다.
[Sentinel 구조]
Sentinel1 Sentinel2 Sentinel3
↓ ↓ ↓
Master → Slave1 → Slave2
(장애 시 Slave1이 Master 승격)
Redis Cluster — 샤딩 + 고가용성 동시 해결
16384개의 hash slot을 여러 Master 노드에 분산해 데이터를 저장합니다. 각 Master는 Replica를 가지며, 특정 Master 장애 시 해당 Replica가 자동으로 Master로 승격됩니다. 대용량 데이터와 높은 처리량이 필요할 때 사용하지만 Multi-key 명령어 제한 등 운영 복잡도가 높습니다.
[Cluster 구조 — 최소 3 Master + 3 Replica]
Master1(slot 0-5460) Master2(slot 5461-10922) Master3(slot 10923-16383)
↓ ↓ ↓
Replica1 Replica2 Replica3
| 항목 | Sentinel | Cluster |
|---|---|---|
| 데이터 분산 | 없음 (Master 1대) | 샤딩 (N개 Master) |
| 용량 한계 | 서버 1대 메모리 | 전체 노드 합산 |
| 페일오버 | 자동 (Sentinel 투표) | 자동 (내장) |
| 권장 규모 | 소~중형 (수십 GB 이하) | 대형 (100GB 이상) |
| 운영 복잡도 | 낮음 | 높음 |
Redis 상태 확인 실습
Redis 서버 상태를 순서대로 확인하는 5단계 루틴입니다. 장애 대응 시에도 이 순서로 확인합니다.
# 1단계: 연결 확인
redis-cli -h redis-server -p 6379 ping
# PONG
# 2단계: 메모리 상태
redis-cli -h redis-server info memory | grep -E "used_memory_human|maxmemory_human|maxmemory_policy"
# 3단계: 전체 키 수
redis-cli -h redis-server dbsize
# 4단계: DB별 키 분포
redis-cli -h redis-server info keyspace
# 5단계: 느린 명령어 확인
redis-cli -h redis-server slowlog get 5
# 출력 형식: [ID, 실행시각, 소요시간(마이크로초), 명령어, 인수]
# 1) 1) (integer) 14 ← slowlog ID
# 2) (integer) 1717041600 ← 실행 시각 (unix timestamp)
# 3) (integer) 15432 ← 소요 시간 (15.4ms)
# 4) 1) "KEYS" ← 문제 명령어 발견
# 2) "*"
redis-cli ping && redis-cli info memory | grep used_memory_human && redis-cli dbsize && redis-cli info keyspace && redis-cli slowlog get 5- redis-cli ping → PONG이 즉시 반환됐는가
- used_memory_human이 maxmemory_human의 80% 미만인가 (메모리 여유 확인)
- maxmemory-policy가 서비스 특성에 맞게 설정됐는가 (캐시: allkeys-lru)
- slowlog에 KEYS 명령어가 찍혀있지 않은가 (잘못된 사용 확인)
- info keyspace의 db0 키 수가 예상 범위인가
Elasticsearch 클러스터 상태 확인
Elasticsearch 클러스터 상태 API — Green/Yellow/Red 대응
Elasticsearch는 REST API로 모든 상태를 확인합니다. 클러스터 상태, 인덱스 목록, 노드 상태를 curl 한 줄로 볼 수 있습니다.
# 1. 클러스터 전체 상태 (가장 먼저 확인)
curl http://es-server:9200/_cluster/health?pretty
# 응답 예시 (Green):
# {
# "cluster_name": "my-cluster",
# "status": "green",
# "number_of_nodes": 3,
# "number_of_data_nodes": 3,
# "active_primary_shards": 15,
# "active_shards": 30,
# "relocating_shards": 0,
# "initializing_shards": 0,
# "unassigned_shards": 0 ← 0이어야 Green
# }
# 응답 예시 (Yellow):
# "status": "yellow",
# "unassigned_shards": 5 ← Replica 샤드 미할당
# 응답 예시 (Red):
# "status": "red",
# "unassigned_shards": 3 ← Primary 샤드 미할당
# 2. 인덱스 목록 및 상태
curl http://es-server:9200/_cat/indices?v
# 출력:
# health status index uuid pri rep docs.count store.size
# green open products-2026 abc123 1 1 1234567 2.3gb
# yellow open orders-2025 def456 1 1 567890 890mb
# 3. 노드 상태 확인
curl http://es-server:9200/_cat/nodes?v
# 출력:
# ip heap.percent ram.percent cpu load_1m node.role name
# 10.0.1.10 45 78 5 0.5 mdi node-1
# 10.0.1.11 52 80 8 0.8 mdi node-2
# 4. 미할당 샤드 상세 원인 확인 (Yellow/Red 시)
curl http://es-server:9200/_cluster/allocation/explain?pretty
클러스터 상태별 대응:
| 상태 | 원인 | 대응 |
|---|---|---|
| Green | - | 정상 |
| Yellow | Replica 미할당 (노드 부족) | 노드 추가 또는 replica 수 줄이기 |
| Red | Primary 미할당 | 즉시 대응 — 노드 복구 또는 샤드 재할당 |
ES 상태 확인은 항상 클러스터 레벨 → 인덱스 레벨 → 노드 레벨 순서로 확인합니다.
# 전체 상태 요약 (한 줄 형식)
curl -s "http://es-server:9200/_cat/health?v"
# epoch timestamp cluster status node.total node.data shards pri relo init unassign
# 1717041600 09:00:00 my-cluster green 3 3 30 15 0 0 0
# Yellow 상태 시 미할당 샤드 확인
curl -s "http://es-server:9200/_cat/shards?v&h=index,shard,prirep,state,node" | grep UNASSIGNED
# Yellow 해결 — replica 수를 1에서 0으로 줄이기 (단일 노드 환경)
curl -X PUT "http://es-server:9200/_settings" \
-H "Content-Type: application/json" \
-d '{"index": {"number_of_replicas": 0}}'
# 특정 인덱스만 변경
curl -X PUT "http://es-server:9200/my-index/_settings" \
-H "Content-Type: application/json" \
-d '{"index": {"number_of_replicas": 0}}'
curl -s http://es-server:9200/_cluster/health?pretty- 클러스터 status가 green인가
- unassigned_shards가 0인가 (Yellow/Red면 원인 확인 필요)
- 노드 수(number_of_nodes)가 예상한 클러스터 노드 수와 일치하는가
- heap.percent가 80% 미만인가 (_cat/nodes?v 확인)
- curl http://es-server:9200 에서 클러스터 이름과 버전이 응답됐는가
트러블슈팅
원인: Redis의 메모리 사용량이 maxmemory 한계에 도달했고, maxmemory-policy가 noeviction으로 설정돼 있어 새로운 쓰기 명령을 모두 거부하고 있습니다.
# 1. 현재 메모리 상태 확인
redis-cli info memory | grep -E "used_memory_human|maxmemory_human|maxmemory_policy"
# maxmemory_policy: noeviction ← 문제 설정 확인
# 2. 전체 키 수 및 TTL 없는 키 비율 확인
redis-cli dbsize
redis-cli info keyspace
# expires 수가 keys에 비해 매우 작으면 TTL 미설정 키 과다
# 3. 즉각 조치 (서비스 중단 방지)
# 옵션 A: eviction 정책 변경 (캐시 성격이면)
redis-cli config set maxmemory-policy allkeys-lru
# 옵션 B: maxmemory 임시 증가 (장기 해결책이 아님)
redis-cli config set maxmemory 4gb
# 옵션 C: TTL 없는 불필요 키 삭제
redis-cli --scan --pattern "old-cache:*" | xargs -L 100 redis-cli del
# 4. redis.conf 영구 반영
# maxmemory 4gb
# maxmemory-policy allkeys-lru
원인: 클러스터에 Replica 샤드를 배치할 노드가 부족합니다. 노드가 1대인데 replica가 1로 설정돼 있거나, 노드 한 대가 다운된 경우입니다.
# 1. 미할당 샤드 확인
curl -s "http://es-server:9200/_cat/shards?v" | grep UNASSIGNED
# 2. 원인 상세 확인
curl -s "http://es-server:9200/_cluster/allocation/explain?pretty"
# "explanation": "cannot allocate because a previous copy of the primary shard existed..."
# "explanation": "the shard cannot be allocated because there are not enough nodes"
# 3-A: 단일 노드 환경 — replica를 0으로 설정
curl -X PUT "http://es-server:9200/_all/_settings" \
-H "Content-Type: application/json" \
-d '{"index.number_of_replicas": 0}'
# 3-B: 다운된 노드가 있는 경우 — 노드 복구 후 샤드 자동 재할당 대기
# 노드 복구 후 상태 확인
curl -s "http://es-server:9200/_cat/nodes?v"
# 3-C: 노드 추가 (장기 해결책)
# 새 노드를 같은 클러스터 이름으로 시작하면 자동으로 샤드 재배치됨
# 4. 상태 모니터링 (자동 복구 확인)
watch -n 5 'curl -s "http://es-server:9200/_cat/health?v"'
실제 업무에서 이 지식이 쓰이는 상황:
1. 배포 직후 Redis 상태 확인 루틴:
# 신규 서비스 배포 후 캐시 동작 확인
redis-cli -h redis-server info memory | grep used_memory_human
redis-cli -h redis-server dbsize
# 키 수가 급격히 늘었으면 TTL 설정 여부 점검
redis-cli -h redis-server info keyspace | grep expires
2. Redis 느린 응답 민원 접수 시:
# 느린 명령어 먼저 확인
redis-cli slowlog get 20 | grep -A 4 '"KEYS"'
# KEYS 명령어 발견 → 개발팀에 SCAN으로 교체 요청
# 메모리 단편화 확인
redis-cli info memory | grep mem_fragmentation_ratio
# 1.5 이상이면 Redis 재시작 또는 MEMORY PURGE 고려
3. Elasticsearch 정기 점검:
# 매일 아침 헬스체크 스크립트
STATUS=$(curl -s "http://es-server:9200/_cat/health?h=status" | tr -d '\n')
if [ "$STATUS" != "green" ]; then
echo "ES 클러스터 상태 이상: $STATUS"
curl -s "http://es-server:9200/_cluster/allocation/explain?pretty"
fi
다음 모듈에서는 cron과 Quartz 스케줄러 장애 분석과 Spring Batch 재처리 실무를 다룹니다.