Redis 명령어!

Redis

싱글 스레드 이벤트 처리 형태로 동작하는 인메모리 Key–value store(KVS).

Redis is an open source (BSD licensed),
in-memory data structure store, used as a database, cache and message broker.

싱글스레드로 동작하다 모니 메모리를 전체순회하는 O(N) 시간복잡도 형태의 쿼리를 피해야 하며 key 단위로 값을 가져오는 O(1) 함수 사용을 권장한다.

services:
  redis:
    image: redis:7.2
    container_name: redis
    ports:
      - "6379:6379"
    
  redisinsight:
    image: redislabs/redisinsight:2.52
    container_name: redisinsight
    ports:
      - "5540:5540"
    depends_on:
      - redis
    environment:
      - RI_HOST=0.0.0.0
      - REDIS_URI=redis://redis:6379

cache miss: 데이터를 요청했을 때 캐시 메모리가 데이터를 가지오 있다면 cache hit, 없다면 cache miss,
CPU 와 Cache Memory, RAM 에서 사용하는 OS 용어.

명령어

명령어 사전: https://redis.io/docs/latest/commands/acl/

redis 에는 여러가지 data type 이 존재하는데 주로 사용하는 것은 아래 6종류

  • string
  • lists
  • hash
  • set
  • zset

이 외에도 GEO, Bitmap 관련 data type 이 있다.

KEYS <pattern>
DEL <key>
UNLINK <key> # 키를 비동기적으로 삭제
FLUSHDB [ASYNC | STNC] # 현재 DB 전체 삭제
FLUSHALL [ ASYNC | SYNC ] # DB 전체 삭제

key 를 설정할 때 분류(그룹핑)을 위해 : 을 사용하여 key 를 구성하는것을 권장한다.
ex) HSET user:1 points

string 명령어

redis 의 key, value 모두 string 을 사용한다.

문자열 외에도 이진데이터(숫자, 부동소수점 등)을 string 으로 관리한다.

Redis의 문자열을 저장할 때 SDS(Simple Dynamic String) 데이터 구조를 사용한다.

GET GETDEL SET MSET MGET

GET <key> 
SET <key> <value>

GETDEL <key> # 값을 가져오고 키를 삭제

SET 명령어는 아래와 같이 복잡한 설정들은 가진다.

SET key value [ NX | XX ] [ GET ] [ EX seconds | PX milliseconds | EXAT unix - time - seconds | PXAT unix - time - milliseconds | KEEPTTL ]
  • [ NX | XX ]: 키의 존재 여부를 조건에 추가
    NX: key 가 존재하지 않을 경우 수행
    XX: key 가 존해잘 경우 수행
  • [ GET ]: key 로 값을 가져온 후 설정(v6.2 이상 사용 가능)
  • [ EX | PX | EXAT | PXAT | KEEPTTL ]: TTL 설정
    EX: 초 PX: 밀리초 EXAT: 유닉스 초 PXAT: 유닉스 밀리초 KEEPTTL: 기존 TTL 유지하면서 SET

TTL 의 경우 SETEX, PSSETEX 등의 추가명령을 통해 수행할 수 있지만 SET 의 옵션을 사용하는 것을 권장한다.

SET mykey "hi"        # "OK"
SET mykey "Hello" GET # "Hello" 값을 설정하고 이전 값을 반환 (사용 권장)
GETSET mykey "Hello"  # "Hello" 값을 설정하고 이전 값을 반환 (권장하지 않음)

SET mykey "Hello" NX  # (nil) 키가 존재하지 않을 때만 설정 (NX):
SET nxkey "Hello" NX  # "OK"

SET xxkey "Hello" XX  # (nil) 키가 존재할 때만 설정
SET mykey "Hello" XX  # "OK"
MSET s1 1 s2 2 s3 3 # "OK"
MGET s1 s2 s3       # 1) "1"
                    # 2) "2"
                    # 3) "3"

MSETNX s1 1 s2 2 # 여러개의 키가 모두 존재하지 않을 때에만 저장, 
                 # 하나라도 존재할 경우 모두 실패

GETRANGE APPEND STRLEN

