뭐가 이렇게 어렵냐?
- Redis의 핵심 구조와 작동 원리
- 인메모리 기반 고성능 저장 방식의 장점
- 다양한 데이터 구조(String, Hash, List, Set 등)의 특징 및 활용 사례
- 영속성(Persistence) 옵션의 동작 방식을 이해하고 선택하기
- 클러스터링과 고가용성 구조를 통해 Redis가 안정적으로 운영되는 원리
Redis 개요
Redis는 Remote Dictionary Server의 약자임
데이터를 메모리(RAM)에 저장하는 초고속 인메모리 데이터 저장소라고 함
디스크 기반 데이터베이스보다 훨씬 빠르게 데이터를 읽고 쓸 수 있다
캐시, 세션 저장소, 실시간 순위 집계 등 다양한 분야에서 사용된다
1. 인메모리 데이터 저장 구조
Redis는 모든 데이터를 메모리에 저장하고, 필요할 때 디스크에 백업한다
즉 속도는 메모리급, 안정성은 디스크급으로 설계되어 있음
| 항목 | 설명 |
| 저장 위치 | RAM(인메모리) |
| 데이터 접근 속도 | 매우 빠름(매우) |
| 백업 방식 | RDB, AOF 등 디스크 기반 옵션 제공 |
| 활용 사례 | 캐시, 세션 관리, 순위 시스템, 실시간 알림 등 |
* Redis는 단순 캐시가 아니라, 빠른 데이터 접근이 필요한 모든 상황에서 활용 가능한 고성능 데이터 저장소임
2. 싱글 스레드 기반 고성능 구조
Redis는 단일 스레드(Event Loop) 구조로 동작함
즉, 한번에 한번만 처리하지만 논블로킹 I/O 모델을 통해 초당 수십만 건의 요청을 처리할 수 있음
| 장점 | 설명 |
| 경쟁 조건 없음 | 하나의 스레드만 실행되므로 락(Lock) 불필요 |
| Context Switching 없음 | CPU 오버헤드 최소화 |
| 높은 처리량 | 수십만 QPS(Queries Per Second) 가능 |
* DB는 다중 스레드로 병렬 처리하지만, Redis는 단일 스레드로도 더 높은 효율을 낼 수 있다
Redis의 주요 데이터 구조
Redis는 단순 문자열 캐시를 넘어, 다양한 데이터 구조를 지원하고 있음
이 덕에 복잡한 데이터 조작도 별도의 DB없이 메모리에서 즉시 처리할 수 있음
1. 데이터 구조 요약
| 타입 | 설명 | 주요 활용 사례 |
| String | 기본 데이터 타입(문자열, 숫자 등) | 세션 토큰, 사용자 이름 등 |
| List | 순서가 있는 데이터 목록 | 메시지 큐, 최근 검색 기록 등 |
| Set | 중복 없는 조합 | 좋아요 사용자 목록, 태그 관리 |
| Sorted Set(ZSet) | 점수 기반 정렬 집합 | 랭킹 시스템, 점수 집계 |
| Hash | Key - Value 쌍의 객체형 데이터 | 사용자 프로필, Json 구조 |
| Bitmap / HyperLogLog | 비트연산 또는 통계 집계용 | 방문자 수, 클릭 수 |
2. 예제 명령어
/**
* 1) String(단일 값)
* - 가장 기본 타입 : key - > string value
* - 대표 사용 : 간단한 사용 값, 토큰, 카운터(증감은 INCR / DECR)
* - 주의 : 덮어쓰기(SET)는 기존 값이 사라짐. TTL이 필요하다면 SET key value EX <sec> 사용
*/
// 사용자 1의 이름을 Alice로 저장하기
SET user:1:name "Alice" // 새로 저장 또는 덮어쓰기
// 저장된 이름 읽기
GET user:1:name // "Alice" 출력
/**
* 참고 : 만료시간(예를 들어 60초)까지 함께 저장하려면
* SET user:1:name "Alice" EX 60
*/
/**
* 주의 : 숫자 카운터의 경우 SET 대신 INCR/DECR 권장
* INCR page:view:home
* -> 1씩 증가함
*
* GET page:view:home
* -> 1 출력됨
*/

/**
* 2) List(순서가 있는 큐 / 스택)
* - 대표 사용 : 최근 기록(타임라인), 작업 큐(왼쪽 PUSH, 오른쪽은 POP)
* - LPUSH : 왼쪽(머리)에 삽입 -> 새 값이 앞에 옴(최근 항목이 인덱스 0)
* - LRANGE : start stop : 구간 조회(stop = -1이면 끝까지)
* -주의 : 길이 무한 증가 방지를 위해 Trim 또는 maxlen 정책을 병행함
*/
// 최근 검색어를 왼쪽에 차례대로 삽입하기 (가장 최근이 맨 앞)
LPUSH recent:search "Redis"
// ["Redis"]
LPUSH recent:search "Spring"
// ["Spring", "Redis"]
// 전체 목록 조회(0부터 끝까지)
LRANGE recent:search 0 -1
// ["Spring", "Redis"]
/**
* 최근 N개만 유지하고 싶다면 : LTRIM recent:search 0 19
* -> 상위 20개만 보존함
*/
/**
* 3) Set(중복 없는 조합)
* - 대표 사용 : 좋아요한 사용자의 집합, 팔로워 목록 등 "중복 제거"가 필요한 경우
* - SADD : 원소 추가(중복 자동 제거)
* - SMEMBERS : 모든 원소 조회하기(순서 보장 x)
* - SISMEMBER : 특정 원소 포함 여부 체크(0(1))
*/
// 게시글 100번을 좋아요한 사용자 집합에 1, 2, 3 추가
SADD like:post:100 user:1 user:2 user:3
// {user:1, user:2, user:3}
// 좋아요 사용자 전체 조회(순서 없이)
SMEMBERs like:post:100
// {"user:2", "user:1", "user:3"}와 같이 순서없음
/**
* 사용자 2가 좋아요를 했는지 확인하기
* SISMEMBER like:post:100 user:2
* 1(참), 0(거짓)
*/
/**
* 4) Sorted Set(정렬된 집합, 점수(score) + 값)
* - 대표 사용 : 랭킹, 점수판, 만료시각을 score로 쓰는 일정 정렬 등
* - ZADD score member: score 기준 오름차순 정렬
* - ZRANGE start stop WITHSCORES: 인덱스 구간 조회(낮은 점수 -> 높은 점수)
* - ZREVRANGE: 높은 점수 -> 낮은 점수(내림차순 랭킹에 유용함)
*/
// 랭킹 집합에 점수와 이름 추가하기(score가 낮을수록 앞임)
ZADD ranking 100 "Alice"
// {"Alice":100}
ZADD ranking 200 "Bob"
// {"Alice":100, "Bob":200}
// 오름차순(낮은점수 -> 높은점수)으로 조회하기 + 점수도 함께
ZRANGE ranking 0 -1 WITHSCORES
// ["Alice","100"]
/**
* 일반적인 "1등이 점수 높은 사람"이라면, ZREVRANGE 사용하기
* ZREVRANGE ranking 0 -1 WITHSCORES
* ["Bob","200","Alice","100"]
*/
/**
* 5) Hash(필드가 여러개인 객체)
* - 대표 사용 : 사용자 / 상품처럼 속성이 여러개인 "한 개체"를 하나의 키에 저장
* - HSET key field value ... : 여러 필드를 한번에 설정하기
* - HGETALL key : 모든 필드/값 조회하기 (갯수가 많으면 HSCAN 고려하기)
* - HGET key field : 단일 필드 조회하기
*/
// user:1 해시에 name, age 필드 설정하기
HSET user:1 name "Alice" age 25
// {name:"Alice", age:"25"} -> 숫자도 문자열로 저장됨
// 전체 필드 조회하기(필드와 값이 번갈아서 나옴)
HGETALL user:1
// ["name","Alice","age","25"] 와 같이 번갈아서 나옴
/**
* 부분 조회 : HGET user:1 age
* "25" 가 출력됨
* 주의 : 필드 수가 매우 많으면 HGETALL 대신 HSCAN으로 분할 조회가 안전하다!
*/
* Redis는 데이터 타입이 다양하므로, 적절한 구조를 선택하는 것이 성능과 메모리 효율에 큰 영향을 미친다고 한다
Redis의 영속성(Persistence)
Redis는 인메모리 시스템이지만, 데이터를 잃지 않기 위해서 두가지 영속성 옵션을 제공한다고 함
1. RDB(Redis Database Snapshot)
- 일정 주기로 전체 데이터를 스냅샷 형태로 디스크에 저장함
- 서버 재시작시 마지막 스냅샷을 불러온다
save 900 1 # 900초(15분) 내 1회 이상 변경되면 저장하기
save 60 1000 # 1분 내 1000건이상 변경 시 저장하기
| 항목 | 설명 |
| 파일명 | dump.rdb |
| 장점 | 복원 속도 빠름, 백업이 용이함 |
| 단점 | 주기적 저장이라 최근 변경 데이터 손실 가능 |
2. AOF(Append Only File)
- 모든 쓰기 명령(SET, LPUSH 등)을 순차적으로 파일에 기록한다
- 장애가 발생하면 명령을 다시 실행해서 복구할 수 있음
appendonly yes
appendfsync everysec
| 항목 | 설명 |
| 파일명 | appendonly.aof |
| 장점 | 데이터 손실 최소화 |
| 단점 | 파일 크기가 커지고 복구 시간이 길다 |
3. RDB + AOF 혼합 전략
Redis는 두 방식을 병행하여, 속도와 안전성의 균형을 맞출 수 있음!
| 방식 | 특징 |
| RDB(Redis Database Snapshot) | 빠른 백업 및 복원 |
| AOF(Append Only File) | 안정적인 실시간 보존 |
| 혼합 | 고속성과 안정성을 동시에 확보 가능 |
* 실무 운영환경에서는 대부분 RDB + AOF를 병행해서 사용한다고 함
단, 개발 환경에서는 단순히 RDB만 설정해도 충분하다고 한다
Redis 클러스터링과 고가용성 구조
대규모 트래픽 환경에서 Redis는 클러스터 구조를 통해 성능과 안정성을 높일 수 있음
1. Redis 클러스터 구조
| 구성요소 | 역할 |
| Master Node | 실제 데이터 저장 및 요청 처리 |
| Replica Node | Master 복제본 유지, 장애 시 승격됨(Failover) |
| Slot | 데이터를 해시 기반으로 분산 저장함(0 ~ 16383 slot) |
클러스터는 자동으로 데이터 샤딩(Sharding)을 수행하여 부하를 분산한다고 함
2. Sentinel 기반 고가용성
Sentinel은 Redis 서버의 상태를 모니터링하고, 장애가 발생하면 자동으로 복구(Failover) 해줌
| 구성 요소 | 설명 |
| Sentinel | Redis 인스턴스 상태 감시 |
| Master | 쓰기 처리 담당 |
| Replica | 읽기 처리 + 복제 유지 |
| Failover | 장애시 Replica를 Master로 승격함 |
팁
* Redis는 단순 캐시뿐만 아니라 Pub/Sub, 메시지 큐, 세션 스토리지 등에도 자주 활용된다
* CPU가 많은 서버에서는 여러 Redis 인스턴스를 띄워 분산 실행하면 성능이 향상된다고 함
* TTL(Time To Live)를 반드시 설정해야 메모리 누수(Cache Leak)를 방지할 수 있다
* 모니터링 명령어 : INFO, MONITOR, SLOWLOG GET -> 이러한 명령어는 운영 중 필수 점검 항목임
정리
| 구분 | 내용 |
| 저장 구조 | 인메모리 기반 초고속 접근 |
| 처리 구조 | 싱글 스레드 기반 논블로킹 I/O |
| 데이터 구조 | String, Hash, List, Set, ZSet 등 다양함 |
| 영속성 | RDB, AOF, 혼합 지원 |
| 확장성 / 가용성 | 클러스터링 및 Sentinel 구성 가능 |
'Spring Boot > Cache' 카테고리의 다른 글
| 분산 캐시의 이해와 Redis : 분산 캐시 구현 시 고려사항 (0) | 2026.01.17 |
|---|---|
| 분산 캐시의 이해와 Redis : 분산 캐시 활용 패턴 (0) | 2026.01.17 |
| 분산 캐시의 이해와 Redis : 분산 캐시의 필요성 (0) | 2026.01.17 |
| 캐시 모니터링과 문제 해결 : 일반적 캐시 문제와 해결 방법 (0) | 2026.01.15 |
| 캐시 모니터링과 문제 해결 : 캐시 성능 분석 (0) | 2026.01.15 |