본문 바로가기
개발

[Redis] 레디스 기본타입(String)

by 박연호의 개발 블로그 2024. 1. 18.

redis string은 가장 기본적인 redis 데이터 타입으로 binary arrays, serialized objects, text, 연속된 bytes를 저장합니다. redis의 키는 string이기 때문에 값으로 사용할 때, 문자열을 문자열로 매핑하고 있습니다(key:value -> 문자열:문자열). 이런 특징 때문에 HTML page를 캐싱하는데 redis를 사용할 수 있습니다.

 

    > SET fruit banana
    OK
    > GET fruit
    banana

SET, GET 명령어로 key에 데이터를 할당, 검색할 수 있으며, SET명령어는 key에 값이 존재하더라도 기존 값을 덮어 씁니다.  값은 binary data를 포함한 모든 종류의 문자열이 될 수 있으며, 심지어 jpeg 이미지를 value에 저장할 수 있습니다. 여기서 value의 값은 512MB을 넘을 수 없습니다.

 

대부분의 string 명령어는 O(1) 시간복잡도를 가지지만, SUBSTR, GETRANGE, SETRANGE 명령어는 O(n) 복잡도를 가집니다.

 

    > set total_crashes 0
    OK
    > incr total_crashes
    (integer) 1
    > incrby total_crashes 10
    (integer) 11

redis의 몇몇 명령어는 string값을 integer로 다룹니다. INCR명령어는 string값을 integer로 파싱하여 1 증가시킵니다. INCR 명령어는 atomic하게 동작하는데, 이는 키 값조회 + 키 값증가를 한번에 처리합니다. 여러 클라이언트가 동일한 키에 대해 INCR 명령어를 수행해도 race condition이 발생하지 않습니다.

 

대부분의 string 명령어는 O(1) 시간복잡도를 가지지만 SUBSTR, GETRANGE, SETRAGE 명령어를 O(n)의 시간복잡도는 가집니다. 이런 random access 명령어를 긴 문자열을 다룰 때 performane issue를 가집니다.


명령어

- GET

O(1)

GET key

key의 value를 검색하며, key가 존재하지 않는 경우 nill을 반환하며 값이 string이 아닌 경우 error를 반환합니다.

 

 

- APPEND

O(1)

APPEND key value

key의 문자열 값의 끝에 새로운 값을 추가하는 명령어 입니다. 해당 key가 없으면 key를 새로 만들고 value를 할당합니다.

APPEND 명령어는 어떤 고정된 문자열을 압축하여 관리하는데 유용합니다. 예를 들어, 백드라운드 작업이 도는 시간을 매번 기록한다면

APPEN temperature YYYYMMDDHHSSMM
APPEN temperature YYYYMMDDHHSSMM
APPEN temperature YYYYMMDDHHSSMM
....

key에 시간 데이터를 계속 붙이면서(여기서 시간 데이터는 14자리로 고정되야함), STRLEN, ETRANGE, ..등의 함수를 사용하여 temperature의 값을 14자리씩 자르면서 날짜 데이터를 사용할 수 있습니다. 

 

 

- DECR

O(1)

DECR key

key에 저장된 값을 -1 합니다. 만약 키가 존재하지 않는다면, SET key 0을 한 다음, -1 합니다. value가 잘못된 타입이거나, 숫자로 표현할 수 없는 값인 경우 에러를 반환합니다. 이 연산의 제한값은 64 bit signed integers 입니다.

 

 

- DECRBY 

O(1)

DECRBY key decrement

key의 값은 decrement만큼 감소합니다. DECR와 마찬가지로 키가 존재하지 않은 경우 SET key 0한 다음 decrement만큼 감소하며 value가 잘못된 타입이거나, 숫자로 표현할 수 없는 경우 에러를 반환합니다. 이 연산의 제한값은 64 bit signed integers 입니다.

 

 

- GETDEL

O(1)

GETDEL key

key의 값을 반환 후 key를 삭제합니다.

 

 

- GETEX

O(1)

GETEX key [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | PERSIST]

key의 값을 반환 하면서 만료시간을 설정합니다.

 

EX : seconds, 초 단위로 만료시간을 설정

PX : milliseconds, ms 단위로 만료시간을 설정

EXAT : timestamp-seconds, 초 단위 unix time으로 만료시간을 설정

PXAT : timestamp-milliseconds, ms 단위 unix time으로 만료시간을 설정