SET mykey "Hello world" # "OK"
GETRANGE mykey 0 3      # "Hell"
GETRANGE mykey -3 -1    # "rld"
GETRANGE mykey 10 15    # "Hello world"
GETRANGE mykey 30 35    # "(nil)"
SET mykey "Hello"     # "OK"
APPEND mykey " World" # (integer) 11, 문자열 추가와 동시에 문자열 길이 반환
STRLEN mykey          # (integer) 11, 문자열 길이 반환
GET mykey             # "Hello World"

string 명령어 - 숫자

SET count 100  # "OK"
TYPE count     # (string)
INCR count     # (integer) 101, 증가
DECR count     # (integer) 100, 감소
INCRBY count 5 # (integer) 105, 증가
DECRBY count 3 # (integer) 102, 감소

INCRBY count -2 # (integer) 100 
INCRBYFLOAT mykey 1.5 # "1.5"
INCRBYFLOAT mykey 2.7 # "4.2"
INCRBYFLOAT mykey -1  # "3.2", 부동소수점은 별도 감소 명령어 없음

string 명령어 - expired 설정하기

                # 유효 시간(초) 설정 (EX)
SET mykey "Hello" PX 10000            # 유효 시간(밀리초) 설정 (PX)
SET mykey "Hello" EXAT 1672531199     # 특정 유닉스 시간(초)까지 유효 (EXAT)
SET mykey "Hello" PXAT 1672531199123  # 특정 유닉스 시간(밀리초)까지 유효 (PXAT)
SET mykey "Hello" KEEPTTL # TTL을 유지하면서 값을 업데이트 (KEEPTTL)

list 명령어

stack, queue 의 기능을 지원함.

LPUSH, RPUSH, LRANGE, LPOP, RPOP

LPUSH <key> <value1> ... <valueN>  # list 왼쪽에 value 추가
RPUSH <key> <value1> ... <valueN>  # list 오른쪽에 value 추가
LRANGE <key> <start> <end>         # index range 읽기

LPOP <key> # list 왼쪽에서 value 삭제
RPOP <key> # list 오른쪽에서 value 삭제
LPUSH mylist 1 2 3 4 5  # (integer) 5
LPUSH mylist 6 7 8 9 10 # (integer) 10
LRANGE mylist 0 -1      # 1) "10"
                        # 2) "9"
                        # 3) "8"
                        # 4) "7"
                        # 5) "6"
                        # 6) "5"
                        # 7) "4"
                        # 8) "3"
                        # 9) "2"
                        # 10) "1"
LPOP mylist             # "10"
RPOP mylist             # "1"

LSET LTRIM RPOPLPUSH LREM

LSET <key> <index> <value> # 특정 index 의 요소 쓰기
LTRIM <key> <start> <end>  # list 범위 자르기
RPOPLPUSH <key1> <key2>    # key1 list 에서 RPOP 하고 key2 에 LPUSH 

LREM <key> <count> <value> # list 왼쪽부터 count 만큼 value 일치요소 제거
LPUSH mylist 1 2 3 4 5 6 7 8 9 10 # (integer) 10

LSET mylist 9 -1   # "OK"
LTRIM mylist 4 9   # "OK", index 5 부터 저장됨
LRANGE mylist 0 -1 # 1) "6"
                   # 2) "5"
                   # 3) "4"
                   # 4) "3"
                   # 5) "2"
                   # 6) "-1"

LPUSH mylist 1 2 3 4 5 6 7 8 9 10 # (integer) 10
RPOPLPUSH mylist mylist # "1"
RPOPLPUSH mylist mylist # "2"
LRANGE mylist 0 -1      # 1) "2"
                        # 2) "1"
                        # 3) "10"
                        # 4) "9"
                        # 5) "8"
                        # 6) "7"
                        # 7) "6"
                        # 8) "5"
                        # 9) "4"
                        # 10) "3"
LPUSH mylist a b c a a c # (integer) 6
LREM mylist 2 a          # (integer) 2
LRANGE mylist 0 -1       # 1) "c"
                         # 2) "c"
                         # 3) "b"
                         # 4) "a"

LLEN LINDEX

LLEN <key> # list 길이 반환
LINDEX <key> <index>        # 특정 index 의 요소 읽기
LPUSH mylist 1 2 3 4 5 6 7 8 9 10 # (integer) 10
LLEN mylist                       # (integer) 10
LINDEX mylist 9                   # "1"

LPOS LINSERT

LPOS <key> <element> [options] # 찾고자 하는 요소 인덱스를 반환

LINSERT <key> BEFORE|AFTER <pivot> <value> # pivot 요소 앞 혹은 뒤에 value 추가
RPUSH mylist "a" "b" "c"      # (integer) 3
LINSERT mylist BEFORE "b" "x" # (integer) 4
LINSERT mylist AFTER "a" "y"  # (integer) 5
LRANGE mylist 0 -1            # 1) "a"
                              # 2) "y"
                              # 3) "x"
                              # 4) "b"
                              # 5) "c"

RPUSH mylist "apple" "banana" "cherry" "banana" "date"
LPOS mylist "banana"         # (integer) 1
LPOS mylist "banana" COUNT 2 # 1) "1" , 2개 요소 검색
                             # 2) "3"
LPOS mylist "banana" RANK 2  # (integer) 3, RANK 이후부터 검색
LPOS mylist "orange"         # (nil)

hash 명령어

해시에 들어가는 요소의 개수가 많거나 hash 형의 장점인 내부 인코딩의 메모리 압축을 제대로 활용하지 못한다.
그리고 hash 특성상 O(N) 시간복잡도를 가지는 함수가 여럿 있는데, 싱글스레드로 동작하는 Redis 에게 delay 를 유발함으로 hash 의 크기를 작게 관리하거나 사용에 유의해야한다.

하나의 hash 크기가 크면 샤드 간 데이터 분산이 어려워진다.

HSET HGET HMGET HKEYS HVALS HGETALL

HSET myhash field1 value1 field2 value2 # (integer) 2
HSET myhash field3 value3               # (integer) 1

# 입력한 field 의 value 가져오기
HGET myhash field1 # "value1"

# 입력한 field 목록의 value 가져오기
HMGET myhash field1 field2 # 1) "value1"
                           # 2) "value2"
                          
# field 전체 가져오기
HKEYS myhash    # 1) "field1"
                # 2) "field2"
                # 3) "field3"

# value 전체 가져오기
HVALS myhash    # 1) "value1"
                # 2) "value3"
                # 3) "value2"

# field-value 전체 가져오기
HGETALL myhash  # 1) "field1"
                # 2) "value1"
                # 3) "field3"
                # 4) "value3"
                # 5) "field2"
                # 6) "value2"

HKEYS, HVALS, HGETALL 의 경우 내부 요소 개수만큼 조회하기에 O(N) 형태이며 hash 크기에 따라 사용시 유의해야 한다.

HLEN HEXISTS HSETNX HDEL

HSET myhash field1 value1 field2 value2 field3 value3 # (integer) 2

# field 가 존재하는지 확인
HEXISTS myhash field1 # (integer) 1
HEXISTS myhash field0 # (integer) 0

# field 가 존재하는지 확인하고 SET 진행
HSETNX myhash field4 value4 # (integer) 1
HSETNX myhash field4 value4 # (integer) 0, 2번째 실행은 실패

# 요소 길이 가져오기
HLEN myhash        # (integer) 4

# field 에 해당하는 요소 삭제
HDEL myhash field2 # (integer) 1

HRANDFIELD

HSET myhash field1 value1 field2 value2 field3 value3 # (integer) 2
# 랜덤 field 가져오기
HRANDFIELD myhash   # "field3"

# 랜덤 field count만큼 가져오기
HRANDFIELD myhash 2 # 1) "field2"
                    # 2) "field3"

hash 명령어 - 숫자 문자열

HSET user:1 points 10      # (integer) 1
HINCRBY user:1 points 5    # (integer) 15
HINCRBYFLOAT user:1 points # "25.25"

HSET user:1 name "John Doe" # (integer) 1
HSTRLEN user:1 name         # (integer) 8

