Post

Redis 데이터 구조: 9가지 타입과 활용 방법

String/List/Hash/Set/Sorted Set의 핵심 기능, Bitmap/HyperLogLog/Geospatial/Stream 구조의 특징과 명령어

Redis 데이터 구조: 9가지 타입과 활용 방법

1. String

  • String에는 최대 512MB의 문자열 데이터를 저장할 수 있다
  • 이진 데이터를 포함하는 모든 종류의 문자열이 binary-safe하게 처리되기 때문에 JPEG 이미지와 같은 바이트 값, HTTP 응답값 등의 다양한 데이터를 저장하는 것도 가능

1-1. GET

1
GET hello
  • 데이터 조회

1-2. SET

1
SET hello world
  • key: hello, value: world
  • 이미 키가 존재하는 경우 새로 입력된 값으로 대체된다
  • NX 옵션
    1
    
    SET hello newval NX
    
    • 지정한 키가 없을 때만 새로운 키를 저장
  • XX 옵션
    1
    
    SET hello newval XX
    
    • 키가 이미 있을 때만 새로운 값으로 덮어 쓰며 새로운 키를 생성하진 않는다

1-3. INCR/INCRBY

1
2
INCR counter
INCRBY counter 50
  • INCR/INCRBY를 사용하면 string 자료 구조에 저장된 숫자를 원자적으로(atomic) 조작할 수 있다
  • DECR/DECRBY 커맨드는 동일한 방식으로 데이터를 감소시키는 커맨드이다
  • 커맨드가 원자적이라는 건 같은 키에 접근하는 여러 클라이언트가 경쟁 상태(race condition)를 발생시킬 일이 없음을 의미한다

1-4. MSET/MGET

1
2
MSET a 10 b 20 c 30
MGET a b c
  • MSET/MGET 커맨드를 이용해 한 번에 여러 키를 조작할 수 있다



2. List

  • Redis에서 list는 순서를 가지는 문자열의 목록
  • 하나의 list에는 최대 42억여 개의 아이템을 저장할 수 있다
  • 일반적인 배열처럼 인덱스를 이용해 데이터에 직접 접근할 수도 있으며, 서비스에서는 스택과 큐로서 많이 사용된다

2-1. LPUSH/RPUSH

  • LPUSH 커맨드는 list의 왼쪽(head)에 데이터를 추가
  • RPUSH 커맨드는 list의 오른쪽(tail)에 데이터를 추가

2-2. LRANGE

  • LRANGE는 시작과 끝 아이템의 인덱스를 각각 인수로 받아 출력

2-3. LPOP

  • list에 저장된 첫 번째 아이템을 반환하는 동시에 list에서 삭제
  • 숫자와 함께 사용하면 지정한 숫자만큼의 아이템을 반복해서 반환

2-4. LTRIM

  • 시작과 끝 아이템의 인덱스를 인자로 전달받아 지정한 범위에 속하지 않는 아이템은 모두 삭제하지만, LPOP과 같이 삭제되는 아이템을 반환하지는 않는다
  • LPUSH와 LTRIM 커맨드를 사용해 고정 길이 큐 유지하기
    1
    2
    
      LPUSH logdata <data>
      LTRIM logdata 0 999
    
    • list에 데이터를 저장하면서 매번 1000번째 이상의 인덱스를 삭제
    • 데이터를 일단 쌓은 뒤 주기적으로 배치 처리를 이용해 삭제하는 것보다 위와 같은 방식으로 삭제하는 것이 효율적
    • list에서 tail 데이터를 삭제하는 작업은 O(1)으로 동작하지만, 배치를 이용한다면 처리 시마다 삭제할 데이터를 검색하기 때문

2-5. LINSERT

  • 원하는 데이터의 앞이나 뒤에 데이터 추가 가능
  • 데이터의 앞에 추가하려면 BEFORE 옵션을, 뒤에 추가하려면 AFTER 옵션을 추가
  • 만약 지정한 데이터가 없는 경우 오류를 반환

2-6. LSET

  • 지정한 인덱스의 데이터를 신규 입력하는 데이터로 덮어 쓴다
  • 만약 list의 범위를 벗어난 인덱스를 입력하면 에러를 반환

2-7. LINDEX

  • 원하는 인덱스의 데이터 확인



3. Hash

3-1. HSET