PERSIST : 만료시간을 제거

 

 

- GETRANGE

O(N) : 시간 복잡도는 반환된 문자열에 의해 결정되지만, 기존에 존재하는 문자열에 대해 substring을 만드는 것은 매우 저렴하므로, 작은 문자열에 대해서는 상수 시간 O(1)을 가집니다.

GETRANGE key start end

문자열 값의 substring을 반환합니다. 

 

 

- GETSET

O(1)

GETSET key value

key의 기존 값을 새로운 값으로 변경하면서 기존 값을 반환합니다. 만약 기존값이 문자열 값이 아니면 에러를 반환하며, 위 명령어가 실행되면 기존값의 ttl은 제거됩니다.

 

GETSET은 INCR 명령어와 함께 카운팅 숫자의 atomic reset에 사용할 수 있습니다. 예를 들어, 어떤 이벤트가 발생할 때 마다 INCR명령어로 카운팅 하다, 카운팅 숫자를 반환하면서 다시 0으로 만들고 싶을 때 GETSET mycount 0 명령어를 사용할 수 있습니다.

 

 

- INCR

O(1)

INCR key

key의 값을 1증가 시킵니다. 키가 존재하지 않으면 SET key 0을 하고 값을 1 증가시킵니다. 만약 값이 잘못된 타입이거나, 정수로 표현할 수 없는 문자열인 경우 에러를 반환합니다. 명령어의 최대값은 64 bit signed integers입니다.

 

redis는 전용 정수형 타입이 없으며 INCR은 문자열 명령어 입니다. 문자열 값은 base-10 64 bit sigend integer로 interpreted되어 사용됩니다. INCR명령어로 api의 호출 제한 기능을 구현할 수 있습니다.

 

 

- INCRBY

O(1)

INCRBY key increment

key에 저장된 값은 increment만큼 증가시킵니다. 만약 key가 존재하지 않으면, SET key 0한 후, 명령어를 실행합니다. 만약 키의 값이 잘못된 타입이거나, 숫자로 표현할 수 없는 문자열인 경우 에러가 발생합니다. 값의 범위는 64 bit signed integers 입니다.

 

 

INCRBYFLOAT

O(1)

INCRBYFLOAT key increment

키에 저장된 값에 floating number를 증가시키고 음수값을 입력하면 floating number 만큼 감소 시킵니다. 키에 값이 존재하지 않으면 키의 값을 0으로 설정 후 명령어를 실행합니다.

 

 

- LCS

O(N*M) : N : s1.length, M : s2.length

LCS key1 key2 [LEN] [IDX] [MINMATCHLEN min-match-len] [WITHMATCHLEN]

 

LCS는 longest common subsequence의 약자로, 두 문자열 간에 공통 부분 문자열을 찾는 명령어 이며 옵션값에 따라 LCS 명령어의 수행 결과가 다릅니다.

> MSET key1 ohmytext key2 mynewtext
OK
> LCS key1 key2
"mytext"

ohmytext와 mynewtext 각각 왼쪽부터 읽었을 때 공통 문자열은 mytext 입니다.

> LCS key1 key2 LEN
(integer) 6

LEN 옵션은 공통 문자열의 길이를 구할땐 사용합니다.

> LCS key1 key2 IDX
1) "matches"
2) 1) 1) 1) (integer) 4
         2) (integer) 7
      2) 1) (integer) 5
         2) (integer) 8
   2) 1) 1) (integer) 2
         2) (integer) 3
      2) 1) (integer) 0
         2) (integer) 1
3) "len"
4) (integer) 6

IDX 옵션은 두 문자열의 공통 문자열의 인덱스로 비교할 수 있게 해줍니다. 두 문자열의 공통 문자열은 mytext이며, text는 첫번째 문자열은 인덱스 4~7에 있으며, 두번째 문자열은 인덱스 5~8에 있습니다. 또한 my는 첫번째 문자열의 2~3 위치에, 두번째 문자열의 0~1에 있습니다.

> LCS key1 key2 IDX MINMATCHLEN 4
1) "matches"
2) 1) 1) 1) (integer) 4
         2) (integer) 7
      2) 1) (integer) 5
         2) (integer) 8
3) "len"
4) (integer) 6

 