set 명령어

순서 없이 고유한 문자열 집합

SADD SMEMBERS SCARD SISMEMBER

# SADD key member [member ...]
# SET 추가
SADD myset member1 member2 member3 # (integer) 3

# SET 의 member 전체 가져오기
SMEMBERS myset # 1) "member1"
               # 2) "member2"
               # 3) "member3"

# SET 길이 가져오기               
SCARD myset # 3

# SET member 포함여부 확인하기
SISMEMBER myset member3 # (integer) 1

SPOP SREN

SADD myset 1 2 3 4 5 6 7 8 9

# 무작위 member 가져오고 삭제
SPOP myset    # "6"

SPOP myset 5  # 1) "2"
              # 2) "1"
              # 3) "5"
              # 4) "9"
             
SPOP myset 10 # 1) "3"
              # 2) "4"
              # 3) "7"
              # 4) "8"

SPOP myset    # (nil)
SPOP myset 3  # (empty list or set)
SADD myset 1 2 3 4 5

# 입력한 member 삭제
SREM myset 9   # (integer 0)
SREM myset 1   # (integer 1)
SREM myset 2 3 # (integer 2)

SMISMEMBER SRANDMEMBER SMOVE

SADD myset 1 2 3 4 5

# 입력한 member 가 포함되어있는지 확인
SMISMEMBER myset 1   # 1) "1"

SMISMEMBER myset 1 2 # 1) "1"
                     # 2) "1"

SMISMEMBER myset 1 6 # 1) "1"
                     # 2) "0"

# 무작위 member 가져오기
SRANDMEMBER myset    # "1"
SRANDMEMBER myset 2  # 1) "1"
                     # 2) "4"
SADD myset1 1 2 3
SADD myset2 4 5 6

# 지정 member 를 set 으로부터 다른 set 으로 이동
SMOVE myset1 myset2 1 # (integer) 1

SMEMBERS myset1 # 1) "2"
                # 2) "3"

SMEMBERS myset2 # 1) "1"
                # 2) "4"
                # 3) "5"
                # 4) "6"


set 명령어 - 집합

집합 관련 명령어는 요소를 전체순회함으로 set 의 길이가 길다면 사용을 유의해야한다.

SADD myset1 1 2 3 4 5
SADD myset2 3 4 5 6 7

# SDIFF key [key ...]
# 차집합 가져오기(첫번째 set 기준)
SDIFF myset1 myset2 # 1) "1"
                    # 2) "2"
# 차집합 가져오고 set 으로 저장하기, (기존데이터는 초기화됨)
SDIFFSTORE myset3 myset1 myset2 # (integer) 2
SMEMBERS myset3 # 1) "1"
                # 2) "2"

# SINTER key [key ...]
# 교집합 가져오기
SINTER myset1 myset2 # 1) "3"
                     # 2) "4"
                     # 3) "5"
# 교집합 가져오고 set 으로 저장하기, (기존데이터는 초기화됨)
SINTERSTORE myset3 myset1 myset2
SMEMBERS myset3 # 1) "3"
                # 2) "4"
                # 3) "5"

# SUNION key [key ...]
# 합집합 가져오기
SUNION myset1 myset2 # 1) "1"
                     # 2) "2"
                     # 3) "3"
                     # 4) "4"
                     # 5) "5"
                     # 6) "6"
                     # 7) "7"
SUNIONSTORE myset3 myset1 myset3

# SINTERCARD numkeys key [key ...] [LIMIT limit]
# 교집합의 개수 가져오기, limit 으로 종료조건 지정 가능
SINTERCARD 2 myset1 myset2 # (integer) 3
SINTERCARD 2 myset1 myset2 1 # (integer) 1

zset 명령어

Sorted Set, <score, member> 로 이루어진 set,

ZADD ZINCRBY ZRANDMEMBER

score 가 동일한 member 를 삽입할 경우 member 의 사전순서로 순위를 매긴다.

# score-member 쌍 추가
ZADD myzset 1 member1 2 member2 3 member3 # (integer) 3
ZADD myzset 4 member4 # (integer) 1
ZADD key [ NX | XX ] [ GT | LT ] [ CH ] [ INCR ] score member [ score member ...]

