Redis) 이것이 레디스다 5 - 데이터 구조와 명령어 (작성 중)

레디스는 거대한 키-값 저장소 즉, 거대한 Map 저장소이다.

레디스 데이터 구조와 명렁어

  • 문자열 데이터

저장 가능한 문자열의 크기는 최대 512MB
문자열 데이터 저장 시 구조체로 변환하여 저장하며 이를 레디스 객체형이라고 부른다.

mset, mget : 문자열의 다중 저장과 조회

1
2
3
4
5
6
127.0.0.1:6379> mset key1 val1 key2 val2
OK
127.0.0.1:6379> mget key1 key2 key3
1) "val1"
2) "val2"
3) (nil)

setnx : 조회 후 해당 키의 값이 없으면 값을 저장

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> set key1 val1
OK
127.0.0.1:6379> setnx key1 val100
(integer) 0
127.0.0.1:6379> get key1
"val1"
127.0.0.1:6379> setnx key2 val2
(integer) 1
127.0.0.1:6379> get key2
"val2"

msetnx : setnx을 여러번 실행한 효과 (하나의 키라도 기존에 값이 존재할 경우 값은 모두 저장되지 않는다.)

1
2
3
4
5
6
7
8
9
10
11
127.0.0.1:6379> msetnx key1 val1 key2 val2 key3 val3
(integer) 1
127.0.0.1:6379> mget key1 key2 key3
1) "val1"
2) "val2"
3) "val3"
127.0.0.1:6379> msetnx key3 val300 key4 val4
(integer) 0
127.0.0.1:6379> mget key3 key4
1) "val3"
2) (nil)

setnxmsetnx는 원자성을 보장한다.

MSETNX is atomic, so all given keys are set at once. It is not possible for clients to see that some of the keys were updated while others are unchanged.

Redis doc : https://redis.io/commands/msetnx

getset : 이전 값을 가져오고 새로운 값을 set한다.

1
2
3
4
5
6
127.0.0.1:6379> getset key1 val1
(nil)
127.0.0.1:6379> getset key1 val2
"val1"
127.0.0.1:6379> get key1
"val2"

incr, decr : 값을 1씩 증/감
incrby, decrby : 값을 인자 만큼 증/감

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> set key1 1
OK
127.0.0.1:6379> incr key1
(integer) 2
127.0.0.1:6379> decr key1
(integer) 1
127.0.0.1:6379> incrby key1 10
(integer) 11
127.0.0.1:6379> decrby key1 100
(integer) -89

증감처리는 64-bit signed integer 범위내에서만 가능

1
2
3
4
127.0.0.1:6379> set overflow 9223372036854775807
OK
127.0.0.1:6379> incr overflow
(error) ERR increment or decrement would overflow

strlen : 문자열의 길이를 조회한다.

1
2
3
4
127.0.0.1:6379> set val1 hello
OK
127.0.0.1:6379> strlen val1
(integer) 5

  • 비트 연산

setbit, getbit : 입력된 오프셋 위치에 bit값을 저장하고 조회한다.
bitcount : 해당 키의 비트 중 1의 갯수를 조회한다.

1
2
3
4
5
6
7
8
127.0.0.1:6379> setbit bit 0 1
(integer) 0
127.0.0.1:6379> setbit bit 1 0
(integer) 0
127.0.0.1:6379> setbit bit 3 1
(integer) 0
127.0.0.1:6379> bitcount bit
(integer) 2
비트연산은 어디에 쓸까?

사용자의 날짜별 로그인 이력을 저장하는데 사용하는건 어떨까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# id가 100인 사용자의 2019.04.28의 로그인 이력을 저장한다.
127.0.0.1:6379> setbit login-history-20190428 100 1
(integer) 0

# id가 300인 사용자의 2019.04.28의 로그인 이력을 저장한다.
127.0.0.1:6379> setbit login-history-20190428 300 1
(integer) 0

# id가 200인 사용자의 2019.04.28의 로그인 이력을 조회한다.
127.0.0.1:6379> getbit login-history-20190428 200
(integer) 0

# 2019.04.28의 전체 로그인한 사용자의 수 조회
127.0.0.1:6379> bitcount login-history-20190428
(integer) 2

  • 해시 데이터