1
2
3
4
HSET Product:123 Name "Hello world"
HSET Product:123 TypeID 35
HSET Product:123 Version 2002
HSET Product:234 Name "Track Ball" TypeID 32
  • HSET 커맨드를 사용해 hash에 아이템을 저장하며, 한 번에 여러 필드-값 쌍을 저장할 수도 있다

3-2. HGET

1
2
3
HGET Product:123 TypeID
HMGET Product:234 Name TypeID
HGETALL Product:234
  • HGET 커맨드를 사용해 hash에 저장된 데이터를 가져올 수 있으며, 이때는 hash 자료 구조의 키와 아이템의 필드를 함께 입력해야 한다
  • HMGET 커맨드를 이용하면 하나의 hash 내에서 다양한 필드의 값을 가져올 수 있다
  • HGETALL 커맨드는 hash 내의 모든 필드-값 쌍을 차례로 반환한다



4. Set

4-1. SADD

1
2
SADD myset A
SADD myset A A A C B D D E F F F F G
  • SADD 커맨드를 사용해 set에 아이템을 저장할 수 있으며 한 번에 여러 개의 아이템 저장 가능
  • SADD 커맨드는 저장되는 실제 아이템 수를 반환

4-2. SMEMBERS

  • set에 저장된 전체 아이템을 출력
  • 데이터를 저장한 순서와 관계없이 랜덤한 순서로 데이터 출력

4-3. SREM

  • set에서 원하는 데이터를 삭제

4-4. SPOP

  • set 내부의 아이템 중 랜덤으로 하나의 아이템을 반환하는 동시에 set에서 그 아이템을 삭제

4-5. SUNION/SINTER/SDIFF

  • 합집합은 SUNION, 교집합은 SINTER, 차집합은 SDIFF