ZADD 함수의 반환값 기존 요소를 변경할 경우 (integer) 0, 새로운 요소 추가할 경우 (integer) N 이다.

ZADD myzset 1 member1 2 member2 3 member3 4 member4 # (integer) 4
# member 가 존재하지 않을 때에만 실행
ZADD myzset NX 400 member4 # (integer) 1
# member 가 존재할 때에만 실행
ZADD myzset XX 400 member4 # (integer) 0, 실행되건 되지 않건 항상 0이다.  

# 입력 숫자가 기존 점수보다 클 경우에만 추가, 새로운 요소 추가가능
ZADD myzset GT 200 member2
# 입력 숫자가 기존 점수보다 낮을 경우에만 추가, 새로운 요소 추가가능
ZADD myzset LT -2 member2

# 입력 숫자만큼 score 증가
ZINCRBY myzset 100 member1 # "101"
# member 를 무작위로 가져오기
# ZRANDMEMBER key [count [WITHSCORES]]
ZADD myzset 1 a 2 b 3 c 4 d 5 e 6 f 7 g # (integer) 7
ZRANDMEMBER myzset   # "a"
ZRANDMEMBER myzset 2 # 1) "b"
                     # 2) "g"

ZCARD ZCOUNT ZLEXCOUNT

ZADD myzset 1 a 2 b 3 c 4 d 5 e 6 f 7 g # (integer) 7

# member 개수 반환
ZCARD myzset # (integer) 7

