
기존엔 redis image 만 사용했었는데, 다른 이미지도 존재했다.
redis/redis-stack-server 는 여러 플러그인이 추가된 Redis Stack 서버 이미지이며, 확률형 데이터, JSON 문서 등을 사용하고 싶다면 선택하면된다.
redis/redis-stack는 redis/redis-stack-server에 Redis Insight가 추가된 이미지이다.
Redis Insight를 같이 사용하고 싶다면 선택하면 된다.
docker-compose.yml
services:
redis-stack:
image: redis/redis-stack
container_name: redis-stack-compose
restart: always
environment:
REDIS_ARGS: "--requirepass systempass"
ports:
- 6379:6379
- 8001:8001
해당 yml 파일로 redis를 docker container 로 띄우게 된다면 id : defuault, password : systempass 인 redis가 6379 포트로 띄워지고, redis/redis-stack 이미지를 사용했기에 redis insight가 함께 설치된다.
8001 포트로 redis insight 에 접속할 수 있게 된다.
redis insight은 redis의 데이터들을 시각적으로 보여주는 역할을 하는 클라이언트 툴이다.
가장 기본적인 자료형이며, 저장할 수 있는 최대 크기는 512MB이다.
SET user:email alex@example.com
GET user:emailSET <key> <value>: key에 value 문자열 데이터를 저장, "으로 공백 구분GET <key>: key에 저장된 문자열 반환만약 저장된 데이터가 정수 데이터라면 데이터를 바로 증가, 감소가 가능하다.
SET user:count 1
INCR user:count
DECR user:countINCR key: key에 저장된 데이터를 1 증가DECR key: key에 저장된 데이터를 1 감소여러 Key - Value를 한번에 다루고 싶다면 MSET, MGET을 활용할 수 있다.
MSET user:name alex user:email alex@example.com
MGET user:name user:emailMSET key value [key value …]: key value의 형태로 주어진 인자들을 각 key에 value를 저장MGET key [key]: 주어진 모든 key에 해당하는 데이터를 반환.여러 문자열 데이터를 Linked List의 형태로 보관하는 자료형이다. Linked List이기 때문에, 중간의 데이터 보다는 양끝의 데이터, 즉 스택 또는 큐 처럼 사용할 수 있다.
PUSH 또는 POP을 L 또는 R과 조합하여, 왼쪽 또는 오른쪽에 데이터를 추가 / 제거가 가능합니다.
LPUSH user:list alex # [alex]
LPUSH user:list brad # [brad, alex]
RPUSH user:list chad # [brad, alex, chad]
RPUSH user:list dave # [brad, alex, chad, dave]
LPOP user:list # brad
RPOP user:list # chadLPUSH key value: key에 저장된 리스트의 앞쪽에 value를 저장RPUSH key value: key에 저장된 리스트의 뒤쪽에 value를 저장LPOP key: key에 저장된 리스트의 앞쪽에서 값을 반환 및 제거RPOP key: key에 저장된 리스트의 뒤쪽에서 값을 반환 및 제거리스트를 사용하면서 흔히 사용하는 길이 구하기, 범위 내 원소 반환하기 등의 기능도 제공한다.
LLEN user:list
LRANGE user:list 0 3
LRANGE user:list 0 -1LLEN key: key에 저장된 리스트의 길이를 반환LRANGE key start end: key의 start부터 end까지 원소들을 반환LLEN은 없는 Key를 대상으로 하면 0이 되지만, 다른 자료형을 저장한 Key를 대상으로 하면 오류가 발생한다.
LRANGE의 경우 (언제나 그렇듯) 시작을 0으로 생각하고,
end가 실제 길이를 벗어나도 오류가 발생하진 않는다.start > end일 경우 빈 결과가 반환된다.문자열의 집합이다. 집합인 만큼 중복값을 제거하며, 순서가 존재하지 않는다.
SADD user:java alex # [alex]
SADD user:java brad # [alex, brad]
SADD user:java chad # [alex, brad, chad]
SREM user:java alex # [brad, chad]
SMEMBERS user:java # [alex, brad, chad]
SISMEMBER user:java brad # true
SISMEMBER user:java dave # falseSADD key value: key에 저장된 집합에 value를 추가SREM key value: key에 저장된 집합의 value를 제거SMEMBERS key: key에 저장된 집합의 모든 원소를 반환SISMEMBER key value: key에 저장된 집합에 value가 존재하는지 반환SCARD key: key에 저장된 집합의 크기를 반환여기에 복수의 집합이 있다면, 교집합, 합집합 등의 기능을 제공한다. 결과 집합 자체를 반환하기도, 결과 집합의 크기를 반환하기도 한다.
# 다른 Set에 추가한 뒤,
SADD user:python alex
SADD user:python dave
SINTER user:java user:python # [alex]
SUNION user:java user:python # [alex, brad, chad, dave]
SINTERCARD 2 user:java user:python # 1SINTER key1 key2: key1과 key2에 저장된 집합들의 교집합의 원소들을 반환SUNION key1 key2: key1과 key2에 저장된 집합들의 합집합의 원소들을 반환SINTERCARD number key1 [key2 ...]: number개의 key에 저장된 집합들의 교집합의 크기를 반환중복을 허용하지 않으며, 어떤 데이터의 존재 여부를 확인하는 SISMEMBER 같은 경우 O(1)의 시간복잡도를 가지고 있다. 그래서 중복 없는 방문 수, 인증 토큰 블랙리스트 등을 구현할때 활용할 수 있다.
단, 매우 높은 방문 수를 기록하는 서비스인 경우 실제 데이터가 필요하지 않다면, 근사값을 돌려주는 확률형 자료형을 사용하는게 권장된다.
Redis 전체가 Map 이라면 Hash는 Map<String, Map<String, String>>의 형식이라고 생각할 수 있다.
HSET user:alex name alex age 25
HSET user:alex major CSE
HGET user:alex name
HGET user:alex age
HMGET user:alex age major
HGETALL user:alex
HKEYS user:alex
HLEN user:alexHSET key field value [field value]: key의 Hash에 field에 value를 넣는다. 한번에 여러 field - value 쌍을 넣어줄 수 있다.HGET key field: key에 저장된 Hash의 field에 저장된 value를 반환. 없는 field의 경우 null.HMGET key field [field]: key에 저장된 Hash에서 복수의 field에 저장된 value를 반환.HGETALL key: key에 저장된 Hash에 저장된 field - value를 전부 반환.HKEYS key: key에 저장된 Hash에 저장된 field를 전부 반환HLEN key: key에 저장된 Hash에 저장된 field의 갯수를 반환Hash는 본래 하나의 키에 복잡한 데이터 (객체의 데이터 라던지)를 하나의 키에 저장하는 용도로 주로 활용되고, 공식 문서에서도 여러 Key에 걸쳐 객체의 데이터를 표현하기 보단 Hash를 자주 활용할 것을 권장하고 있습다.
장바구니 같은 기능은 사용자별로, 어떤 물품이 몇개나 담겨있는지와 같은 정보가 포함되어야 한다. 사용자 마다 Hash 데이터를 생성하고, 물품 - 갯수 형식으로 데이터를 저장하면 사용자별 장바구니를 쉽게 저장할 수 있다.
이름처럼 정렬된 집합이다. 기본적으로 Set과 동일하게, 유일한 값들만 유지하지만 여기에 더해 각 값들에 score라고하는 실수를 함께 보관한다. 그리고 데이터를 가져올 때, score를 바탕으로 정렬하여 값들을 가져올 수 있다.
ZADD user:ranks 10 alex
ZADD user:ranks 9 brad 11 chad
ZADD user:ranks 8 dave
ZINCRBY user:ranks 2 alex
ZRANK user:ranks alex
ZRANGE user:ranks 0 3
ZREVRANK user:ranks alex
ZREVRANGE user:ranks 0 3ZADD key score member [score member ...]: key의 Sorted Set에 score를 점수로 가진 member를 추가, 이미 있는 member의 경우 새로운 score를 설정ZRANK key member: key의 Sorted Set의 member의 순위를 오름차순 기준으로 0에서 부터 세서 반환ZRANGE key start stop: key의 Sorted Set의 member들을 start 부터 stop 순위까지 오름차순 기준으로 반환ZREVRANK key member: key의 Sorted Set의 member의 순위를 내림차순 기준으로 0에서 부터 세서 반환ZREVRANGE key start stop: key의 Sorted Set의 member들을 start 부터 stop 순위까지 내림차순 기준으로 반환ZINCRBY key increment member: key의 Sorted Set의 member의 score를 increment 만큼 증가 (음수를 전달하면 감소)대표적으로 리더보드나 Rate Limiter, 즉 순위와 관련된 기능을 만드는데 사용된다.
그 외 자료형과 상관없이 사용할 수 있는 명령들이 있다. 이 중 대표적으로 많이 사용하는 건, Key를 제거하기 위한 DEL, 만료시각 설정을 위한 EXPIRE 등이 있다.
SET somekey "to be deleted"
DEL somekey
SET expirekey "to be expired"
EXPIRE expirekey 5
EXPIRETIME expirekeyDEL key: key(와 저장된 데이터)를 제거EXPIRE key seconds: key의 TTL(유효시각)을 seconds로 설정, seconds초가 지나면 key 제거EXPIRETIME key: key가 만료되는 시각을 Unix Timestamp로 반환모든 Key를 제거하고 싶다면 FLUSHDB를 사용할 수 있다.
-- String - INCR(++), DECR(--)
-- INCR posts:{id}
INCR posts:1
INCR posts:2
INCR posts:3
-- 오늘의 조회수를 따로 관리하고 싶다면
INCR articles:1:today
-- 하루가 지난 시점에서
RENAME articles:1:today articles:20XX-XX-XX
-- 초기화
FLUSHDB
-- SET
SADD posts:1 alex
SADD posts:1 brad
SADD posts:1 chad
-- 해당 게시글의 조회수
SCARD posts:1
SADD posts:2 alex
SADD posts:2 chad
SCARD posts:2
-- 각 원소가 원래 있는 값이라면 0 , 하나라도 추가되었다면 1 반환
SADD posts:1 alex bard chad
-- 그래서 0이라면 스킵하고, 1일 경우엔 Sorted Set에 넣어서 리더보드 기능 구현
ZINCRBY posts:ranks 1 posts:1
ZINCRBY posts:ranks 1 posts:2
-- 가장 높은 조회수의 글을 뽑아냄
-- 곧 사라질 예정인 명령어
ZREVRANGE posts:ranks 0 0
ZRANGE posts:ranks 0 0 REV
Docker 에서 제공하는 redis image 들의 종류를 알아봤는데, 클라이언트 툴 형식으로 제공되고 있는줄 처음 알았다. 지금은 IntelliJ 유료버전 에서 제공되는 DataGrip 을 통해 쉽게 여러 데이터베이스들을 통합해서 사용할 수 있는 툴을 사용하는데 익숙해져서 굳이 사용하지 않을 듯 하지만, Redis가 처음이고 데이터베이스 통합 연결 툴을 사용하지 않는 사람이라면 도커를 통해 쉽게 띄울 수 있어 사용할 만 한 것 같다.
Redis가 싱글스레드 기반의 빠른 입출력을 제공해주는 데이터베이스 이지만, 사용할때 O(1) 가 아닌 명령어들에 대해서는 한 번 더 생각하고 사용해야 한다.