Map구조로 되어있는 데이터 : Map의 키를 필드, 값은 그대로 값이라고 지칭한다.
해시 데이터에는 2^23 - 1개의 필드와 값을 저장할 수 있다.

hset, hget : 해시 데이터에 값을 저장하고 조회한다.

1
2
3
4
127.0.0.1:6379> hset hash key1 val1
(integer) 1
127.0.0.1:6379> hget hash key1
"val1"

hmset, hmget : 해시 데이터에 다중으로 값을 저장하고 조회한다.

1
2
3
4
5
6
127.0.0.1:6379> hmset hash key1 val1 key2 val2
OK
127.0.0.1:6379> hmget hash key1 key2 key3
1) "val1"
2) "val2"
3) (nil)

hkeys : 모든 필드를 조회한다. (O(N)이므로 사용시 유의)
hvals : 모든 값을 조회한다. (O(N)이므로 사용시 유의)
hlen : 저장된 필드의 수를 조회한다.
hdel : 지정한 필드를 제거한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
127.0.0.1:6379> hmset hash key1 val1 key2 val2
OK
127.0.0.1:6379> hkeys hash
1) "key1"
2) "key2"
127.0.0.1:6379> hvals hash
1) "val1"
2) "val2"
127.0.0.1:6379> hlen hash
(integer) 2
127.0.0.1:6379> hdel hash key1
(integer) 1
127.0.0.1:6379> hlen hash
(integer) 1127.0.0.1:6379> hmset hash key1 val1 key2 val2
OK
127.0.0.1:6379> hlen hash
(integer) 2

hincrby, hincrbyfloat : 해당 필드의 값을 증가시킨다. (감소는 없다)

1
2
3
4
5
6
7
8
127.0.0.1:6379> hset devson age 0
(integer) 1
127.0.0.1:6379> hincrby devson age 29
(integer) 29
127.0.0.1:6379> hincrby devson height 0
(integer) 0
127.0.0.1:6379> hincrbyfloat devson height 171.5
"171.5"

  • 셋 데이터

중복을 허용하지 않는 집합 형태의 자료구조

sadd : 셋에 저장한다. (O(N)이지만 이는 저장하려는 요소에 비례한다. 저장된 요소의 양과는 무관)
scard : 요소의 수를 조회한다.
spop : 요소를 pop하고 제거한 요소를 돌려준다.
srem : 요소를 지정하여 제거한다.

1
2
3
4
5
6
7
8
127.0.0.1:6379> sadd set val1 val2 val3
(integer) 3
127.0.0.1:6379> spop set
"val2"
127.0.0.1:6379> srem set val1
(integer) 1
127.0.0.1:6379> scard set
(integer) 1

sismember : 해당 요소가 있는지 확인한다. (있으면 1 / 없으면 0)
smove : 요소를 다른 셋에 이동시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
127.0.0.1:6379> sadd set val1 val2
(integer) 2

# 조회
127.0.0.1:6379> sismember set val1
(integer) 1
127.0.0.1:6379> sismember set val3
(integer) 0

# 이동 후 요소의 수 조회
127.0.0.1:6379> smove set new-set val1
(integer) 1
127.0.0.1:6379> scard set
(integer) 1
127.0.0.1:6379> scard new-set
(integer) 1

집합연산

집합연산의 경우 비용이 매우 비싸기 때문에 반드시 필요한 상황에서만 사용하자

sdiff : 차집합
sinter : 교집합
sunion : 합집합

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
127.0.0.1:6379> sadd user1:friend user2 user3 user4
(integer) 3
127.0.0.1:6379> sadd user2:friend user1 user4 user6
(integer) 3

127.0.0.1:6379> sdiff user1:friend user2:friend
1) "user2"
2) "user3"
127.0.0.1:6379> sdiff user2:friend user1:friend
1) "user1"
2) "user6"

127.0.0.1:6379> sinter user1:friend user2:friend
1) "user4"

127.0.0.1:6379> sunion user1:friend user2:friend
1) "user4"
2) "user1"
3) "user2"
4) "user3"
5) "user6"

  • 정렬된 셋 데이터

기존 셋 데이터에서 score 값을 통해 요소들을 정렬시킨다.


(작성 중)

Share