# min max 사이 해당 score 의 member 개수 반환
# ZCOUNT key min max
ZCOUNT myzset 1 3   # (integer) 3, 1이상 3이하
ZCOUNT myzset (1 3  # (integer) 2, 1초과 3이하
ZCOUNT myzset 1 (3  # (integer) 2, 1이상 3미만
ZCOUNT myzset (1 (3 # (integer) 1, 1초과 3미만

# ZLEXCOUNT key min max
# 사전 기준 min max 사이 member 개수 반환
ZLEXCOUNT myzset [b [f # (integer) 5

ZREM ZPOPMIN ZMPOP

ZADD myzset 1 member1 2 member2 3 member3 4 member4 # (integer) 3

# 지정 member 삭제
ZREM myzset member1 # (integer) 1, 실패시 0 반환

# ZPOPMAX key [count]
# score 가 가장큰 요소 삭제 및 반환
ZPOPMAX myzset 2 # 1) "member4"
                 # 2) "4"
                 # 3) "member3"
                 # 4) "3"

# score 가 가장자은 요소 삭제 및 반환
ZPOPMIN myzset   # 1) "member2"
                 # 2) "2"

ZSCORE ZMSCORE ZLEXCOUNT

ZADD myzset 1 member1 2 member2 3 member3 4 member4 # (integer) 3

# 입력 member 의 score 조회
ZSCORE myzset member3          # "3"

# 입력 member 목록의 score 조회
ZMSCORE myzset member3 member1 # 1) "3"
                               # 2) "1"

ZRANK ZREVRANK ZRANGE

ZADD myzset 1 member1 2 member2 3 member3 4 member4 # (integer) 3

# member 의 rank 오름차순으로 반환
ZRANK myzset member1 # (integer) 0
ZRANK myzset member4 # (integer) 3

# member 의 rank 내림차순으로 반환
ZREVRANK myzset member1 # (integer) 3
ZREVRANK myzset member4 # (integer) 0

# member 반환, score 오름차순
ZRANGE myzset 0 -1    # 1) "member1"
                      # 2) "member2"
                      # 3) "member3"
                      # 4) "member4"

# member 반환, score 내림차순
ZRANGE myzset 0 -1 REV # 1) "member4"
                       # 2) "member3"
                       # 3) "member2"
                       # 4) "member1"

# member-score 반환, score 오름차순
ZRANGE myzset 0 -1 WITHSCORES    # 1) "member1"
                                 # 2) "1"
                                 # 3) "member2"
                                 # 4) "2"
                                 # 5) "member3"
                                 # 6) "3"
                                 # 7) "member4"
                                 # 8) "400"

ZREVRANGE 명령을 사용해 내림차순으로 조회 가능하지만 ZRANGE + REV 조합 사용을 권장함.
현재 deprecated 상태임

ZREMRANGEBYLEX ZREMRANGEBYRANK ZREMRANGEBYSCORE

ZADD myzset 1 a 2 b 3 c 4 d 5 e 6 f 7 g # (integer) 7

# ZREMRANGEBYLEX key min max
# member 의 사전 min max 기준 삭제
ZREMRANGEBYLEX myzset [b [d # (integer) 3
ZRANGE myzset 0 -1          # 1) "a"
                            # 2) "e"
                            # 3) "f"
                            # 4) "g"

# ZREMRANGEBYRANK key start stop
# rank 의 start stop 정렬 인덱스 기준 삭제,
ZADD myzset 1 one 2 two 3 three 4 four 5 five # (integer) 5
ZREMRANGEBYRANK myzset 1 3 # (integer) 3
ZRANGE myzset 0 -1         # 1) "one"
                           # 2) "five"

# ZREMRANGEBYSCORE key min max                              
# score 의 start stop 정렬 score 기준 삭제
ZADD myzset 1 one 2 two 3 three 4 four 5 five # (integer) 5
ZREMRANGEBYSCORE myzset 1 3 # (integer) 3
ZRANGE myzset 0 -1          # 1) "four"
                            # 2) "five"

zset 명령어 - 집합

set 집합 명령어에서 제공했던 차집합, 교집합, 합집합에 대한 함수를 제공한다.

  • ZDIFF
  • ZDIFFSTORE
  • ZINTER
  • ZINTERSTORE
  • ZUNION
  • ZUNIONSTORE
  • SINTERCARD

사용방법은 set 집합 명령어와 동일하니 위에 참고

ZMPOP

여러개의 집합에서 score 를 비교하여 count 만큼 꺼낼 수 있다.

# ZMPOP numkeys key [ key ...] < MIN | MAX > [ COUNT count ] 

ZADD myzset 1 member1 2 member2 3 member3 4 member4

ZMPOP 2 zunknonw myzset MIN         # 1) "myzset"
                                    # 2) 1) 1) "member1"
                                    #       2) "1"

ZMPOP 2 zunknonw myzset MIN COUNT 2 # 1) "myzset"
                                    # 2) 1) 1) "member2"
                                    #       2) "2"
                                    #    2) 1) "member3"
                                    #       2) "3"

zunknonw 은 존재하지 않는 zset 임에도 불구하고 정상동작한다.
zunknonw 이 존재했다면 zunknonw 에서 우선적으로 값을 가져온다.

SCAN 명령어

간단하게 100개 정도의 key-value 를 추가

for i in $(seq 1 100); do redis-cli SET "key$i" "value$i"; done

KEYS *
# 1) "key32"
# 2) "key68"
# 3) "key60"
# ...
# 98) "key34"
# 99) "key43"
# 100) "key73"

100개정도는 문제없이 가져오겠지만 억 단위라면 싱글 스레드의 delay 를 유발한다.
이는 redis 를 사용하는 모든 어플리케이션의 delay 로 이어지게 된다.

때문에 커서를 기준으로 끊어더 단위로 값을 가져오는 SCAN 명령을 지원한다.

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
# count: 커서가 한번에 반환할 요소 개수
# type: 커서가 검색할 데이터 타입(string, list, set, zset, hash 가 있음) 
scan 0  # 1) "72", 다음 cursor 값
        # 2) 1) "key32"
        #    2) "key15"
        #    ...
        #    9) "key51"
        #    10) "key20"

scan 72 # 1) "12"
        # 2) 1) "key3"
        #    2) "key88"
        #    ...
        #    10) "key74"
        #    11) "key54"

...

scan 55 # 1) "0"
        # 2) 1) "key82"
        #    2) "key50"
        #    3) "key49"
        #    4) "key30"
        #    5) "key43"
        #    6) "key73"

커서는 항상 0으로 순회 시작하고 0으로 끝난다.
첫번째 반환값은 항상 다음 커서값을 반환한다.

SCAN 0 MATCH user:* COUNT 50 TYPE string

[hash, set, zset] 데이터에서도 KEYS 와 동일한 문제가 발생할 수 있다.
요소가 많으면 많을수록 delay 가 발생하게된다.

TYPE 별 지원하는 SCAN 명령은 아래와 같다.

HSCAN key cursor [MATCH pattern] [COUNT count]
SSCAN key cursor [MATCH pattern] [COUNT count]
ZSCAN key cursor [MATCH pattern] [COUNT count]

시간제한 명령어

SET mykey "Hello" EX 1000 # OK, 1000초 제한

TTL mykey               # (integer) 6, 남은 시간(초) 확인
PTTL mykey              # (integer) 5625, 남은 시간(밀리초) 확인
EXPIRETIME mykey        # (integer) 1722591161, unix 초
PEXPIRETIME mykey       # (integer) 1722591160725, unix 밀리초

# EXPIRE key seconds [NX | XX | GT | LT]
EXPIRE mykey 300        # (integer) 1, TTL 재설정, 초
PEXPIRE mykey 3000        # (integer) 1, TTL 재설정, 밀리초
EXPIREAT mykey 1722511161 # (integer) 1, TTL 재설정, unix 초
PERSIST key # (integer) 1
TTL mekey   # (integer) -2
GET mykey EX seconds # 값을 가져오고 해당 값에 TTL 설정

TTL 관리의 부하

효율적인 키 만료 처리를 위해 아래 2가지 방법을 혼합하여 처리한다.

  • Lazy Expiration(지연 만료)
    클라이언트가 만료된 키에 접근할 때만 해당 키를 삭제
  • Active Expiration(능동 만료)
    주기적(tick)으로 만료된 키를 스캔하고 삭제, interval 은 기본 100밀리초이며 TTL 설정된 키를 20개 랜덤샘플링하여 25% 이상 만료되어 있다면 주기를 더 짧게 수정한다.

메모리 Eviction Policy(제거 정책)에 의해 TTL 설정된 키가 삭제될 수 도 있다.

  • 메모리가 부족할 때 메모리 정책에 따라서 더 짧은 주기로 Active Expiration 를 실행
  • Eviction Policy으로 인해 TTL 이 짧은 키를 삭제하거나 영구저장소로 이동.
  • 기본 설정은 신규 추가 중단(noeviction) 방식을 사용한다.

트랜잭션

MULTI ... EXEC 명령어 실행 중에는 다른 클라이언트의 간섭 없이 원 자적 처리를 할 수 있 명령어를 큐에넣어 처리한다.

MULTI       # "OK"
SET foo 10  # "QUEUED"
INCR foo    # "QUEUED"
INCR foo    # "QUEUED"
GET foo     # "QUEUED"
EXEC        # 1) "OK"
            # 2) "11"
            # 3) "12"
            # 4) "12"

중간에 실패할만한 명령어를 껴놓으면 실행전에 실패 가능성을 알 수 있기 때문에 전체 트랜잭션을 실행시키지 않는다.

MULTI       # "OK"
SET bar 10  # "QUEUED"
INCR bar    # "QUEUED"
UNKNOWN bar # "ERR unknown command 'UNKNOWN' ...
INCR bar    # "QUEUED"
GET bar     # "QUEUED"
EXEC        # "EXECABORT Transaction discarded because of previous errors."
GET bar     # (nil)

정상적인 명령어지만 논리적으로 실패하는 경우(ex: 문자열을 1 증가) 트랜잭션은 실행된다.
명령 실행 원자성만 보장할 뿐 롤백은 되지 않는다.

SET bar 10       # "OK"
MULTI            # "OK"
INCR bar         # "QUEUED"
SET bar "hello"  # "QUEUED"    
INCR bar         # "QUEUED"
GET bar          # "QUEUED"
EXEC             # 1) "11"
                 # 2) "OK"
                 # 3) "ReplyError: ERR value is not an integer or out of range"
                 # 4) "hello"   
GET bar          # hello

카테고리:

업데이트: