devoong2
devoong2
devoong2
전체 방문자
오늘
어제

인기 글

최근 글

  • Category (34)
    • Java (4)
    • Spring (13)
    • JPA (4)
    • DesignPattern (1)
    • 동시성 (Concurrency) (3)
    • 회고 (1)
    • Redis (1)
    • Network (3)
    • Kafka (2)
    • Spring Batch (2)

최근 댓글

반응형
hELLO · Designed By 정상우.
devoong2

devoong2

Redis의 기본 자료구조 및 사용법
Redis

Redis의 기본 자료구조 및 사용법

2023. 2. 10. 23:10
반응형

Redis의 기본 자료구조 및 사용법

Redis는 key/value 형태로 저장되는 database이며 다음과 같은 자료구조를 지원합니다.

  • Strings
  • Lists
  • Sets
  • Hashes
  • SortedSets
  • Streams
  • Geospatial indexes
  • Bitmaps
  • Bitfields
  • HyperLogLog

이중에서 자주 사용되는 Strings, Lists, Sets, Hashes, SortedSets 에 대해 정리했습니다.

Strings

  • 일반적인 문자열 형태이다
  • 카운터 구현(incr, decr), 비트 연산을 수행하는 기능을 지원한다.
  • Redis 문자열의 최대 길이는 512MB이다

SET SETNX SETEX MSET
GET MGET
DEL
INCR INCRBY DECR DECRBY

SET

값을 저장한다.
SET {key} {value}

GET

값을 조회한다.
GET {key}

> SET user devoong2
OK
> GET user
"devoong2"

DEL

키를 삭제한다
DEL {key}

> DEL user
(integer) 1
> KEYS *
(empty array)

SETNX

키가 존재하지 않는 경우에만 저장한다 (SET if Not eXists)
SETNX {key} {value}

> SETNX user devoong2
OK
> GET user
"devoong2"
> SETNX user woobeen
false
> GET user
"devoong2"

SETEX

지정한 시간이 지나면 삭제되는 키를 저장 (시간 단위는 s)
SETEX {key} {value} {s}

> SETEX user devoong2 30
OK
> TTL user (TTL -> 남은 시간을 알려주는 명령어)
(integer) 30

조회시마다 현재 남은 expire 시간을 알려준다


MSET

여러개의 데이터를 한번에 저장
MSET {key1} {value1} {key2} {value2} ...

> MSET key1 Hello key2 Hello2
OK
> GET key1
"Hello"
> GET key2
"Hello2"

MGET

여러개의 데이터를 한번에 조회
MGET {key1} {key2}

> MGET key1 key2
1) "hello"
2) "hello2

INCR

숫자를 1씩 증가, redis에 값이 없을시에는 0부터 증가
incr {key}

> INCR key1
(integer) 1
> INCR key1
(integer) 2
> GET key1
"2"

> SET key1 10
OK
> INCR key1
(integer) 11
> GET key1
"11"

주의사항

  • 문자열의 경우에는 에러가 발생함
  • redis 정수의 범위를 벗어나는 경우에도 에외 발생
  • 9,223,372,036,854,775,808(2^63) ~ 9,223,372,036,854,775,807(2^63-1)

INCRBY

지정한 숫자(정수)만큼 증가, redis에 값이 없을경우 0을 기준으로 증가
INCRBY {key1} {n}

> INCRBY key1 5
(integer) 5
> INCRBY key1 10
(integer) 15
> GET key1
"15"

> INCRBY key1 -5
(integer) -5
> INCRBY key1 -10
(integer) -15
> GET key1
"-15"

소수점이 있는 경우엔 에러가 발생


DECR

숫자를 1씩 감소, redis에 값이 없을경우 0부터 감소
DECR {key}

> DECR key1
(integer) -1
> DECR key1
(integer) -2
> GET key1
"-2"

> SET key1 10
OK
> DECR key1
(integer) 9
> DECR key1
(integer) 8
> GET key1
"8"

DECRBY

지정한 숫자(정수)만큼 감소, redis에 값이 없을경우 0을 기준으로 감소
DECRBY {key} {n}

> DECRBY key1 5
(integer) -5
> DECR key1 10
(integer) -15
> GET key1
"-15"

Sets

  • 중복되지 않는 문자열의 모음(Set 자료구조와 유사)
  • 정렬되지 않음
  • key와 value가 1:N 관계, Sets에서는 집합이라는 의미로 value를 member라고 부름
  • 교집합, 합집합 및 차이와 같은 일반적인 집합 연산을 효율적으로 수행
  • Redis 집합의 최대 크기는 2^32 - 1(4,294,967,295)

SADD
SMEMBERS SISMEMBER SCARD
SREM
SUNION SUNIONSTORE SINTER SINTERSTORE SDIFF SDIFFSTORE

