개요
- DB, 캐시, 메시지 브로커 등으로 사용되는 오픈소스 in-memory 저장소
- 단순 key-value가 아니라 자료구조 서버에 가까움 : String, Hash, List, Set, Sorted Set, Bitmap 등을 명령 하나로 다룸
- 도입 전에 캐시로 쓸지 원본 저장소로 쓸지부터 정해야 함 : 캐시면 유실을 허용하고 TTL을 붙이면 되지만, 저장소면 영속화·백업·메모리 증설 비용을 전부 떠안음
구조

Single Thread

- Redis는 싱글 스레드 모델인데, 패킷 단위로 명령어들을 받아 수행함
- 패킷 : Client와 Redis 간의 통신 단위이며, “SET mykey myvalue” 같은 명령이 패킷에 담겨 Redis로 전송됨
- ProcessCommand : 패킷이 모여 처리되는 과정이며, Client로부터 도착한 순서대로 처리·실행함을 의미함
- 단순한 GET, SET 명령어는 괜찮지만 KEYS, FLUSHALL 등의 명령어는 데이터 Full Scan을 하기에 자칫하다간 병목이 발생할 수 있음
- 명령 하나가 오래 걸리면 뒤에 줄 선 모든 요청이 같이 밀림. 운영 중인 서버에서 KEYS는 쓰지 말고, 커서 기반의 SCAN으로 나눠 훑어야 함
- Redis 6부터 I/O 멀티스레딩이 들어왔지만 소켓 읽기·쓰기만 나눠 가질 뿐, 명령 실행 자체는 여전히 싱글 스레드임
- 범인을 찾을 땐 slowlog :
SLOWLOG GET으로 임계치를 넘은 명령과 인자를 확인함
Memory
- Redis가 싱글 스레드 모델을 채택한 이유 중 하나가 Memory와 연관이 있음
- Memory Access 지연 감소 : Redis는 데이터를 저장하고 빠르게 제공하는 것이 목적이기에, 데이터를 Memory에 저장하고 직접 Access하여 관리함, 그래서 속도가 매우 빠른 편
- Atomic 보장 : 데이터의 원자성, 일관성을 위해 모든 연산을 순차적으로 처리함, 락 없이도 단일 명령은 원자적으로 끝남
- Memory에 데이터를 저장하기에 Redis 클러스터를 재시작하거나 메모리를 삭제하면 데이터도 함께 삭제됨. 캐시로 쓸 땐 원본이 DB에 있으니 문제가 없지만, 저장소로 쓴다면 영속화 설정이 필수임
- RDB : 특정 시점의 스냅샷을 통째로 덤프하는 방식임, 복구가 빠른 대신 마지막 스냅샷 이후의 데이터는 유실됨
- AOF(Append-Only File) : 쓰기 명령을 로그화하여 디스크에 저장하는 방식임, 재시작 시 로그를 다시 실행해 지속성을 보장함. 유실 구간이 짧은 대신 파일이 커져 주기적인 rewrite가 필요함
- 유실을 최소화하려면 둘을 함께 켜고 AOF로 복구, RDB는 백업본으로 둠
- 메모리가 한계에 닿았을 때의 동작은 maxmemory-policy로 정해짐. 기본값이 noeviction이라 지정하지 않으면 메모리가 찼을 때 쓰기 명령이 에러로 떨어짐
- 캐시 용도면 allkeys-lru 또는 allkeys-lfu로 두어 안 쓰는 키부터 밀어냄
- TTL 없는 키가 쌓이면 어떤 정책을 써도 결국 메모리가 차오르니, 캐시 키엔 만료 시간을 붙이는 것이 기본
- 단일 인스턴스는 그 자체가 SPOF임. 복제(replica)와 Sentinel로 장애 조치를 두고, 데이터가 한 대의 메모리를 넘어서면 Cluster로 샤딩함