MINMATCHLEN는 4는 최소 공통 문자열 중에 최소 4이상은 만족하는 문자열에 해당하는 인덱스를 가져옵니다. 위의 예시에서 text는 4 이상이기 때문에 4~7, 5~8을 보여주고 있습니다.

> LCS key1 key2 IDX MINMATCHLEN 2 WITHMATCHLEN
1) "matches"
2) 1) 1) 1) (integer) 4
         2) (integer) 7
      2) 1) (integer) 5
         2) (integer) 8
      3) (integer) 4
   2) 1) 1) (integer) 2
         2) (integer) 3
      2) 1) (integer) 0
         2) (integer) 1
      3) (integer) 2

WITHMATCHLEN 옵션은 MINMATCHLEN 명령어에 길이가 추가적으로 보여줍니다. 공통 문자열이 최소 2이상인 부분은 4~7, 5~8이며, 이때 문자열은 길이는 4입니다. 마찬가지고 2~3, 0~1의 문자열 길이는 2 입니다.

 

 

- MGET

O(N) : N은 검색하려고 하는 키의 개수

MGET key [key ...]

입력한 모든 key의 값을 반환합니다. 값이 문자열이 아니거나, 키가 존재하지 않는 경우 nill을 반환하며 이러한 이유로 MGET 명령어는 실패하지 않습니다.

 

 

- MSET

O(N) : N은 입력하려고 하는 키의 개수

MSET key value [key value ...]

복수개의 key, value값을 설정합니다. 동일한 키가 존재하는 경우 기존값을 덮어 씁니다. 기존값을 덮어씌우고 싶지 않으면 MSETNX를 사용해야 합니다. MSET 명령어를 atomic하여 입력된 모든 key, value값은 한번에 설정됩니다. 일부키는 업데이트 되었지만 다른 키는 변경되지 않았음을 확인하는 것은 불가능 합니다.

 

 

- MSETNX

O(N) : N은 입력하려고 하는 키의 개수

MSETNX key value [key value ...]

MSET와 같지만, key의 값이 하나라도 존재한다면 명령어는 모두 실패하게 됩니다. 즉, key값이 없을 때 MSETNX를 사용해야 합니다. MEST은 atomic하기 때문에 입력된 모든 값이 한번에 설정됩니다. 일부키는 업데이트 되었지만 다른 키는 변경되지 않았음을 확인하는 것은 불가능 합니다.

 

 

- SET

O(N) 

SET key value [NX | XX] [GET] [EX seconds | PX milliseconds |
  EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]

key의 값으로 문자열을 설정합니다. 이미 키가 존재하는 경우, 값의 타입에 상관없이 값을 덮어 씁니다. 또한 명령어 성공 시, key의 기존 ttl은 삭제됩니다.

 

EX : seconds, 키의 만료 시간을 초단위로 설정합니다.

PX : ms, 키의 만료 시간을 ms단위로 설정합니다.

EXAT : timestamp-seconds, 키의 만료시간을 unix time 초 단위로 설정합니다.

PXAT : timestamp-ms, 키의 만료시간을 unix time ms 단위로 설정합니다.

NX : 키가 없는 경우만 키의 값을 설정합니다.

XX : 키가 있는 경우에만 키의 값을 설정합니다.

KEEPTTL : 기존의 ttl을 유지합니다. SET 명령어 성공 시, key의 ttl은 삭제하지만 KEEPTTL 옵션을 주면 기존 ttl이 유지됩니다.

SET : 키의 새로운 값을 설정하고, 이전 값을 반환하거나 키가 존재하지 않는 경우 nill을 반환합니다.  

 

SET key val NX EX timeout 명령어로 레디스를 활용한 lock을 구현할 수 있습니다. 클라이언트는 앞의 명령어가 OK를 반환하면 lock을 획득하고, DEL 명령어로 key를 삭제하여 unlock할 수 있습니다.

 

 

- SETRANGE

O(1)

SETRANGE key offset value

지정된 오프셋에서 시작하여 value의 전체 길이로 키에 저장된 문자열의 일부를 덮어 씁니다.  오프셋이 현재 키 값의 문자열의 길이보다 큰 경우, 오프셋에 맞도록 문자열은 0바이트로 패딩 됩니다.

SETRANGE와 GETRANGE 명령어로 redis string을 O(1) random access를 가지는 선형 배열로 사용할 수 있습니다.

 

 

- STRLEN

O(1)

STRLEN key

 

키에 저장된 문자열의 길이를 반환합니다.