Redis 자료 구조 - Set
- Development/Hadoop, NoSQL, BigData
- 2021. 5. 12.
개요
프로그래밍 언어에서 어떨 때 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 pub/sub 소개 (2) | 2021.06.17 |
---|---|
Redis Geo - Geospatial 명령어 (0) | 2021.06.07 |
Redis 자료 구조 - ZSet (Sorted Set) (0) | 2021.06.02 |
Redis 자료 구조 - Hash (0) | 2021.05.27 |
Redis 자료 구조 - List (0) | 2021.05.10 |
Redis 자료 구조 - String (0) | 2021.05.06 |
Memcached vs. Redis - 특징 비교 (0) | 2021.05.03 |
Redis 개요 (0) | 2021.04.28 |