SADD

집합에 데이터를 추가
SADD {key} {member}

> SADD key1 hello
(integer) 1
> SADD key1 hello2 hello3
(integer) 2
> SMEMBERS key1 (멤버 조회)
1) "hello3"
2) "hello2"
3) "hello"

------------------------------------
중복된 값을 저장하는 경우
> SADD key1 hello
(integer) 1
> SADD key1 hello
(integer) 0
> SMEMBERS key1
1) "hello"

Subquery 사용 가능

example
> SADD key1 (get key2)
> SADD key1 (lrange mylist2 0 -1)
...

SREM

집합의 멤버를 삭제
SREM {key} {member} [{member} ...]

> SADD key1 hello hello2 hello3
(integer) 3
> SREM key1 hello
(integer) 1
> SMEMBERS key1
1) "hello3"
2) "hello2"

> SREM key1 hello2 hello3
(integer) 2
> SMEMBERS key1
(empty array)

SMEMBERS

집합의 모든 데이터를 조회
SMEMBERS {key}

> SADD key1 hello hello2 hello3
(integer) 3
> SMEMBERS key1
1) "hello3"
2) "hello2"
3) "hello"

SISMEMBER

집합에 member가 존재하는지 확인(member가 있으면 1 없으면 0을 리턴)
SISMEMBER {key} {member}

> SADD key1 A B C
(integer) 3

> SISMEMBER key1 A
(integer) 1
> SISMEMBER key1 D
(integer) 0

SCARD

집합에 속한 member의 개수를 조회(SLEN을 사용해도 동일)
SCARD {key}

> SADD key1 hello hello2 hello3
(integer 3)
> SCARD key1
(integer 3)
> SREM key1 hello
(integer 1)
> SCARD key1
(integer 2)

SUNION

집합들의 합집합을 구한다
SUNION {key} [{key} ...]

> SADD key1 hello hello2
(integer) 2
> SADD key2 hello3
(integer) 1

// key1 = {hello, hello2}
// key2 = {hello3}

> SUNION key1 key2
1) "hello3"
2) "hello"
3) "hello2"

SUNIONSTORE

합집합을 구해 새로운 키에 저장
SUNIONSTORE {destination_key} {source_key} [{source_key} ...]

source_key의 합의 결과가 destination_key에 저장된다


SINTER

집합들의 교집합을 구한다
SINTER {key} [{key} ...]

교집합이 있는 경우
> SADD key1 hello hello2
(integer) 2
> SADD key2 hello
(integer) 1

// key1 = {hello, hello2}
// key2 = {hello}

> SINTER key1 key2
1) "hello"

-------------------------------------------

교집합이 없는 경우
> SADD key1 hello hello2
(integer) 2
> SADD key2 hello3
(integer) 1

// key1 = {hello, hello2}
// key2 = {hello3}

> SINTER key1 key2
(empty array)

SINTERSTORE

교집합을 구해 새로운 키에 저장
SINTERSTORE {destination_key} {source_key} [{source_key} ...]

source_key의 교집합의 결과가 destination_key에 저장된다


SDIFF

집합들의 차집합을 구한다
SDIFF {key} [{key} ...]

> SADD key1 A B C
(integer) 3
> SADD key2 C D
(integer) 2

// key1 = {A, B, C}
// key2 = {C, D}

> SDIFF key1 key2
1) "A"
2) "B"

SDIFFSTORE

차집합을 구해 새로운 키에 저장
SDIFFSTORE {destination_key} {source_key} [{source_key} ...]

source_key의 차집합의 결과가 destination_key에 저장된다


SortedSets

  • key하나에 여러개의 score와 value로 구성
  • value는 score로 정렬되며 중복되지 않음
  • score가 같은 경우 value로 정렬됨
  • SortedSets에서는 집합이라는 의미로 value를 member라고 부름

ZADD
ZRANGE ZREVRANGE ZCARD ZSCORE ZCOUNT
ZREM
ZINCRBY ZPOPMAX ZPOPMIN

ZADD

데이터를 score와 함께 추가
ZADD {key} {score} {member} [{score} {member} ...]

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZRANGE key 0 -1
1) "apple"
2) "banana"
3) "grape"

ZREM

member 삭제
ZREM {key} {member} [{member} ...]

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZREM key apple
"12"
> ZRANGE key 0 -1 withscores
1) "banana"
2) "2"
3) "grape"
4) "3"

ZRANGE

member 목록을 조회 (score가 작은것부터 조회)
ZRANGE {key} {start} {stop}

  • start, stop 은 index
  • index가 작은것부터 0, 1, 2 ... 로 정해짐
  • 전체조회는 start 0, stop -1 을 지정
> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZRANGE key 0 -1
1) "apple"
2) "banana"
3) "grape"
-------------------------------------------------------
> ZRANGE key 0 -1 withscores  // withscores 옵션을 사용하면 score도 같이 보여줌
1) "apple"
2) "1"
3) "banana"
4) "2"
5) "grape"
6) "3"

ZREVRANGE

member 목록을 score가 큰것부터 조회(index가 큰것부터 0, 1, 2 ... 로 정해짐)
SINTAX - ZRANGE {key} {start} {stop}

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZREVRANGE key 0 -1
1) "grape"
2) "3"
3) "banana"
4) "2"
5) "apple"
6) "1"

ZCARD

key의 member 개수를 리턴
ZCARD {key}

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZCARD key
(integer) 3

ZINCRBY

스코어를 increment만큼 증가 혹은 감소 (실수도 가능)
ZINCRBY {key} {increment} {member}

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZINCRBY key 10 banana
"12"
> ZRANGE key 0 -1 withscores
1) "apple"
2) "1"
3) "grape"
4) "3"
5) "banana"
6) "12"

ZSCORE

member의 score를 조회
ZSCORE {key} {score}

  • min, max에 지정한 숫자를 포함해 카운팅
  • min에 -inf, max에 +inf 를 지정하면 전체를 조회
> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZSCORE key grape
"3"

ZCOUNT

score로 범위를 지정해서 카운트
ZCOUNT {key} {min} {max}

  • min, max에 지정한 숫자를 포함해 카운팅
  • min에 -inf, max에 +inf 를 지정하면 전체를 조회
> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZCOUNT key -inf +inf  // 모든 member의 수
(integer) 3
> ZCOUNT key 2 +inf  // score가 2이상인 member의 수
(integer) 2
> ZCOUNT key -inf 1  // score가 1이하인 member의 수
(integer) 1
> ZCOUNT key 1 2  // score가 1이상 2이하인 member의 수
(integer) 2

ZPOPMAX

집합의 큰 값부터 꺼내옴
ZPOPMAX {key} {count}

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZPOPMAX key 1
1) "grape"
2) "3"
> ZPOPMAX key 2
1) "banana"
2) "2"
3) "apple"
4) "1"

ZPOPMIN

집합의 작은 값부터 꺼내옴
ZPOPMAX {key} {count}

> ZADD key 1 apple 2 banana 3 grape
(integer) 3

> ZPOPMAX key 1
1) "apple"
2) "1"
> ZPOPMAX key 2
1) "banana"
2) "2"
3) "grape"
4) "3"

Hashes

  • field-value 구조로 구성된 컬렉션 (java의 hashtable과 유사함)
  • key하위에 subkey를 이용해 Hash Table을 제공
  • 대부분의 해시 명령의 복잡도는 O(1), HKEYS, KVALS, HGETALL는 O(n)이며 여기서 n은 레코드의 개수

redis hashes 는 다음과 같은 형태를 가지게 됨

redis-image

HSET
HGET HMGET HGETALL HLEN HKEYS HVALS HEXISTS
HDEL
HINCRBY HINCRBYFLOAT

HSET

key에 filed와 value를 저장
HSET {key} {field} {value} [{field} {value} ...]

> HSET person name devoong2
(integer) 1

HDEL

key의 filed로 value를 삭제
HDEL {key} {field} [{field} ...]

> HSET person name devoong2
(integer) 1

> HDEL person name
(integer) 1

HGETALL

key의 모든 field와 value를 조회
HGETALL {key}

> HSET person name devoong2
(integer) 1
> HSET person gender male
(integer) 1

> HGETALL person
1) "name"
2) "devoong"
3) "gender"
4) "male"

HGET

key와 filed로 value를 조회
HGET {key} {field}

> HSET person name devoong2
(integer) 1

> HGET person name
"devoong2"

HMGET

key와 filed로 여러개의 value를 조회
HGET {key} [{key} ...]

> HSET person name devoong2
(integer) 1
> HSET person gender male
(integer) 1

> HMGET person name gender
1) "devoong"
2) "male"

HLEN

key의 filed 개수를 조회
HLEN {key} {field}

> HSET person name devoong2
(integer) 1
> HSET person gender male
(integer) 1

> HLEN person
(integer) 2

HKEYS

key의 모든 filed를 조회
HKEYS {key}

> HSET person name devoong2
(integer) 1
> HSET person gender male
(integer) 1

> HKEYS person
1) "name"
2) "gender"

HVALS

key의 모든 value를 조회
HVALS {key}

> HSET person name devoong2
(integer) 1
> HSET person gender male
(integer) 1

> HVALS person
1) "devoong"
2) "male"

HINCRBY

field의 value를 increment만큼 증가or감소
HINCRBY {key} {field} {increment}

> HINCRBY key count 1
"1"
> HINCRBY key count 5
"6"

HINCRBYFLOAT

