
โ Redis๋?(Remote Dictionary Service)
์๋๊ฐ ์ด์ด์ด์ดใ ใ ์ฒญ ๋น ๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋ค๋ฅธ SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ด ์ฌ์ฉํ๊ฒ ๋๋ค.
Redis๋ Key Value In-memory ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ค.
(SQL, MongoDB ๋ฑ์ ๋์คํฌ์์ ๊ฐ์ ์ฝ์ด์ค๋๋ผ ์๋์ ์ผ๋ก ๋๋ฆฌ๋ค.)
์ฅ์ : ๋น ๋ฅด๋ค.
๋จ์ : ๋น์ธ๋ค.
์ฉ๋์ด ํ๋ ๋์คํฌ์ฒ๋ผ ์ถฉ๋ถํ์ง๊ฐ ์๊ธฐ์, ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ค์ ๋ณด์กฐํ๋ ์ฉ๋๋ก ์ฌ์ฉํ๋ค.
โ ์ค์น
brew install redis
brew services start redis
โ Usecase
๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํด์ cli๋ฅผ ํ์ฑํํ๋ค.
redis-cli
GET, SET
โฐโ redis-cli โโฏ
127.0.0.1:6379> SET hello world
OK
127.0.0.1:6379> GET hello
"world"
127.0.0.1:6379> SET hello bye
OK
127.0.0.1:6379> GET hello
"bye"
127.0.0.1:6379>
Redis์ SET์ ์ธ์ ๋ ๋ฎ์ด์ด๋ค.
๋ช
๋ น์ด๋ ๋์๋ฌธ์ ์๊ด์์ง๋ง ๋ฐ์ดํฐ์ ๊ตฌ๋ถํ๊ธฐ ์ํ์ฌ ๋๋ฌธ์๋ก ์
๋ ฅํ๋ ๊ฒ์ ์ถ์ฒ.
string์ ์ ์ฅํ ๋ world๋ "world"๋ ๋๊ฐ๋ค.
Convention
127.0.0.1:6379> SET users:1 nico
OK
127.0.0.1:6379> GET users:1
"nico"
127.0.0.1:6379>
users:1 ์ด๋ฐ ์์ผ๋ก users ๋ค์ userID๋ฅผ ๋ถ์ด๋ ๊ฒ ๊ด์ต์ด๋ค.(๊ณต์๋ฌธ์๋ ์ด ๋ฐฉ์์ผ๋ก ํจ)
DEL
127.0.0.1:6379> DEL users:1 hello
(integer) 2
127.0.0.1:6379>
์ง์ ํด์ ์ญ์
FLUSHALL
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379>
๋ฉ๋ชจ๋ฆฌ ์ ์ฒด ์ญ์
Key ๋ง๋ฃ ์์ ์ง์ ๊ฐ๋ฅ
127.0.0.1:6379> SET users:1 nico NX EX 10
OK
NX: users:1 ๊ฐ ์์ ๋ nico ๊ฐ์ ์ ์ฅํด๋ผ.
XX: users:1 ๊ฐ ์์ ๋ nico ๊ฐ์ ์ ์ฅํด๋ผ.
EX seconds: ๋ง๋ฃ์๊ฐ ์ง์
MGET, MSET
127.0.0.1:6379> MSET users:1 nico users:2 lynn users:3 lanna
OK
127.0.0.1:6379> MGET users:1 users:2 users:3
1) "nico"
2) "lynn"
3) "lanna"
127.0.0.1:6379>
Multiple๋ก GET, SET ํ ์ ์์
INCR, DECR
127.0.0.1:6379> SET visitors 0
OK
127.0.0.1:6379> INCR visitors
(integer) 1
127.0.0.1:6379> INCR visitors
(integer) 2
127.0.0.1:6379>
INCR๋ฅผ ์ฌ์ฉํ์ฌ string ๋ฐ์ดํฐ ํ์ ์ ์ฆ๊ฐ ์ํฌ ์ ์๋ค.
127.0.0.1:6379> SET visitors 0
OK
127.0.0.1:6379> INCR visitors
(integer) 1
127.0.0.1:6379> INCR visitors
(integer) 2
127.0.0.1:6379> DECR visitors
(integer) 1
127.0.0.1:6379>
DECR๋ ๋ฐ๋
INCRBY, DECRBY
127.0.0.1:6379> DECR visitors
(integer) 1
127.0.0.1:6379> INCRBY visitors 10
(integer) 11
127.0.0.1:6379> DECRBY visitors 5
(integer) 6
127.0.0.1:6379>
์ฆ๊ฐ, ๊ฐ์ ๋จ๊ณ ์ง์ ๊ฐ๋ฅ
LPUSH, RPUSH
127.0.0.1:6379> LPUSH l 1
(integer) 1
127.0.0.1:6379> LPUSH l 2
(integer) 2
127.0.0.1:6379> LPUSH l 3
(integer) 3
127.0.0.1:6379> LPUSH l 4
(integer) 4
127.0.0.1:6379> LPUSH l 5
(integer) 5
127.0.0.1:6379> LRANGE l 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379>
์ผ์ชฝ์์ ์ถ๊ฐ๋จ. ๋จผ์ ๋ค์ด๊ฐ ๊ฐ์ด ์ค๋ฅธ์ชฝ์ผ๋ก ๊ฐ๊ฒ ๋จ
127.0.0.1:6379> RPUSH l 0
(integer) 6
127.0.0.1:6379> LRANGE l 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "0"
127.0.0.1:6379>
RPUSH๋ ๋ฐ๋
LPOP, RPOP
127.0.0.1:6379> LRANGE l 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "0"
127.0.0.1:6379> LPOP l
"5"
127.0.0.1:6379> RPOP l
"0"
127.0.0.1:6379>
127.0.0.1:6379> RPOP l 2
1) "1"
2) "2"
127.0.0.1:6379>
์ฌ๋ฌ ๊ฐ popํ ์๋ ์์
LLEN
127.0.0.1:6379> LLEN l
(integer) 2
List length ๊ตฌํ๊ธฐ
LSET
127.0.0.1:6379> LRANGE l 0 -1
1) "4"
2) "3"
127.0.0.1:6379> LSET l 1 hello
OK
127.0.0.1:6379> LRANGE l 0 -1
1) "4"
2) "hello"
127.0.0.1:6379>
index๋ฅผ ์ฌ์ฉํด์ ํด๋น index์ ๊ฐ์ ๋ฐ๊พธ๊ธฐ
https://redis.io/docs/latest/commands/?group=list
Commands
Redis Cloud Fully managed and integrated with Google Cloud, Azure, and AWS.
redis.io
Set
List์ ๋น์ทํ์ง๋ง List์ฒ๋ผ ์ ๋ ฌ๋์ด์์ง ์๊ณ , ์ค๋ณต๋ value๋ฅผ ํ์ฉํ์ง ์๋๋ค.
SADD
127.0.0.1:6379> SADD votes:song:1 user:1
(integer) 1
127.0.0.1:6379> SADD votes:song:1 user:2
(integer) 1
127.0.0.1:6379> SADD votes:song:1 user:2
(integer) 0
์ค๋ณต ํ์ฉ x
SMEMBERS
127.0.0.1:6379> SMEMBERS votes:song:1
1) "user:1"
2) "user:2"
ํด๋น key๋ฅผ ๊ฐ์ง๋ set์ value๋ค์ ๋ณด์ฌ์ค
SISMEMBER
127.0.0.1:6379> SISMEMBER votes:song:1 user:1
(integer) 1
127.0.0.1:6379> SISMEMBER votes:song:1 user:3
(integer) 0
user:1์ด votes:song:1์ member์ธ์ง ํ์ธ
SCARD
127.0.0.1:6379> SCARD votes:song:1
(integer) 2
Cardinality์ ์ค์๋ง
Set ์์์ ๊ฐ์๋ฅผ ๋ณด์ฌ์ค
SINTER
127.0.0.1:6379> SINTER votes:song:1 votes:song:2
1) "user:3"
๊ต์งํฉ ๊ตฌํ๊ธฐ(intersection)
SDIFF
127.0.0.1:6379> SDIFF votes:song:1 votes:song:2
1) "user:2"
2) "user:1"
votes:song:1์๋ ์์ง๋ง votes:song:2์๋ ์๋ ์์๋ค
SUNION
127.0.0.1:6379> SUNION votes:song:1 votes:song:2
1) "user:4"
2) "user:1"
3) "user:2"
4) "user:3"
5) "user:5"
ํฉ์งํฉ
SREM
127.0.0.1:6379> SREM votes:song:1 user:1
(integer) 1
127.0.0.1:6379> SMEMBERS votes:song:1
1) "user:2"
2) "user:3"
member ์ญ์
Hash
Key์ Value ์์ ๋ชจ์
Redis์ Hash๋ ์ค์ฒฉ๋ Hash๋ฅผ ์ง์ํ์ง ์๋๋ค.
HSET, HGET, HGETALL
127.0.0.1:6379> HSET player:1 name nico xp 0 health 100
(integer) 3
127.0.0.1:6379> HGET player:1 name
"nico"
127.0.0.1:6379> HGETALL player:1
1) "name"
2) "nico"
3) "xp"
4) "0"
5) "health"
6) "100"
HINCRBY
127.0.0.1:6379> HINCRBY player:1 xp 10
(integer) 10
127.0.0.1:6379> HGETALL player:1
1) "name"
2) "nico"
3) "xp"
4) "10"
5) "health"
6) "100"
127.0.0.1:6379> HINCRBY player:1 health -10
(integer) 90
HMGET
127.0.0.1:6379> HMGET player:1 xp health
1) "10"
2) "90"
Multiple GET
HEXISTS
127.0.0.1:6379> HEXISTS player:1 xp
(integer) 1
Sorted Set
๊ฐ๊ฐ์ value์ ์ ์๋ฅผ ๋ถ์ฌํ ์ ์๊ณ , ๊ทธ ์ ์์ ๋ฐ๋ผ ์ ๋ ฌ๋๋ค.
127.0.0.1:6379> ZADD scores 1 user:1 2 user:2 10 user:3 6 user:4
(integer) 4
127.0.0.1:6379> ZRANGE scores 0 -1
1) "user:1"
2) "user:2"
3) "user:4"
4) "user:3"
WITHSCORES
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "user:1"
2) "1"
3) "user:2"
4) "2"
5) "user:4"
6) "6"
7) "user:3"
8) "10"
ZREVRANGE
127.0.0.1:6379> ZREVRANGE scores 0 -1
1) "user:3"
2) "user:4"
3) "user:2"
4) "user:1"
ZRANK
127.0.0.1:6379> ZRANK scores user:1
(integer) 0
127.0.0.1:6379> ZRANK scores user:3
(integer) 3
Sorted Set์์ ๋ฑ์๊ฐ ๋ช ๋ฑ์ธ์ง ๋ณผ ์ ์๋ค.
ZADD
127.0.0.1:6379> ZADD scores 20 user:1
(integer) 0
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "user:2"
2) "2"
3) "user:4"
4) "6"
5) "user:3"
6) "10"
7) "user:1"
8) "20"
๋ด๋ถ ๋ฐ์ดํฐ ์์
ZINCRBY
127.0.0.1:6379> ZINCRBY scores 30 user:2
"32"
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "user:4"
2) "6"
3) "user:3"
4) "10"
5) "user:1"
6) "20"
7) "user:2"
8) "32"
ZRANGEBYSCORE
127.0.0.1:6379> ZRANGEBYSCORE scores 7 50
1) "user:3"
2) "user:1"
3) "user:2"
์ ์๊ฐ 7์ ์ด์ 50์ ์ดํ์ธ ์ฌ์ฉ์๋ค๋ก ์ ํ
ZCOUNT
127.0.0.1:6379> ZCOUNT scores 5 10
(integer) 2
5์ ์ด์ 10์ ์ดํ์ ์ ์๋ค ์นด์ดํธ
ZREM
127.0.0.1:6379> ZREM scores user:2
(integer) 1
127.0.0.1:6379> ZRANGE scores 0 -1
1) "user:4"
2) "user:3"
3) "user:1"
127.0.0.1:6379>
user:2 ์ญ์
โ Python ํ๊ฒฝ์์ Redis ์ฌ์ฉํ๊ธฐ
Redis ์ค์น
(hiredis๋ redis์ ์ต์ ํ ๋ฒ์ )
pip install 'redis[hiredis]'
Redis ์ฌ์ฉ
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
r.set("hello", "world")
print(r.get("hello"))
r.hset("users:1", mapping={"name": "nico", "age": 19999})
print(r.hgetall("users:1"))
decode_responses๋ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋์ฝ๋ฉํด์ ๋ฌธ์์ด๋ก ๋ฐ์์ง๋ฅผ ์ค์ ํ๋ ์์ฑ
mapping์ hash ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ๋ console์์์ฒ๋ผ ๋ถํธํ๊ฒ ์์ฑํ ํ์์์ด ๊ตฌ์กฐํ ์ํฌ ์ ์๋๋ก ํ๋ ์์ฑ
(python์์ ์์ฑํ ์ฟผ๋ฆฌ ๋ด์ฉ์ console์์๋ ํ์ธ ๊ฐ๋ฅํ๋ค.)
SQL๊ณผ ๊ฐ์ด ์ฌ์ฉ
import redis
import sqlite3
import json
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
conn = sqlite3.connect("movies_download.db")
cur = conn.cursor()
def make_expensive_query():
redis_key = "director:movies"
cached_results = r.get(redis_key)
if cached_results:
print("cache hit")
return json.loads(cached_results)
else:
print("cache miss")
res = cur.execute("SELECT COUNT(*), director FROM movies GROUP BY director;")
all_rows = res.fetchall()
r.set(redis_key, json.dumps(all_rows), ex=20)
return all_rows
v = make_expensive_query()
conn.commit()
conn.close()
r.close()
โ TypeScript ํ๊ฒฝ์์ redis ์ฌ์ฉํ๊ธฐ
bun add redis
or
npm install redis
์ Python์ 'redis[hiredis]'๋ฅผ ์ค์นํ๋๊ฐ?
Python์ ์ฑ๋ฅ์ ์ํด hiredis ๊ฐ์ C ํ์ฅ์ ์ถ๊ฐ๋ก ์ค์นํ์ง๋ง, TypeScript ํ๊ฒฝ์์๋ ๊ธฐ๋ณธ Redis ํด๋ผ์ด์ธํธ๊ฐ ์ถฉ๋ถํ ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ์ต์ ์์ด ์ฌ์ฉํ๋ค
Redis Client ์ฐ๊ฒฐ
import { createClient } from "redis";
const client = createClient();
์๋ฌด๋ฐ ์ต์ ์์ด ์ฐ๊ฒฐํ๋ฉด ๊ธฐ๋ณธ๊ฐ์ผ๋ก localhost์ port:6379์ ์ฐ๊ฒฐ๋จ(redis-cli๋ก port ๋ณผ ์ ์์)
Usage
import { createClient } from "redis";
const client = createClient();
await client.connect();
await client.flushAll();
await client.hSet("users:1", {
username: "nico",
password: "1234",
});
const r = await client.hGetAll("users:1");
console.log(r);
await client.close();
Bun์ ์ฌ์ฉํ๊ณ ์์ง ์๊ฑฐ๋, ์ฌ์ฉํ๊ณ ์๋ Node.js ๋ฒ์ ์ ๋ฐ๋ผ์ ์์ ๊ฐ์ด ๋ชจ๋ ์ต์์์์ await๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ ์ ์๋ค.
(์ด๋ฐ ๊ฒฝ์ฐ์ ๋ชจ๋ await ์ฝ๋๋ฅผ async ํจ์ ์์ ๋ฃ์ด์ ์ฒ๋ฆฌํด์ผ ํ๋ค.)