본문 바로가기
프로그래밍/redis

[Redis] Redis 자료구조 알아보기

by 사바라다 2020. 12. 24.

안녕하세요. 이전 [Redis] Redis의 기본 명령어 포스팅에서 Redis의 기본적인 명령어와 이와 연관된 자료구조에 대해서 간단하게 알아본적이 있습니다. Redis는 다양한 자료구조를 기본적으로 제공하고 있는데 상당히 높은 생산성을 제공합니다.

Redis 자료구조를 잘 알고 적절하게 사용한다면 생산성 및 퍼포먼스도 얻을 수 있습니다. 따라서 오늘은 여러분들과 Redis의 자료구조에 대해서 알아보는 시간을 여러분들과 가져보려고합니다.

redis.io에 소개되고 있는 자료구조

Redis는 아래의 자료구조를 공식적으로 지원하고 있습니다.

  • Strings : Vinary-safe한 기본적인 key-value 구조
  • Lists : String element의 모음, 순서는 삽입된 순서를 유지하며 기본적인 자료구로 Linked List를 사용
  • Sets : 유일한 값들의 모임인 자료구조, 순서는 유지되지 않음
  • Sorted sets : Sets 자료구조에 score라는 값을 추가로 두어 해당 값을 기준으로 순서를 유지
  • Hahses : 내부에 key-value 구조를 하나더 가지는 Reids 자료구조
  • Bit arrays(bitMaps) : bit array를 다를 수 있는 자료구조
  • HyperLogLogs : HyperLogLog는 집합의 원소의 개수를 추정하는 방법, Set 개선된 방법
  • Streams : Redis 5.0 에서 Log나 IoT 신호와 같이 지속적으로 빠르게 발생하는 데이터를 처리하기 위해서 도입된 자료구조

아래의 각 자료구조에 대한 자세한 이야기는 https://redis.io/topics/data-types를 번역한 내용에 이해를 돕기 위한 간단한 설명을 추가하였습니다.

Strings

Strings 타입은 Redis의 가장 기본적인 Type 입니다. 일반적으로 우리가 알고 있는 Key-value 형식을 따르고 있습니다. key와 value 모두 binary safe 하기때문에 어떠한 데이터의 종류도 key, value의 값이 될 수 있습니다.

아래는 Strings 명령어의 특이사항 및 활용방법입니다.

  • 값의 최대 길이는 512MB입니다.
  • INCR, DECR, INCRBY 명령어를 통해 Atomic counters를 구현할 수 있습니다. Atomic Counter란 thread safe한 counter라 생각해 주시면 됩니다.
  • APPEND 명령어를 통해 값에 어펜드가 가능합니다.
  • GETRANGE, SETRANGE 명령어를 통해 값에 랜덤 엑세스가 가능합니다. 랜덤 액세스란 값의 어느 위치든 index를 통해 접근 할 수 있는 기능입니다.
> set mykey somevalue
OK
> get mykey
"somevalue"
> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152

Lists

Lists는 Linked List와 유사한 형태로 데이터가 저장되는 Redis에서 제공하는 자료구조입니다. 따라서 처음과 마지막 부분에 element를 추가 / 삭제 / 조회하는 것은 O(1)의 속도를 가지지만 중간의 특정 index 값을 조회할 때는 O(N)의 속도를 가지는 단점을 동일하게 가지고 있습니다. Linked List에 대해서 좀 더 알고 싶으신 분들은 제가 이전에 작성한 [자료구조] 코드로 알아보는 java의 LinkedHashMap를 참조하시면 좋을것 같습니다.

중간에 있는 index값을 가져와야할 경우가 많다면 Sorted Set 자료구조를 추천드립니다.

아래는 Lists 명령어의 특이사항 및 활용방법입니다.

  • 소셜네트워크에서 타임라인과 같은 기능을 구현할 때 LPUSH를 통해 제일 첫 부분에 Insert하며 LRANGE 명령어를 통해 일정 크기를 고정적으로 빠르게 반환할 수 있습니다.
  • LPUSH 명령어와 LTRIM 명령어를 함께 사용하면 Lists의 크기를 항상 일정하게 고정시킬 수 있습니다.
  • LPUSH와 RPOP을 이용한다면 message를 전달하는 queue로 사용할 수 있습니다.
> rpush mylist A
(integer) 1 # 들어있는 element 수 반환
> rpush mylist B
(integer) 2
> lpush mylist first
(integer) 3
> lrange mylist 0 -1 # 0을 기준으로 -1은 마지막, 1은 다음번째, -2는 마지막에서 2번째
                     # 이 예제는 처음부터 끝까지 
1) "first"
2) "A"
3) "B"
> rpush mylist 1 2 3 4 5 "foo bar"
(integer) 6
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "foo bar"
> rpush mylist a b c
(integer) 3
> rpop mylist
"c" # 삭제되넌 것 반환
> rpop mylist
"b"
> rpop mylist
"a"

Sets

Redis Sets는 순서가 보장되지않는 Strings의 집합 자료구조입니다. 기본적으로 추가, 삭제, element의 존재 유무확인 등에 대해서 O(1)의 속도를 보장합니다. 또한 Set 이기 때문에 동일한 value는 추가한다고 해서 2개가 공존하지 않습니다.

> sadd myset 1 2 3
(integer) 3
> smembers myset
1. 3
2. 1
3. 2

아래는 Sets 명령어의 특이사항 및 활용방법입니다.

  • 트래킹에 사용될 수 있습니다. 블로그에 접근한 IP 리스트를 관리하고자 할 때 중복을 허용하지 않는 Sets 자료구조를 활용한다면 좋을 결과를 얻을 수 있을 것입니다.
  • 모든 태그를 나타내는 리스트에도 사용될 수 있습니다. 각 포스팅마다 태그가 있고 해당 태그의 모든 리스트를 보고 싶을 때 중복이 허용되지 않는 Set은 사용하기 좋은 자료구조 일 수 있습니다.
  • Sets는 Sets간의 합집합, 차집합 등을 지원해주기 때문에 문제해결에 도움이 될 수 있습니다. ex) SINTER
  • Sets의 요소를 랜덤으로 뽑는 SPOP, SRANDMEMBER 등의 명령어가 있습니다.

Hashes

Redis의 Hashes는 value로 또 다른 key-value Map을 가지는 자료구조입니다. 쉽게 이해하기 위해서 아래의 바로 예제를 보도록 하게습니다.

> hmset user:1000 username antirez birthyear 1977 verified 1
OK
> hget user:1000 username # user:1000 key와 username 이라는 hashkey를 이용하여 Get
"antirez"
> hget user:1000 birthyear
"1977"
> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"

Sorted sets

Redis의 Sorted sets 자료구조는 Sets 자료구조에 Score를 추가로 기록하여 score가 낮은순서부터 높은순서대로 정렬되는 자료구조입니다. 동일한 값은 오지 못하며 Score는 동일할 수 있다는 사실을 명심하셔야합니다.

아래는 Sorted Sets 명령어의 특이사항 및 활용방법입니다.

  • 온라인 게임의 랭킹에 사용될 수 있습니다. ZADD 명령어를 통해 score와 이름을 함께 보내면 쉽고 빠르게 정렬되고 유일값을 가지는 자료구조를 만들 수 있습니다. 또한 찾을때는 ZRANK, ZRANGE 명령어를 이용할 수 있습니다.
  • Sorted Sets는 자주 Redis에 저장된 데이터의 index를 저장하기 위해서 사용되기도 합니다.hashes에 user를 담아둔다고 한다면 이 값을 나이순으로 정렬하던지 할 수 있는 것입니다.
> zadd hackers 1940 "Alan Kay" # sorted Sets 자료구조로 추가
(integer) 1
> zadd hackers 1957 "Sophie Wilson"
(integer) 1
> zadd hackers 1953 "Richard Stallman"
(integer) 1
> zadd hackers 1949 "Anita Borg"
(integer) 1
> zadd hackers 1965 "Yukihiro Matsumoto"
(integer) 1
> zadd hackers 1914 "Hedy Lamarr"
(integer) 1
> zadd hackers 1916 "Claude Shannon"
(integer) 1
> zadd hackers 1969 "Linus Torvalds"
(integer) 1
> zadd hackers 1912 "Alan Turing"
(integer) 1
> zrange hackers 0 -1 # score를 통한 범위 검색
1) "Alan Turing"
2) "Hedy Lamarr"
3) "Claude Shannon"
4) "Alan Kay"
5) "Anita Borg"
6) "Richard Stallman"
7) "Sophie Wilson"
8) "Yukihiro Matsumoto"
9) "Linus Torvalds"

마무리

오늘은 이렇게 Redis의 자료구조와 어떻게 활용하면 좋을지에 대해서 알아보는 시간을 가져보았습니다.

Redis는 잘 활용만 한다면 정말 빠른 퍼포먼스를 기대할 수 있습니다.

감사합니다.

참조

redis_data-types

redis_data-types-intro

redisgate_hyperloglog

댓글