약 한달 전. DB 락 전략 - 분산락 에서 Redis 를 언급한 적이 있다.
지금 내가 알고있는 Redis라는 건
빠른 저장소와공용 창고 느낌으로만 알고 있다.
하지만, 아는 내용이 너무 추상적이다 보니 깊이 있게 조사하고 싶어졌다.

Redis는 세계에서 가장 빠른 인메모리 데이터베이스로,
다양한 자료구조와 고성능 기능을 제공하여
캐시,
NoSQL 저장소,
벡터 검색 등 폭넓은 활용이 가능한 솔루션입니다.
RAM(메모리)을 기반으로 동작하는
오픈소스 인메모리 Key-Value 데이터 저장소이다.
단순히 캐시로만 사용하는 것이 아니라,
다양한 자료구조와 기능을 지원하는 고성능 NoSQL 데이터베이스이기도 하다.
다양한 데이터 구조 지원
└ 문자열, 해시, 리스트, 세트, 정렬된 세트, 비트맵, 하이퍼로그로그, 지리공간 인덱스, 스트림 등
고성능 기능
└ 원자적 연산, 비동기 복제, 자동 장애 조치, Lua 스크립팅, LRU 방식의 키 제거
유연한 지속성 옵션
└ 디스크에 주기적으로 데이터 저장 또는 로그 방식 저장 선택 가능
폭넓은 프로그래밍 언어 지원 및 ANSI C로 개발
클러스터링과 고가용성 기능 내장
요청(값 보내기) -> 레디스가 메모리에 저장 ->
( 선택사항 : 디스크/DB 에 저장 ) -> 응답
단순하고 기본적인 자료구조
카운터, 토큰, 플래그 등등에 사용
(Command)
set <key> <value> | ex > set users:1:name kun ( SET )
get <key> | ex > set users:1:name ( GET )
del <key> | ex > set users:1:name ( DEL )
+ 유효기간 까지?
setex <key> <sec> <value> | setex users:1:name 30 kun1
순서가 존재하는 값의 목록 스택/큐 와 비슷한 자료구조
채팅 로그, 작업 큐에 사용
(Command)
lpush <key> <value> | ex > lpush users:1:name kun (LEFT PUSH|맨 앞에 추가)
rpush <key> <value> | ex > rpush users:1:name kun (RIGHT PUSH|맨 뒤에 추가)
lpop <key> | ex > lpop users:1:name ( 맨앞에서 꺼내기 )
rpop <key> | ex > lpop users:1:name ( 맨뒤에서 꺼내기 )
lrange <key> <start> <last<end:-1>> | ex> lrange users:1:name 0 -1
( 시작 인덱스 0 부터 끝까지(-1) 모든 요소 가지오기
lindex <key> <index> | ex> lindex users:1:name 3 (key 의 3번 인덱스 가져오기)
lset <key> <index> <value> | ex> lset users:1:name 2 kun2 (key 의 2번 인덱스 kun2 변경)
llen <key> | ex> llen users:1:name ( 길이 확인 )
중복되지 않고 순서가 보장되지 않는 자료구조
태그, 관심사, 교집합, 합집합 연산에 사용
(Command)
sadd <key> <value> | ex > sadd tags:1 music (추가)
sadd <key> <v1> <v2> | ex > sadd tags:1 music travel (여러 개 추가)
smembers <key> | ex > smembers tags:1 (모든 값 조회)
srem <key> <value> | ex > srem tags:1 music (값 제거)
scard <key> | ex > scard tags:1 (총 개수 확인)
sismember <key> <val> | ex > sismember tags:1 music (값 존재 확인: 1 또는 0)
spop <key> | ex > spop tags:1 (랜덤 요소 하나 제거)
srandmember <key> | ex > srandmember tags:1 (랜덤 요소 보기)
자동 정렬 기능이 포함된 Set 자료구조
우선순위 큐 또는 리더보드에 사용
(Command)
zadd <key> <score> <value> | ex > zadd leaderboard 100 "un" (추가)
zadd <key> <s1> <v1> <s2> <v2> | ex > zadd leaderboard 200 "min" 150 "hana" (여러 개 추가)
zrange <key> <start> <stop> | ex > zrange leaderboard 0 -1 (오름차순 조회)
zrevrange <key> <start> <stop> | ex > zrevrange leaderboard 0 -1 (내림차순 조회)
zscore <key> <value> | ex > zscore leaderboard "un" (점수 확인)
zincrby <key> <inc> <value> | ex > zincrby leaderboard 50 "un" (점수 증가)
zrem <key> <value> | ex > zrem leaderboard "hana" (값 제거)
zrank <key> <value> | ex > zrank leaderboard "un" (오름차순 순위)
zrevrank <key> <value> | ex > zrevrank leaderboard "un" (내림차순 순위)
zcard <key> | ex > zcard leaderboard (총 항목 수)
작은 K-V 를 하나의 키 아래 묶어서 저장하는 자료구조
객체처럼 사용이 가능
(Command)
hset <key> <field> <value> | ex > hset user:1 name "kun" (필드에 값 설정)
hget <key> <field> | ex > hget user:1 name (필드 값 가져오기)
hdel <key> <field> | ex > hdel user:1 name (필드 삭제)
hmset <key> <f1> <v1> <f2> <v2> | ex > hmset user:1 name "kun" age "20" (여러 필드 설정)
hmget <key> <f1> <f2> | ex > hmget user:1 name age (여러 필드 값 가져오기)
hgetall <key> | ex > hgetall user:1 (모든 필드-값 조회)
hkeys <key> | ex > hkeys user:1 (모든 필드 이름만 조회)
hvals <key> | ex > hvals user:1 (모든 값만 조회)
hexists <key> <field> | ex > hexists user:1 name (필드 존재 확인: 1/0)
hlen <key> | ex > hlen user:1 (필드 개수)
hincrby <key> <field> <inc> | ex > hincrby user:1 age 1 (숫자 증가)
비트(0/1) 단위로 정보를 저장하는 공간 절약형 구조
로그인 여부, 출석 체크, ON/OFF 상태 표현에 사용
(Command)
setbit <key> <offset> <value> | ex > setbit active_users 7 1 (8번째 비트를 1로 설정)
getbit <key> <offset> | ex > getbit active_users 7 (8번째 비트 조회)
bitcount <key> | ex > bitcount active_users (1인 비트 수 세기)
bitop <op> <dest> <src1> <src2> | ex > bitop AND online a b (여러 비트맵 연산)
고유한 값들의 개수를 근사치로 매우 적은 메모리로 계산하는 자료구조
방문자 수 카운트, 이벤트 수 집계에 최적화 되어 사용
(Command)
pfadd <key> <element> | ex > pfadd visitors user1 (요소 추가)
pfcount <key> | ex > pfcount visitors (고유 요소 수 추정)
pfmerge <dest> <key1> <key2> | ex > pfmerge total visitorsA visitorsB (합치기)
시간 순으로 기록되는 로그형 데이터 구조
메시지 큐, 실시간 데이터 수집, 이벤트 저장 등에 사용
(Command)
xadd <key> * <field> <value> | ex > xadd chat * user kun message "hi" (항목 추가)
xrange <key> <start> <end> | ex > xrange chat - + (전체 메시지 조회)
xread count 2 streams chat 0 | ex > xread count 2 streams chat 0 (읽기)
xdel <key> <id> | ex > xdel chat 1689000000-0 (메시지 삭제)
xack <key> <group> <id> | ex > xack chat mygroup 1689000000-0 (처리 확인)
위도/경도를 저장하고 거리 계산 등을 할 수 있는 자료구조
geoadd는 반드시 경도 - 위도 - 이름 순으로 입력
반경 내 사용자 찾기, 거리 계산 등 위치 기반 서비스에 사용
(Command)
geoadd <key> <lon> <lat> <name> | ex > geoadd cities 127.0 37.5 "Seoul" (좌표 추가)
geopos <key> <name> | ex > geopos cities "Seoul" (좌표 조회)
geodist <key> <m1> <m2> <unit> | ex > geodist cities Seoul Busan km (거리 계산)
georadius <key> <lon> <lat> <r> m | ex > georadius cities 127.0 37.5 100 m (주변 검색)
단순히 Redis만 사용하고 관계형 데이터베이스(RDBMS)를 사용하지 않는 것의 단점은 무엇인가요?
메모리 기반 저장소 - Redis는 모든 데이터를 메모리에 저장하므로, 데이터가 메모리 용량을 초과할 수 없습니다. - 반면, RDBMS는 데이터를 디스크에 저장하고 필요한 일부만 메모리에 캐싱하므로 메모리보다 큰 데이터셋을 처리할 수 있습니다. 쿼리 언어 없음, 유연성 부족 - Redis는 SQL 같은 쿼리 언어를 지원하지 않고, 단지 명령어만 존재합니다. - 즉, 즉석 쿼리가 불가능하며, 모든 데이터 접근 방식은 개발자가 미리 설계해야 합니다. 이로 인해 유연성이 크게 떨어집니다. 제한적인 영속성 보장 - Redis는 스냅샷 또는 append-only file(AOF) 방식으로 데이터를 지속시킬 수 있지만, - RDBMS처럼 트랜잭션 로그, 체크섬, 시점 복구 등 강력한 영속성 기능은 제공하지 않습니다. 보안 기능 제한 - Redis는 인스턴스 단위의 단순한 접근 제어만 제공합니다. - 반면 RDBMS는 객체 단위의 세밀한 권한 관리 및 룰 기반 보안 기능을 제공합니다. 스케일링 어려움 - Redis는 단일 CPU 코어에서 단일 스레드로 동작합니다. - 확장성을 위해선 여러 인스턴스를 직접 구성하고 클라이언트 측에서 샤딩을 구현해야 합니다. - 반면 RDBMS는 일반적으로 멀티코어를 활용한 멀티프로세스 또는 멀티스레드 구조를 지원하며, 클라이언트 레벨 병렬 처리도 기본적으로 지원합니다.
실시간 분석(Real-time analytics)
- 애플리케이션은 Redis를 이용해 대량의 데이터를 실시간으로 저장하고 처리할 수 있으며,
이를 통해 기업은 데이터를 빠르게 분석하고 시각화하여 신속한 비즈니스 의사결정을 내릴 수 있습니다.
온라인 게임(Online gaming)
- 게임 소프트웨어는 Redis를 활용하여 플레이어 프로필, 게임 점수, 리더보드 등
게임 상태 정보를 저장 및 관리할 수 있습니다.
- 이를 통해 빠르고 끊김 없는 게임 플레이 환경이 가능해집니다.
이커머스(E-commerce)
- 전자상거래 애플리케이션은 Redis를 이용해 상품 카탈로그, 사용자 프로필, 장바구니 정보 등을
저장 및 관리할 수 있습니다.
- 이를 통해 사용자에게 빠르고 효율적인 쇼핑 경험을 제공합니다.
소셜 미디어(Social media)
- 소셜 앱은 Redis를 통해 사용자 프로필, 친구 목록, 뉴스피드 등
소셜 미디어 상호작용 데이터를 저장하고 관리할 수 있습니다.
- 이는 빠르고 부드러운 사용자 경험을 가능하게 합니다.
언제 레디스의 K,V 를 사용하나요? - StackOverflow
질문답변
하지만 Redis는 전통적인 관계형 데이터베이스를 대체하는 NoSQL 대안은 아닙니다. Redis는 RDBMS 세계에서 제공하는 표준 기능들(예: 복잡한 쿼리 처리 등)을 지원하지 않기 때문이며, 오히려 그런 쿼리는 Redis의 성능을 저하시킬 수도 있습니다. 대체로 MongoDB나 CouchDB 같은 문서형 데이터베이스가 RDBMS의 대체제로 더 적합하고, Redis는 특정 기능을 빠르게 처리하거나, 고급 자료구조가 필요한 경우에 보완적으로 사용하는 것이 가장 적절합니다.
모든 데이터를 Redis에 저장하나요? - StackOverflow
질문답변
Redis는 캐시 용도로 최적화된 도구입니다. 무엇을 캐싱할지, 그리고 정말 캐시가 필요한지를 먼저 결정해야 해요. 이건 결국 애플리케이션의 규모에 따라 달라집니다. 예를 들어, 게시글(articles)이 자주 변경되고, 사용자가 많지 않다면, Redis는 굳이 필요하지 않을 수도 있습니다. 그리고 Redis에서는 검색이 불가능하다는 점을 기억하세요. 예를 들어 SELECT articles WHERE author='foo' 같은 쿼리는 Redis에선 할 수 없어요. 반면에, 사용자 수가 많아져서 DB 부하가 심각해지는 상황이라면, 모든 게시글의 HTML을 미리 렌더링해서 Redis에 저장해두는 방법을 고려할 수 있어요. 그렇게 하면 DB나 웹 서버의 부하를 줄일 수 있겠죠. 하지만 이 방식도 어떤 게시글을 캐싱할지 미리 알고 있어야만 가능합니다.

모든 DB 중 Redis 는 7위를 기록하고 있으며,
NoSQL 에서는 2위
K,V 형식에서는 1위를 차지하고 있다.