field의 value를 float만큼 증가or감소
HINCRBY {key} {field} {float}

> HINCRBYFLOAT key count 1.1
"1.1"
> HINCRBYFLOAT key count 5.5
"6.6"

HEXISTS

key의 field가 있는지 조회 (있으면 1, 없으면 0을 리턴)
HEXISTS {key} {field}

> HEXISTS key name
(integer) 0

> HSET key name devoong2
(integer) 0
> HEXISTS key name
(integer) 1

Lists

  • Array 형태의 자료구조
  • value는 입력한 순서대로 저장
  • Stack, Queue 구현 가능
  • key와 value가 1:N 관계
  • Head, Tail에서의 작업은 O(1), 요소 중간에서의 작업은 일반적으로 O(n)의 복잡도를 가짐

LPUSH RPUSH
LPOP RPOP
LSET
LREM
LRANGE LLEN LINDEX RPOPLPUSH

LPUSH

리스트의 왼쪽에 데이터를 저장
LPUSH {key} {element} [{element} ...]

> LPUSH key el1 el2 el3
(integer) 3

> LRANGE key 0 -1
1) "el3"
2) "el2"
3) "el1"

RPUSH

리스트의 오른쪽에 데이터를 저장
RPUSH {key} {element} [{element} ...]

> RPUSH key el1 el2 el3
(integer) 3

> LRANGE key 0 -1
1) "el1"
2) "el2"
3) "el3"

LPOP

리스트의 왼쪽에서 데이터를 꺼냄 (꺼내진 데이터는 리스트에서 삭제)
LPOP {key} {count}

> LPUSH key el1 el2 el3
(integer) 3

> LPOP key
"el3"

> LRANGE key 0 -1
1) "el2"
2) "el1"

> LPUSH key el1 el2 el3
(integer) 3

> LPOP key 2
1) "el3"
2) "el2"

> LRANGE key 0 -1
1) "el1"

RPOP

리스트의 오른쪽에서 데이터를 꺼냄 (꺼내진 데이터는 리스트에서 삭제)
RPOP {key} {count}

> LPUSH key el1 el2 el3
(integer) 3

> RPOP key
"el1"

> LRANGE key 0 -1
1) "el3"
2) "el2"

> LPUSH key el1 el2 el3
(integer) 3

> RPOP key 2
1) "el1"
2) "el2"

> LRANGE key 0 1
1) "el3"

LRANGE

인덱스의 범위로 리스트를 조회

  • 왼쪽부터 오른쪽으로 0, 1, 2... 의 index를 사용
  • 전체를 조회하려면 start: 0, stop: -1 을 지정해야함

RPUSH {key} {start} {stop}

> LPUSH key el1 el2 el3
(integer) 3

> LRANGE key 0 -1
1) "el3"
2) "el2"
3) "el1"

오른쪽 기준으로 조회시에는 음수를 사용

  • 오른쪽부터 왼쪽으로 -1, -2, -3 ... 의 index를 사용
> LPUSH key el1 el2 el3
(integer) 3


> LRANGE key -3 -2
1) "el3"
2) "el2"

LLEN

리스트에서 value의 개수를 조회
LLEN {key}

> LPUSH key el1 el2 el3
(integer) 3

> LLEN key
(integer) 3

LINDEX

인덱스로 특정 위치의 데이터를 조회
LINDEX {key} {index}

> LPUSH key el1 el2 el3
(integer) 3

> LINDEX key 0
"el3"
> LINDEX key 1
"el2"

LSET

인덱스로 특정 위치의 데이터를 변경
LSET {key} {index} {value}

> LPUSH key el1 el2 el3
(integer) 3

> LSET key 0 value1
OK
> LINDEX key 1
"value1"

LREM

리스트의 데이터를 삭제

  • count가 양수인 경우 : 지정한 value를 왼쪽에서부터 count만큼 삭제
  • count가 음수인 경우 : 지정한 value를 오른쪽에서부터 count만큼 삭제
  • count가 0인 경우 : 지정한 value를 모두 삭제

LREM {key} {count} {value}

> LPUSH key el1 el2 el2 el3
(integer) 4

> LREM key 1 el2
integer (1)
> LRANGE key 0 -1
1) "el3"
2) "el2"
3) "el1"

RPOPLPUSH

오른쪽에서 데이터를 꺼내 왼쪽에 넣음
RPOPLPUSH {source_key} {destination_key}

> LPUSH source el1 el2  el3
(integer) 3
> LPUSH destination value1 value2 value3
(integer) 3

> RPOPLPUSH source destination
"el1"
> LRANGE destination 0 -1
1) "el1"
2) "value3"
3) "value2"
4) "value1"
반응형
    devoong2
    devoong2
    github 주소: https://github.com/limwoobin

    티스토리툴바