5. Sorted set

  • sorted set은 스코어 값에 따라 정렬되는 고유한 문자열의 집합
  • 모든 아이템은 스코어-값 쌍을 가지며, 저장될 때부터 스코어 값으로 정렬돼 저장된다
  • 같은 스코어를 가진 아이템은 데이터의 사전 순으로 정렬돼 저장
  • 데이터가 중복 없이 유일하게 저장된다는 점에서 set과 유사
  • 각 아이템은 스코어라는 데이터에 연결돼 있다는 점에서 hash와 유사
  • 또한 모든 아이템은 스코어 순으로 정렬돼 있어, list처럼 인덱스를 이용해 각 아이템에 접근 가능
  • 인덱스를 이용해 아이템에 접근할 일이 많다면 list가 아닌 sorted set을 사용하는 것이 더 효율적이다. list에서 인덱스를 이용해 데이터에 접근하는 것은 O(n)으로 처리되지만, sorted set에서는 O(log(n)으로 처리되기 때문이다.

5-1. ZADD

1
2
ZADD score:220817 100 user:B
ZADD score:228017 150 user:A 150 user:C 200 user:F 300 user:E
  • ZADD 커맨드를 사용하면 sorted set에 아이템을 저장할 수 있으며, 스코어-값 쌍으로 입력해야 한다
  • 한 번에 여러 아이템을 입력할 수 있으며, 각 아이템은 sorted set에 저장되는 동시에 스코어 값으로 정렬된다
  • 만약 저장하고자 하는 데이터가 이미 sorted set에 속해 있다면 스코어만 업데이트 되며, 업데이트된 스코어에 의해 아이템이 재정렬된다
  • 지정한 키가 존재하지 않을 때에는 sorted set 자료구조를 새로 생성하며, 키가 이미 존재하지만 sorted set이 아닐 경우에는 오류를 만환한다
  • 스코어는 배정밀도 부동소수점 문자열이어야 한다
  • option
    • XX: 아이템이 이미 존재할 때만 스코어를 업데이트한다
    • NX: 아이템이 존재하지 않을 때만 신규 삽입하며, 기존 아이템의 스코어를 업데이트하지 않는다
    • LT: 업데이트하고자 하는 스코어가 기존 아이템의 스코어보다 작을 때만 업데이트한다. 기존에 아이템이 존재하지 않을 때에는 새로운 데이터를 삽입한다
    • GT: 업데이트하고자 하는 스코어가 기존 아이템의 스코어보다 클 때만 업데이트한다. 기존에 아이템이 존재하지 않을 때에는 새로운 데이터를 삽입한다

5-2. ZRANGE

  • ZRANGE 커맨드를 사용하면 sorted set에 저장된 데이터를 조회할 수 있으며, start와 stop 범위를 항상 입력해야 한다
  • 인덱스로 데이터 조회
    • ZRANGE 커맨드는 기본적으로 인덱스를 기반으로 데이터를 조회하기 때문에 start와 stop 인자에는 검색하고자 하는 첫 번째와 마지막 인덱스를 전달
    • WITHSCORE 옵션을 사용하면 데이터와 함께 스코어 값이 차례대로 출력
    • REV 옵션을 사용하면 데이터는 역순으로 출력
  • 스코어로 데이터 조회
    • ZRANGE에 BYSCORE 옵션을 사용하면 스코어를 이용해 데이터 조회 가능
    • start, stop 인자 값으로는 조회하고자 하는 최소, 최대 스코어를 전달해야 한다
  • 사전 순으로 데이터 조회
    • 스코어가 같을 때 BYLEX 옵션을 사용하면 사전식 순서를 이용해 특정 아이템을 조회할 수 있다



6. Bitmap

  • Bitmap은 독자적인 자료 구조는 아니며, string 자료 구조에 bit 연산을 수행할 수 있도록 확장한 형태
  • string 자료구조가 binary safe하고 최대 512MB의 값을 저장할 수 있는 구조이기 때문에, 2^32의 비트를 가지고 있는 비트맵 형태라고 볼 수 있다

6-1. SETBIT

1
SETBIT mybitmap 2 1
  • SETBIT 커맨드로 비트 저장

6-2. GETBIT

1
GETBIT mybitmap 2
  • GETBIT 커맨드로 저장된 비트 조회

6-3. BITFIELD

1
BITFIELD mybitmap SET u1 6 1 SET u1 10 1 SET u1 14 1
  • BITFIELD 커맨드로 한 번에 여러 비트를 SET

6-4. BITCOUNT

1
BITCOUNT mybitmap
  • BITCOUNT 커맨드로 1로 설정된 비트의 개수 카운팅



7. Hyperloglog

  • hyperloglog는 집합의 원소 개수인 카디널리티를 추정할 수 있는 자료 구조
  • 대량 데이터에서 중복되지 않는 고유한 값을 집계할 때 사용
  • set과 같은 데이터 구조에서는 중복을 피하기 위해 저장된 데이터를 모두 기억하고 있으며, 저장되는 데이터가 많아질수록 그만큼 많은 메모리를 사용
  • hyperloglog는 입력되는 데이터 그 자체를 저장하지 않고 자체적인 방법으로 데이터를 변경해 처리한다.
    • 저장되는 데이터 개수에 구애받지 않고 계속 일정한 메모리를 유지할 수 있으며, 중복되지 않는 유일한 원소의 개수를 계산할 수 있다
  • 하나의 hyperloglog 자료구조는 최대 12KB의 크기를 가지며, 레디스에서 카디널리티 추정의 오차는 0.81%로, 비교적 정확하게 데이터를 추정할 수 있다
  • 하나의 hyperloglog 자료구조는 최대 2^64 개의 아이템을 저장할 수 있다
  • PFADD 커맨드
    • hyperloglog에 아이템 저장
  • PFCOUNT 커맨드
    • 저장된 아이템의 개수, 즉 카디널리티를 추정할 수 있다



8. Geospatial

  • Geospatial 자료구조는 경도, 위도 데이터 쌍의 집합으로 간편하게 지리 데이터를 저장
  • 내부적으로 데이터는 sorted set으로 저장되며, 하나의 자료구조 안에 키는 중복 저장되지 않는다
  • GEOADD <key> 경도 위도 member 순서로 저장
  • sorted set과 마찬가지로 XX 옵션을 사용하면 이미 아이템이 있는 경우에만, NX 옵션을 사용하면 아이템이 없는 경우에만 데이터를 저장
  • GEOPOS 커맨드
    • 저장된 위치 데이터 조화
  • GEODIST 커맨드
    • 두 아이템 사이의 거리 반환
  • GEOSEARCH 커맨드
    • 특정 위치를 기준으로 원하는 거리 내의 아이템 검색
    • BYRADIUS 옵션을 사용하면 반경 거리를 기준으로 조회
    • BYBOX 옵션을 사용하면 직사각형 거리를 기준으로 데이터를 조회



9. Stream

  • stream은 레디스를 메시지 브로커로서 사용할 수 있게 하는 자료 구조
  • stream 자료구조는 데이터를 계속해서 추가하는 방식(append-only)으로 저장하므로, 실시간 이벤트 혹은 로그성 데이터 저장을 위해 사용 가능
This post is licensed under CC BY 4.0 by the author.