Redis는 데이터를 메모리에 저장하는 초고속 데이터베이스다.
쉽게 말하면 “키(Key)”와 “값(Value)”을 짝으로 보관하는 메모리 상자다.
보통 DB보다는 훨씬 빠르게 읽고 쓸 수 있어서, 캐시나 세션 저장소로 자주 쓰인다.
Redis는 Key-Value 형태로 데이터를 저장한다.
예를 들어 user:1 → pong 이런 식이다.
| 자료형 | 설명 | 예시 |
|---|---|---|
| String | 가장 기본. 숫자·문자열 | SET user:1 pong |
| List | 순서가 있는 목록 | LPUSH queue task1 |
| Set | 중복 없는 집합 | SADD members pong |
| Hash | Key 안에 또 Key-Value | HSET user:1 name pong age 25 |
| Sorted Set | 점수로 정렬된 리스트 | ZADD rank 100 pong |
| Stream | 로그형 데이터 저장소 | XADD mystream * msg "hello" |
| 활용 분야 | 설명 | 예시 |
|---|---|---|
| 캐시(Cache) | 자주 쓰는 데이터를 잠깐 보관 | 상품 목록, 사용자 정보 |
| 세션(Session) | 로그인 상태 유지 | sess:123 → userId=7 |
| 카운터(Counter) | 조회수, 추천수, 요청 수 | INCR page:view |
| 랭킹(Ranking) | 점수 순으로 정렬 | 게임 점수판 |
| 작업 큐(Queue) | 비동기 작업 순서 처리 | 메일 발송 대기열 |
| Pub/Sub | 실시간 알림, 채팅 | 새 알림 브로드캐스트 |
Redis는 기본적으로 메모리에 데이터를 둔다.
하지만 디스크 저장 옵션을 설정하면 꺼져도 다시 불러올 수 있다.
| 방식 | 설명 | 특징 |
|---|---|---|
| RDB | 일정 주기로 전체 스냅샷 저장 | 빠름, 일부 손실 가능 |
| AOF | 모든 명령을 로그로 저장 | 안정적, 용량 큼 |
| 혼합 모드 | 두 방법을 같이 사용 | 안전성과 속도 절충 |
SET user:pong "hello"
GET user:pong
# → "hello"
HSET user:1 name pong level 10
HGET user:1 name
# → "pong"
INCR visit:count
# 방문자 수 +1
docker run -d --name redis -p 6379:6379 redis
터미널에서 접속:
docker exec -it redis redis-cli
SET user:pong "developer"
GET user:pong
✅ 빠른 응답이 필요한 서비스
✅ 로그인 세션, 토큰 관리
✅ 실시간 랭킹, 카운터
✅ 큐·알림 등 간단한 비동기 처리
❌ 데이터 유실이 절대 안 되는 서비스
❌ 대용량 로그 장기 보관
❌ 복잡한 SQL 질의가 필요한 서비스
maxmemory) 를 지정하라서비스:엔티티:IDQ1. Redis는 데이터베이스야, 캐시야?
→ 둘 다 된다. 캐시로도, 간단한 데이터베이스로도 쓴다.
Q2. MySQL 대신 Redis만 써도 돼?
→ 영속성이 완벽히 필요한 서비스는 안 된다. Redis는 “빠른 임시 저장소”에 가깝다.
Q3. 데이터는 언제 사라져?
→ TTL이 끝나거나 메모리가 꽉 차면 오래된 키부터 삭제된다(LRU).
Q4. 왜 이름이 Redis야?
→ “REmote DIctionary Server”의 줄임말이다. “원격 사전 서버”라는 뜻이다.
Redis는 복잡한 DB보다 훨씬 단순하고 빠르다.
Redis는 메모리에 데이터를 저장하지만, 설정에 따라 디스크에 기록해 재시작 후 복구할 수 있다.
| 모드 | 설명 | 장점 | 단점 |
|---|---|---|---|
| RDB (Snapshot) | 일정 주기로 메모리 전체를 통째로 저장 | 속도 빠름, 복원 간단 | 주기 사이 데이터 유실 가능 |
| AOF (Append Only File) | 모든 명령을 로그 파일에 순차 저장 | 안정성 높음 | 파일 커짐, 쓰기 느림 |
| 혼합(Hybrid) | RDB + AOF 병행 | 속도와 안정성 균형 | 설정 복잡 |
save 900 1 # 900초(15분) 내 1개 이상 변경 시 RDB 저장
appendonly yes # AOF 활성화
appendfsync everysec # 1초마다 디스크 동기화
일반적으로 RDB와 AOF를 함께 사용해 복구 속도와 안정성을 동시에 확보한다.
여러 서버가 동시에 같은 자원에 접근할 때 Redis로 락을 걸어 순서를 보장할 수 있다.
SET lock:order:123 "pong" NX PX 30000
NX: 존재하지 않을 때만 생성PX: 만료 시간(ms 단위) 지정if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
여러 Redis 인스턴스에 락을 동시에 요청하고,
과반 이상(예: 5개 중 3개 이상) 성공 시 락을 획득한 것으로 간주한다.
분산 환경에서 락 안정성을 확보하는 방식이다.
Redis는 Master-Replica 구조를 지원한다.
Master는 쓰기, Replica는 읽기 전용으로 사용된다.
# Replica 노드에서
replicaof master-ip 6379
Sentinel은 Redis 노드를 감시하며 장애 발생 시 자동으로 복구를 수행한다.
Redis Cluster는 데이터를 여러 노드에 분산 저장하는 샤딩 구조다.
{}로 같은 슬롯에 묶을 수 있다SET user:{1001}:name pong
SET user:{1001}:age 25
두 키는 {1001} 해시태그 덕분에 같은 노드에 저장된다.
Redis의 병목은 대부분 메모리와 네트워크다.
다음 명령으로 상태를 점검한다.
| 항목 | 명령어 | 설명 |
|---|---|---|
| 클라이언트 연결 수 | INFO clients | 현재 연결된 수 |
| 메모리 사용량 | INFO memory | 전체 메모리 상태 |
| 키 개수 | DBSIZE | 저장된 키 수 |
| 캐시 효율 | INFO stats | hit/miss 비율 |
| 지연 분석 | latency doctor | 느린 명령 탐지 |
redis_exporter를 이용해 시각화| 목표 | 방법 |
|---|---|
| 응답 지연 감소 | 파이프라이닝으로 RTT 줄이기 |
| 메모리 효율 | Hash/List로 구조화해 작은 키 묶기 |
| TTL 관리 | EXPIRE로 만료 설정 |
| 키 삭제 부하 완화 | UNLINK로 비동기 삭제 |
| 대량 삽입 | MSET, PIPELINE 사용 |
| 장애 복구 속도 | AOF + RDB 백업 병행 |
┌──────────────┐
│ Sentinel │
└──────┬───────┘
│
┌─────────┴─────────┐
│ │
┌───────┐ ┌───────┐
│Master │◄─sync───►│Replica│
└───────┘ └───────┘
│ │
Client Client(Read)
Q1. RDB와 AOF를 함께 써도 되나요?
가능하다. RDB는 빠른 복구용, AOF는 변경 내역 보존용으로 병행하면 안전성과 속도를 동시에 얻을 수 있다.
Q2. 락을 걸면 성능이 떨어지나요?
락은 짧은 TTL을 갖기 때문에 부하가 크지 않다. 다만 락 획득 실패 시 재시도 로직을 별도로 관리해야 한다.
Q3. Replica는 자동으로 Master로 바뀌나요?
Sentinel을 구성해야 자동 승격이 가능하다. 단순 복제만으로는 수동 전환이 필요하다.
Q4. 클러스터를 꼭 써야 하나요?
단일 서버 메모리가 충분하다면 필요 없다. 데이터가 많거나 노드 장애 복구를 자동화하려면 필수다.
Q5. 가장 중요한 운영 포인트는?
TTL 설정, 메모리 한도 관리, 백업 주기, 모니터링 시스템 구축이다.
| 기능 | 목적 |
|---|---|
| RDB / AOF | 데이터 보존 |
| Redlock | 안전한 분산 락 |
| Replication | 읽기 부하 분산 |
| Sentinel | 장애 자동 복구 |
| Cluster | 수평 확장 |
| Monitoring | 성능 추적 |
Redis Stream은 로그처럼 데이터를 순서대로 저장하고 읽는 구조다.
메시지 큐(Message Queue)나 실시간 이벤트 로그처럼 작동하며,
Kafka보다 가볍고 Redis 내부에서 바로 사용할 수 있는 스트리밍 기능이다.
Stream은 “이름(Key)”과 “메시지(값)”으로 구성된다.
각 메시지는 고유한 ID(타임스탬프 기반)와 필드-값 쌍(field-value pairs) 을 가진다.
예:
mystream
├── 1697649531123-0 → { user=pong, msg="hi" }
├── 1697649532451-0 → { user=kim, msg="bye" }
| 명령어 | 설명 | 예시 |
|---|---|---|
XADD | Stream에 새 메시지 추가 | XADD mystream * user pong msg "hello" |
XRANGE | 범위로 메시지 조회 | XRANGE mystream - + COUNT 5 |
XREAD | 새 메시지를 실시간으로 읽기 | XREAD BLOCK 0 STREAMS mystream $ |
XDEL | 특정 메시지 삭제 | XDEL mystream 1697649531123-0 |
XLEN | 메시지 개수 확인 | XLEN mystream |
XTRIM | 오래된 메시지 정리 | XTRIM mystream MAXLEN 1000 |
Stream은 단순한 로그가 아니라 소비자 그룹(Consumer Group) 으로 병렬 처리도 가능하다.
즉, 여러 워커(worker)가 동시에 데이터를 나누어 읽는다.
[Producer]
│
▼
┌───────────┐
│ mystream │
└───────────┘
│ │
▼ ▼
[Worker1] [Worker2] ← 같은 Consumer Group 내에서 메시지를 분할 소비
| 명령어 | 설명 | 예시 |
|---|---|---|
XGROUP CREATE | 소비자 그룹 생성 | XGROUP CREATE mystream group1 0 |
XREADGROUP | 그룹 단위로 메시지 읽기 | XREADGROUP GROUP group1 pong STREAMS mystream > |
XACK | 처리 완료 알림 | XACK mystream group1 1697649531123-0 |
XPENDING | 아직 처리되지 않은 메시지 조회 | XPENDING mystream group1 |
XCLAIM | 다른 소비자가 미처 처리 못한 메시지를 가져오기 | XCLAIM mystream group1 pong 3600000 ID |
XADD로 메시지 추가XGROUP CREATE mystream group1 0XREADGROUP으로 메시지 읽기XACK으로 처리 완료 표시XPENDING으로 조회 가능XADD order_stream * orderId 1001 status "created"
XGROUP CREATE order_stream group_orders 0
XREADGROUP GROUP group_orders pong STREAMS order_stream >
출력:
1) "order_stream"
2) 1) 1) "1697649531123-0"
2) 1) "orderId"
2) "1001"
3) "status"
4) "created"
XACK order_stream group_orders 1697649531123-0
Stream은 무한히 커질 수 있다.
따라서 오래된 데이터는 XTRIM으로 관리해야 한다.
XTRIM mystream MAXLEN 1000
→ 1000개를 초과하면 자동 삭제.
~ 옵션을 사용하면 대략적인 수치로 더 빠르게 동작한다:
XTRIM mystream MAXLEN ~ 1000
| 구분 | Stream | List |
|---|---|---|
| 구조 | ID 기반 로그 | 단순 FIFO |
| 다중 소비자 | 지원 | 불가능 |
| 재처리(ACK) | 가능 | 불가능 |
| 순서 보장 | 보장 | 보장 |
| 용도 | 로그·메시지 큐 | 간단 큐, 스택 |
| 사례 | 설명 |
|---|---|
| 실시간 로그 수집 | 서버 로그를 Stream에 쌓고 소비자 그룹에서 분석 |
| 이벤트 큐 | 주문 처리, 알림 발송 등 비동기 작업 분배 |
| IoT 센서 수집 | 다수의 디바이스 데이터를 스트림으로 전송 |
| STT 로그 파이프라인 | 음성 인식 텍스트를 Stream으로 실시간 전송 후 LLM 배치 처리 |
XPENDING과 XCLAIM으로 미완료 메시지 재할당Q1. Stream은 Kafka를 완전히 대체할 수 있나요?
→ 장기 저장·고가용성이 필요한 대규모 스트리밍엔 Kafka가 낫다.
Redis Stream은 단일 서비스 내 경량 로그 큐로 적합하다.
Q2. Consumer Group을 쓰면 중복이 생기지 않나요?
→ 같은 그룹 내에서는 중복되지 않는다. 다만 서로 다른 그룹 간에는 중복 소비가 가능하다.
Q3. Stream은 메모리 초과 시 어떻게 되나요?
→ XTRIM으로 직접 크기를 제어해야 한다. 초과 시 자동 삭제는 없다.
Q4. 하나의 메시지를 두 개 이상의 소비자가 동시에 처리할 수 있나요?
→ 같은 그룹 내에서는 불가능하지만, 서로 다른 그룹을 만들면 가능하다.
| 항목 | 설명 |
|---|---|
| 구조 | 타임스탬프 기반 메시지 로그 |
| 장점 | 빠른 처리, 소비자 그룹, ACK 기반 재처리 |
| 핵심 명령 | XADD, XREAD, XACK, XPENDING, XTRIM |
| 사용처 | 실시간 이벤트 처리, 로그 수집, 큐 시스템 |
| 주의점 | XTRIM 관리, 그룹 중복 처리 주의 |
Redis Cluster는 여러 노드로 데이터를 분산(샤딩) 하여 처리하는 구조다.
단일 서버 메모리 한계를 넘어 확장성과 장애 복구 기능을 제공한다.
즉, 데이터를 여러 Redis 서버에 자동 분산 저장하고 일부 노드가 죽어도 계속 작동한다.
Cluster는 전체 키 공간을 16,384개의 해시 슬롯(hash slot) 으로 나눈다.
각 노드가 슬롯 일부를 맡아 데이터를 저장한다.
예를 들어 3노드 구조라면 다음과 같이 나뉜다:
| 노드 | 슬롯 범위 |
|---|---|
| Node A | 0–5460 |
| Node B | 5461–10922 |
| Node C | 10923–16383 |
Redis는 키 이름을 해싱(Hash)해서 어느 슬롯에 들어갈지 결정한다.
즉, 키가 다르면 저장되는 노드도 달라진다.
Redis는 CRC16 해시 함수를 사용해 키를 16,384개의 슬롯 중 하나로 매핑한다.
HASH_SLOT = CRC16(key) % 16384
같은 슬롯에 저장하려면 키 안에 해시태그 {} 를 넣는다.
SET user:{1001}:name pong
SET user:{1001}:level 10
두 키는 {1001}이 동일하므로 같은 슬롯(노드)에 저장된다.
이 방식으로 다중 키 연산(MGET, MSET, ZINTERSTORE 등)을 가능하게 한다.
| 역할 | 설명 |
|---|---|
| Master 노드 | 실제 데이터를 저장하고 요청 처리 |
| Replica 노드 | Master를 복제해 장애 시 자동 승격 |
| Cluster Bus | 노드 간 통신(7000번대 포트 사용) |
| Client Redirect | 클라이언트가 올바른 노드로 재요청 (MOVED 응답) |
| 기능 | 설명 |
|---|---|
| 샤딩(Sharding) | 키 공간을 여러 노드로 자동 분할 |
| Failover | Master 장애 시 Replica가 자동 승격 |
| 노드 자동 인식 | 새로운 노드 추가 시 슬롯 재분배 |
| 확장성 | 서버를 수평으로 늘려 성능 향상 |
| 무중단 복구 | 일부 노드 장애에도 전체 서비스 지속 |
# 클러스터 상태 확인
CLUSTER INFO
# 노드 목록 확인
CLUSTER NODES
# 슬롯 분포 확인
CLUSTER SLOTS
# 슬롯 이동 (데이터 리밸런싱)
CLUSTER ADDSLOTS <slot numbers>
# 키의 슬롯 확인
CLUSTER KEYSLOT mykey
6개 Redis 인스턴스를 띄운다 (3 Master + 3 Replica):
redis-server --port 7000 --cluster-enabled yes --cluster-config-file nodes-7000.conf
redis-server --port 7001 --cluster-enabled yes --cluster-config-file nodes-7001.conf
...
redis-server --port 7005 --cluster-enabled yes --cluster-config-file nodes-7005.conf
redis-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
--cluster-replicas 1: 각 Master당 1개의 Replica를 생성
user:1을 저장하려 함Client
│
├──> Node A (Master) ───> Node A' (Replica)
│
├──> Node B (Master) ───> Node B' (Replica)
│
└──> Node C (Master) ───> Node C' (Replica)
노드를 추가하면 슬롯을 재분배해야 한다.
Redis는 자동으로 슬롯을 이동시키며 균등하게 분산한다.
redis-cli --cluster reshard 127.0.0.1:7000
reshard 명령어 실행 시:
MOVED 응답 이용)장애 복구 시간은 보통 1~3초 내로 짧다.
| 항목 | 명령어 | 설명 |
|---|---|---|
| 노드 상태 | CLUSTER INFO | 전체 상태 점검 |
| 슬롯 분배 | CLUSTER SLOTS | 각 노드 슬롯 범위 |
| 키 슬롯 위치 | CLUSTER KEYSLOT key | 특정 키 위치 확인 |
| 복제 관계 | CLUSTER REPLICAS <node-id> | Replica 목록 |
| 장애 감지 | CLUSTER FAILOVER | 강제 승격 테스트 |
{}를 적극 활용해 다중 키 연산 최적화redis_exporter, Prometheus, GrafanaQ1. Sentinel과 Cluster는 어떻게 다르나요?
→ Sentinel은 단일 Master-Replica 구조의 자동 장애 복구만 담당한다.
Cluster는 데이터 분산(샤딩) + 장애 복구를 동시에 제공한다.
Q2. Cluster는 언제 써야 하나요?
→ 단일 서버 메모리가 부족하거나 TPS가 많을 때.
즉, 데이터가 커지고 읽기/쓰기가 많은 환경에서 필수다.
Q3. 클러스터 노드가 일부 죽으면 데이터는 날아가나요?
→ Replica가 있으면 자동 승격되어 유지된다. Replica가 없으면 일부 데이터 손실이 발생할 수 있다.
Q4. 클러스터에서도 RDB/AOF를 쓸 수 있나요?
→ 각 노드별로 개별 설정이 가능하다. 일반적으로 Master만 AOF를 활성화한다.
Q5. 트랜잭션은 지원하나요?
→ 같은 슬롯 내 키끼리는 가능하다. 서로 다른 슬롯의 키는 불가능하다.
| 항목 | 설명 |
|---|---|
| 분산 단위 | 16,384 슬롯 |
| 장애 복구 | Replica 자동 승격 |
| 데이터 분배 | CRC16 해시 기반 샤딩 |
| 장점 | 수평 확장, 무중단 복구 |
| 주의점 | 슬롯 이동 시 주의, 다중 키 제약 |
| 활용 | 대규모 캐시, 세션 클러스터, 실시간 분석 데이터 |
애플리케이션 간 데이터를 주고받을 때 메시지 브로커(Message Broker)를 사용한다.
Redis는 Pub/Sub, Stream을 통해 이를 처리하고,
Kafka·RabbitMQ는 별도의 전문 메시지 플랫폼으로 더 복잡한 기능을 제공한다.
각 기술의 동작 원리·장단점·적용 시점을 비교한다.
Redis Pub/Sub(Publish/Subscribe)는 실시간 메시지 전달 기능이다.
데이터를 채널(channel)에 발행(Publish)하면, 구독자(Subscriber)들이 즉시 수신한다.
메시지는 저장되지 않으며, 실시간으로만 전달된다.
SUBSCRIBE news
PUBLISH news "breaking update"
→ “news” 채널을 구독한 모든 클라이언트가 즉시 메시지를 받는다.
Pub/Sub과 달리, 메시지를 로그처럼 저장하고
소비자 그룹으로 분산 처리할 수 있다.
Pub/Sub이 실시간 전파용이라면,
Stream은 메시지 보존과 재처리까지 필요한 환경에 적합하다.
Kafka는 대규모 스트리밍 플랫폼이다.
수백만 건의 메시지를 디스크에 저장하고 여러 소비자 그룹이 병렬 처리한다.
RabbitMQ는 메시지 큐(MQ) 중심의 전통적 브로커다.
AMQP 프로토콜 기반으로, 메시지를 큐에 저장하고 소비자가 꺼내가는 구조다.
fanout, topic, direct)으로 메시지를 분배| 항목 | Redis Pub/Sub | Redis Stream | RabbitMQ | Kafka |
|---|---|---|---|---|
| 지속성 | ❌ 없음 | ✅ 있음 | ✅ 있음 | ✅ 있음 |
| 순서 보장 | 채널별 보장 | Stream 내 보장 | 큐 내 보장 | 파티션 내 보장 |
| ACK / 재처리 | ❌ 불가능 | ✅ 가능 | ✅ 가능 | ✅ 가능 |
| 확장성 | 단일 노드 중심 | 클러스터 가능 | 제한적 | 매우 우수 |
| 지연 시간 | 매우 낮음 (실시간) | 낮음 | 중간 | 약간 높음 |
| 구조 복잡도 | 매우 단순 | 중간 | 중간 | 복잡 |
| 대표 활용 | 채팅, 알림 | 이벤트 로그, 큐 | 주문, 결제 | 로그 스트리밍, 분석 |
| 상황 | 추천 기술 |
|---|---|
| 단순한 실시간 알림 | Redis Pub/Sub |
| 로그·큐형 이벤트 처리 | Redis Stream |
| 안정적인 메시지 큐(ACK 보장) | RabbitMQ |
| 대규모 로그 파이프라인 / 스트리밍 분석 | Kafka |
| Redis 이미 사용 중이며 간단한 비동기 처리만 필요 | Redis Stream으로 충분 |
Client → Redis Pub/Sub → 모든 연결 클라이언트에 즉시 전파
API Server → Redis Stream → Worker Consumer Group
App Logs → Kafka Topic → Spark/Flink → Storage/AI Server
Payment Service → RabbitMQ Exchange → Queue → Billing Service
| 기술 | 장점 | 단점 |
|---|---|---|
| Redis Pub/Sub | 초단순, 빠름 | 메시지 보존 불가, ACK 없음 |
| Redis Stream | 경량 큐, 재처리 가능 | 클러스터 설정 필요 |
| RabbitMQ | 안정적, 라우팅 유연 | 처리량 제한, 운영 복잡 |
| Kafka | 확장성·내구성 최고 | 설정 복잡, 약간의 지연 존재 |
Q1. Redis Pub/Sub으로 Kafka 대체 가능할까?
→ 불가능하다. Pub/Sub은 일시적 전파용이며 로그 저장, 오프셋, 재처리 기능이 없다.
Q2. Redis Stream과 RabbitMQ의 차이는?
→ 둘 다 큐 역할을 하지만, RabbitMQ는 확실한 전송·라우팅 중심,
Stream은 단순 큐 + 로그형 메시지 저장에 가깝다.
Q3. Kafka를 써야 하는 기준은?
→ 하루 수백만 건 이상 로그, 장기 보관, 순서 보장, 분석 연계가 필요할 때.
Q4. Redis Stream을 선택할 때 주의할 점은?
→ 메시지 보존 기간과 크기를 XTRIM으로 제한하고, 소비자 그룹 누락 메시지를 XPENDING으로 관리해야 한다.
Q5. 세 시스템을 함께 쓸 수도 있나?
→ 가능하다.
Kafka는 전체 로그 수집,
RabbitMQ는 비즈니스 이벤트 큐,
Redis Pub/Sub은 실시간 알림용으로 혼합 구성 가능하다.
| 구분 | Pub/Sub | Stream | RabbitMQ | Kafka |
|---|---|---|---|---|
| 데이터 보존 | ❌ | ✅ | ✅ | ✅ |
| 확장성 | 보통 | 높음 | 중간 | 매우 높음 |
| 복잡도 | 낮음 | 중간 | 중간 | 높음 |
| 적합 시점 | 실시간 알림 | 경량 큐 | 안정 메시지 큐 | 로그 스트리밍 |
결론: