Redis 자료 구조 - Set

    개요

    프로그래밍 언어에서 어떨 때 set을 사용할까? 주로 중복을 제거하거나, 말 그대로 집합 연산(포함여부 및 합집합/교집합 등)을 해야할 경우에 사용할 것이다. Redis에서도 이러한 연산을 지원한다.


    명령어

    Redis가 지원하는 집합 연산 기능은 아래와 같다.


    SADD

    127.0.0.1:6379> help sadd
    
      SADD key member [member ...]
      summary: Add one or more members to a set
      since: 1.0.0
      group: set

    set에 아이템을 추가한다.

    // 여러 아이템을 set에 추가
    127.0.0.1:6379> sadd s1 e1 e2 e3
    (integer) 3
    
    127.0.0.1:6379> smembers s1
    1) "e2"
    2) "e3"
    3) "e1"
    
    // 이미 추가된 아이템을 다시 추가시도 -> 변화 없음
    127.0.0.1:6379> sadd s1 e1
    (integer) 0

    SREM

    127.0.0.1:6379> help srem
    
      SREM key member [member ...]
      summary: Remove one or more members from a set
      since: 1.0.0
      group: set

    지정한 요소(들)를 set에서 삭제한다. 여러 개의 요소도 지울 수 있다. 없는 요소가 지정되면 무시한다.

    127.0.0.1:6379> sadd s1 e1 e2 e3
    (integer) 3
    
    127.0.0.1:6379> smembers s1
    1) "e2"
    2) "e3"
    3) "e1"
    
    // 요소 한 개 지우기
    127.0.0.1:6379> srem s1 e1
    (integer) 1
    127.0.0.1:6379> smembers s1
    1) "e2"
    2) "e3"
    
    // 요소 여러 개 지우기 (없는 요소도 지정해 봄)
    127.0.0.1:6379> srem s1 e1 e2 e3
    (integer) 2
    127.0.0.1:6379> smembers s1
    (empty array)

    SCARD

    127.0.0.1:6379> help scard
    
      SCARD key
      summary: Get the number of members in a set
      since: 1.0.0
      group: set

    set에 들어가 있는 아이템 갯수(cardinality)를 리턴한다.

    // 여러 아이템을 set에 추가
    127.0.0.1:6379> sadd s1 e1 e2 e3
    (integer) 3
    
    // 갯수 확인
    127.0.0.1:6379> scard s1
    (integer) 3

    SISMEMBER

    127.0.0.1:6379> help sismember
    
      SISMEMBER key member
      summary: Determine if a given value is a member of a set
      since: 1.0.0
      group: set

    set에 포함된 요소인지 검사한다.

    // 여러 아이템을 set에 추가
    127.0.0.1:6379> sadd s1 e1 e2 e3
    (integer) 3
    
    // s1에 e1이 포함되어 있는지 확인
    127.0.0.1:6379> sismember s1 e1
    (integer) 1
    
    // s1에 e2가 포함되어 있는지 확인
    127.0.0.1:6379> sismember s1 e5
    (integer) 0

    SMEMBERS

    127.0.0.1:6379> help smembers
    
      SMEMBERS key
      summary: Get all the members in a set
      since: 1.0.0
      group: set

    set에 들어가 있는 모든 아이템들을 조회한다.

    // 여러 아이템을 set에 추가
    127.0.0.1:6379> sadd s1 e1 e2 e3
    (integer) 3
    
    127.0.0.1:6379> smembers s1
    1) "e2"
    2) "e3"
    3) "e1"

    모든 아이템을 조회하므로, set에 들어가 있는 아이템의 크기에 따라 성능의 영향을 받을 수 있다. 운영환경에서 전체 데이터를 가져와야 하면 SSCAN을 사용하자.


    SSCAN

    127.0.0.1:6379> help sscan
    
      SSCAN key cursor [MATCH pattern] [COUNT count]
      summary: Incrementally iterate Set elements
      since: 2.8.0
      group: set

    keys가 전체 데이터를 긁어와서 장애를 일으킬 수 있기 때문에 scan을 써야 하는 것과 같이, 집합에서도 전체 members를 가져올 때 사용한다. 분할해서 가져오는 방식이기 때문에 여러번 호출해 줘야 한다.

    // 전체 데이터
    127.0.0.1:6379> smembers s_all
     1) "e3"
     2) "e2"
     3) "e7"
     4) "e5"
     5) "e4"
     6) "e9"
     7) "e10"
     8) "e6"
     9) "e1"
    10) "e8"
    
    // 두 개씩 가져오기
    127.0.0.1:6379> sscan s_all 0 count 2
    1) "2"
    2) 1) "e2"
       2) "e7"
    127.0.0.1:6379> sscan s_all 2 count 2
    1) "5"
    2) 1) "e5"
       2) "e4"
       3) "e9"
    127.0.0.1:6379> sscan s_all 5 count 2
    1) "7"
    2) 1) "e8"
       2) "e10"
       3) "e6"
       4) "e1"
    127.0.0.1:6379> sscan s_all 7 count 2
    1) "0"
    2) 1) "e3"

    1)에 리턴되는 것이 명령을 수행한 후의 커서이다. 즉, 다음 페이지는 저 커서부터 실행하면 된다. count에 숫자를 부여했지만, 저 숫자를 엄격하게 보장해주지는 않는다. 위의 결과에서 보다시피, count로 2를 줬지만 2개를 주기도 4개를 주기도 한다. 커서가 0이 리턴되면 모든 데이터를 다 가져왔다는 즉 다음 페이지가 없다는 의미이다. 즉, 커서를 기반으로 로직을 작성한다면 커서가 0이 리턴될 때까지 반복해야 한다는 뜻이다.

    127.0.0.1:6379> sscan s_all 0 match e1* count 10
    1) "0"
    2) 1) "e10"
       2) "e1"

    위와 같이 match 조건을 추가적으로 부여할 수도 있다.


    SMOVE

    127.0.0.1:6379> help smove
    
      SMOVE source destination member
      summary: Move a member from one set to another
      since: 1.0.0
      group: set

    말 그대로, 집합내 어떤 요소를 다른 집합으로 옮기는 기능이다.

    // e12는 짝수인데, 실수로 s_odd에 넣었다.
    127.0.0.1:6379> sadd s_odd e12
    (integer) 1
    
    127.0.0.1:6379> smembers s_odd
    1) "e9"
    2) "e1"
    3) "e12"
    4) "e7"
    5) "e5"
    6) "e3"
    
    // e12를 원래대로 짝수 집합으로 옮기고 싶다.
    127.0.0.1:6379> smove s_odd s_even e12
    (integer) 1
    
    // 홀수 집합에서 e12가 사라짐
    127.0.0.1:6379> smembers s_odd
    1) "e9"
    2) "e1"
    3) "e7"
    4) "e5"
    5) "e3"
    
    // 짝수 집합에 e12가 추가됨
    127.0.0.1:6379> smembers s_even
    1) "e8"
    2) "e4"
    3) "e6"
    4) "e2"
    5) "e10"
    6) "e12"

    SRANDMEMBER

    127.0.0.1:6379> help srandmember
    
      SRANDMEMBER key [count]
      summary: Get one or multiple random members from a set
      since: 1.0.0
      group: set

    set에서 count 만큼의 요소를 무작위로 가져온다.

    127.0.0.1:6379> sadd s1 e1 e2 e3
    (integer) 3
    
    // 2개 요소 가져옴
    127.0.0.1:6379> srandmember s1 2
    1) "e1"
    2) "e3"
    
    // 원본 set에는 변화 없음
    127.0.0.1:6379> smembers s1
    1) "e2"
    2) "e3"
    3) "e1"

    원본 set의 상태에는 변화가 없다. count를 생략하면 기본적으로 count = 1로 간주한다. 음수로 지정해도 동작하는데 양수를 넣은 것과 큰 차이는 없다.

    // count 생략시
    127.0.0.1:6379> srandmember s1
    "e1"
    127.0.0.1:6379> srandmember s1
    "e3"
    
    // count를 음수로 지정시
    127.0.0.1:6379> srandmember s1 -1
    1) "e3"
    127.0.0.1:6379> srandmember s1 -2
    1) "e2"
    2) "e3"
    127.0.0.1:6379> srandmember s1 -3
    1) "e3"
    2) "e3"
    3) "e1"

    SPOP

    127.0.0.1:6379> help spop
    
      SPOP key [count]
      summary: Remove and return one or multiple random members from a set
      since: 1.0.0
      group: set

    SRANDMEMBER와 비슷하지만, 차이점은 실행 후의 액션이다. SRANDMEMBER는 조회만 하지만, SPOP은 해당 요소를 삭제한다. SRANDMEMBER가 peek이라면, SPOP은 이름처럼 pop을 해버린다.

    // count를 지정하지 않으먼, 1로 간주
    127.0.0.1:6379> spop s1
    "e1"
    
    // 1개 요소가 사라짐
    127.0.0.1:6379> smembers s1
    1) "e2"
    2) "e3"
    
    // 두 개 요소만 있는 상태에서, 5개를 지우라고 함
    127.0.0.1:6379> spop s1 5
    1) "e2"
    2) "e3"
    
    // 모두 지워지고 빈 set이 됨
    127.0.0.1:6379> smembers s1
    (empty array)

    SUNION, SINTER, SDIFF

    127.0.0.1:6379> help sunion
    
      SUNION key [key ...]
      summary: Add multiple sets
      since: 1.0.0
      group: set
    
    127.0.0.1:6379> help sinter
    
      SINTER key [key ...]
      summary: Intersect multiple sets
      since: 1.0.0
      group: set
    
    127.0.0.1:6379> help sdiff
    
      SDIFF key [key ...]
      summary: Subtract multiple sets
      since: 1.0.0
      group: set

    합집합 연산부터 살펴본다.

    // 편의상 e[1,3,5,7,9] = 홀수집합이라고 표현
    // 편의상 e[2,4,6,8,19] = 짝수집합이라고 표현
    
    // 홀수 집합 
    127.0.0.1:6379> smembers s_odd
    1) "e7"
    2) "e5"
    3) "e3"
    4) "e1"
    5) "e9"
    
    // 짝수 집합
    127.0.0.1:6379> smembers s_even
    1) "e2"
    2) "e8"
    3) "e4"
    4) "e6"
    5) "e10"
    
    // 홀수 + 짝수 합집합
    127.0.0.1:6379> sunion s_odd s_even
     1) "e4"
     2) "e9"
     3) "e1"
     4) "e7"
     5) "e8"
     6) "e5"
     7) "e3"
     8) "e2"
     9) "e10"
    10) "e6"

    교집합은 아래와 같다.

    // 전체
    127.0.0.1:6379> smembers s_all
     1) "e3"
     2) "e2"
     3) "e7"
     4) "e5"
     5) "e4"
     6) "e9"
     7) "e10"
     8) "e6"
     9) "e1"
    10) "e8"
    
    // 부분
    127.0.0.1:6379> smembers s_odd
    1) "e7"
    2) "e5"
    3) "e3"
    4) "e1"
    5) "e9"
    
    // 전체와 부분의 교집합
    127.0.0.1:6379> sinter s_all s_odd
    1) "e7"
    2) "e5"
    3) "e3"
    4) "e1"
    5) "e9"

    차집합의 예는 아래와 같다.

    // 전체
    127.0.0.1:6379> smembers s_all
     1) "e3"
     2) "e2"
     3) "e7"
     4) "e5"
     5) "e4"
     6) "e9"
     7) "e10"
     8) "e6"
     9) "e1"
    10) "e8"
    
    // 부분
    127.0.0.1:6379> smembers s_odd
    1) "e7"
    2) "e5"
    3) "e3"
    4) "e1"
    5) "e9"
    
    // 전체 - 부분
    127.0.0.1:6379> sdiff s_all s_odd
    1) "e2"
    2) "e4"
    3) "e6"
    4) "e10"
    5) "e8"

    SUNIONSTORE, SINTERSTORE, SDIFFSTORE

    127.0.0.1:6379> help sunionstore
    
      SUNIONSTORE destination key [key ...]
      summary: Add multiple sets and store the resulting set in a key
      since: 1.0.0
      group: set
    
    127.0.0.1:6379> help sinterstore
    
      SINTERSTORE destination key [key ...]
      summary: Intersect multiple sets and store the resulting set in a key
      since: 1.0.0
      group: set
    
    127.0.0.1:6379> help sdiffstore
    
      SDIFFSTORE destination key [key ...]
      summary: Subtract multiple sets and store the resulting set in a key
      since: 1.0.0
      group: set

    위에서 수행한 집합 연산 결과를 또다른 집합(set)으로 저장하고 싶다면, 이 명령어를 쓴다.

    // s_even과 s_odd를 합쳐서 s_all로 만들기
    127.0.0.1:6379> sunionstore s_all s_even s_odd
    (integer) 10
    
    127.0.0.1:6379> smembers s_all
     1) "e4"
     2) "e6"
     3) "e10"
     4) "e7"
     5) "e8"
     6) "e5"
     7) "e3"
     8) "e2"
     9) "e9"
    10) "e1"

    교집합과 차집합도 동일하다. 명령어 output input1 input2 .. 의 형식을 그대로 따른다.


    'Development > Hadoop, NoSQL, BigData' 카테고리의 다른 글

    Redis 자료 구조 - ZSet (Sorted Set)  (0) 2021.06.02
    Redis 자료 구조 - Hash  (0) 2021.05.27
    Redis 자료 구조 - Set  (0) 2021.05.12
    Redis 자료 구조 - List  (0) 2021.05.10
    Redis 자료 구조 - String  (0) 2021.05.06
    Memcached vs. Redis - 특징 비교  (0) 2021.05.03

    댓글(0)

    Designed by JB FACTORY