Redis - Set
이 포스트는 Redis 의 데이터 타입 중 하나인 Set
타입에 대해 알아본다.
1. Set
List
가 하나의 key 에 여러 개의 배열값을 저장하는 데이터 구조라고 하면Set
은 배열 구조가 아닌 여러 개의member
로 데이터 값을 표현하는 데이터 구조- 중복을 제거하거나, 집합 연산 (포함여부 및 합집합, 교집합 등) 을 해야할 경우에 사용
$ pwd
/usr/local/opt/redis/bin
$ brew services start redis
==> Successfully started `redis` (label: homebrew.mxcl.redis)
$ redis-cli
127.0.0.1:6379>
1.1. 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
127.0.0.1:6379> sadd set1 e1 e2 e3
(integer) 3
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> sadd set1 e2 # 이미 추가된 element 는 추가해도 변화없음
(integer) 0
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
1.2. SMEMBERS
set 안의 모든 member 를 조회하는 명령어이다.
127.0.0.1:6379> help smembers
SMEMBERS key
summary: Get all the members in a set
since: 1.0.0
group: set
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
1.3. SCARD
set 에 있는 member 갯수를 조회하는 명령어이다.
127.0.0.1:6379> help scard
SCARD key
summary: Get the number of members in a set
since: 1.0.0
group: set
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> scard set1
(integer) 3
1.4. SISMEMBER
set 안에 해당 member 가 존재하는지 여부를 조회한다.
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
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> sismember set1 e1
(integer) 1
127.0.0.1:6379> sismember set1 99
(integer) 0
1.5. 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
127.0.0.1:6379> sadd set1 e1 e2 e3 e4
(integer) 4
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e4"
4) "e3"
127.0.0.1:6379> srem set1 e1 e2 e9 e2 # e9 는 없는 member 이지만 오류를 뱉지 않는다.
(integer) 2
127.0.0.1:6379> smembers set1
1) "e4"
2) "e3"
127.0.0.1:6379> smembers set99
(empty array)
127.0.0.1:6379> srem set99 e4 # set99 는 존재하지 않는 set 이지만 오류를 뱉지 않는다.
(integer) 0
1.6. SSCAN
keys
는 전체 데이터를 조회해서 장애를 일으킬 수 있다.
성능을 위해 Hash 에서도 keys
대신 HSCAN
을 사용하는 것처럼 Set 에서도 전체 members
를 조회할 때 SSCAN
을 사용한다.
HSCAN
에 대한 내용은 Redis - Hash 의 2.11.HSCAN
을 참고하세요.
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
아래에서 1) 에 리턴되는 것이 명령을 수행한 후의 커서이다.
다음 호출은 해당 커서부터 실행하면 된다.
count 에 2를 부여했지만 4개, 3개가 리턴되기도 한다.
커서가 0 을 리턴하면 모든 데이터를 다 가져왔다는 의미이므로 커서 기반으로 로직 작성 시 커서가 0 이 될때까지 반복하면 된다.
127.0.0.1:6379> sadd set1 e1 e2 e3 e4 e5 e6 e7 e8 e9 e10
(integer) 10
127.0.0.1:6379> smembers set1
1) "e3"
2) "e6"
3) "e5"
4) "e8"
5) "e2"
6) "e7"
7) "e4"
8) "e1"
9) "e9"
10) "e10"
127.0.0.1:6379> sscan set1 0 count 2
1) "6"
2) 1) "e9"
2) "e3"
3) "e6"
4) "e5"
127.0.0.1:6379> sscan set1 6 count 2
1) "1"
2) 1) "e7"
2) "e4"
127.0.0.1:6379> sscan set1 1 count 2
1) "3"
2) 1) "e1"
2) "e2"
3) "e10"
127.0.0.1:6379> sscan set1 3 count 2
1) "0"
2) 1) "e8"
127.0.0.1:6379> sadd set1 e1 e2 e3 e4 e5 e6 e7 e8 e9 e10
(integer) 10
127.0.0.1:6379> smembers set1
1) "e3"
2) "e6"
3) "e5"
4) "e8"
5) "e2"
6) "e7"
7) "e4"
8) "e1"
9) "e9"
10) "e10"
127.0.0.1:6379> sscan set1 0 match e1* count 10
1) "7"
2) 1) "e1"
2) "e10"
127.0.0.1:6379> sscan set1 7 match e1* count 10
1) "0"
2) (empty array)
SCAN 명령어는 싱글 스레드 아키텍처에서 keys
와 smembers
가 가진 문제점을 해결하는 명령어이지만 아래와 같은 문제점도 있으니 주의하자.
- scan 의 경우 table 의 한 블럭을 조회하기 때문에 갯수가 많으면 시간이 오래 걸릴 수 있음
set
/sorted set
/hash
의 내부 구조가 hash table 이나 skiplist 가 아니면 (ziplist 로 구현된 경우) 한 컬렉션의 모든 데이터를 가져오기 때문에keys
와 비슷한 문제가 그대로 발생할 수 있음count
옵션을 지정할 수 있지만 그 갯수를 엄격하게 보장해주지 않음 (=count 를 2로 해도 4개 리턴해주기도 함)
1.7. SMOVE
source set 에서 destination set 으로 member 를 이동시키는 명령어이다.
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
127.0.0.1:6379> sadd set1 e1 e2
(integer) 2
127.0.0.1:6379> sadd set2 e3 e4
(integer) 2
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
127.0.0.1:6379> smembers set2
1) "e4"
2) "e3"
127.0.0.1:6379> smove set1 set2 e1 # set1 의 member 를 set2 로 이동시킨다.
(integer) 1
127.0.0.1:6379> smembers set1
1) "e2"
127.0.0.1:6379> smembers set2
1) "e1"
2) "e4"
3) "e3"
127.0.0.1:6379> smove set1 set3 e2 # set1 의 member 를 존재하지 않는 set3 으로 이동시킨다.
(integer) 1
127.0.0.1:6379> smembers set1
(empty array)
127.0.0.1:6379> smembers set3 # set3 이 생성되었다.
1) "e2"
127.0.0.1:6379> smembers set2
1) "e1"
2) "e4"
3) "e3"
127.0.0.1:6379> smembers set3
1) "e2"
127.0.0.1:6379> smove set2 set3 e9 # set2 에 존재하지 않는 member 인 e9 를 set3 으로 이동시키면 아무런 변화가 없다.
(integer) 0
127.0.0.1:6379> smembers set2
1) "e1"
2) "e4"
3) "e3"
127.0.0.1:6379> smembers set3
1) "e2"
1.8. SRANDMEMBER
set 에서 랜덤하게 count 수만틈 member 를 조회한다.
count 를 지정하지 않으면 랜덤으로 1개를 조회하고, count 를 0 으로 지정하면 빈 배열을 리턴한다.
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
127.0.0.1:6379> sadd set1 e1 e2 e3 e4 e5
(integer) 5
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e4"
4) "e3"
5) "e5"
127.0.0.1:6379> srandmember set1
"e3"
127.0.0.1:6379> srandmember set1 0
(empty array)
127.0.0.1:6379> srandmember set1 3
1) "e5"
2) "e3"
3) "e2"
127.0.0.1:6379> srandmember set1 3
1) "e1"
2) "e5"
3) "e3"
1.9. SPOP
SRANDMEMBER
와 동일하게 count 갯수만큼 member 를 조회하지만 조회 후 해당 member 를 삭제한다.
SRANDMEMBER
- peek, SPOP
- pop
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
127.0.0.1:6379> smembers set1
1) "e1"
2) "e3"
3) "e5"
4) "e2"
5) "e4"
127.0.0.1:6379> spop set1
"e3"
127.0.0.1:6379> smembers set1
1) "e1"
2) "e5"
3) "e2"
4) "e4"
127.0.0.1:6379> spop set1 2
1) "e4"
2) "e2"
127.0.0.1:6379> smembers set1
1) "e1"
2) "e5"
127.0.0.1:6379> spop set1 5
1) "e1"
2) "e5"
127.0.0.1:6379> smembers set1
(empty array)
1.10. SUNION
, SINTER
, SDIFF
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
SUNION
127.0.0.1:6379> sadd set1 e1 e2
(integer) 2
127.0.0.1:6379> sadd set2 e3 e4
(integer) 2
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
127.0.0.1:6379> smembers set2
1) "e4"
2) "e3"
127.0.0.1:6379> sunion set1 set2
1) "e1"
2) "e2"
3) "e3"
4) "e4"
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
SINTER
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
127.0.0.1:6379> smembers set2
1) "e4"
2) "e3"
127.0.0.1:6379> sinter set1 set2
(empty array)
127.0.0.1:6379> sadd set1 e3
(integer) 1
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> smembers set2
1) "e4"
2) "e3"
127.0.0.1:6379> sinter set1 set2
1) "e3"
SDIFF
127.0.0.1:6379> smembers set1
1) "e2"
2) "e1"
3) "e3"
127.0.0.1:6379> smembers set2
1) "e4"
2) "e3"
127.0.0.1:6379> sdiff set1 set2
1) "e1"
2) "e2"
127.0.0.1:6379> sdiff set2 set1
1) "e4"
1.11. SUNIONSTORE
, SINTERSTORE
, SDIFFSTORE
SUNION
, SINTER
, SDIFF
로 수행한 결과를 새로운 set 으로 저장할 때 사용하는 명령어이다.
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
127.0.0.1:6379> sadd set1 e1 e2 e3
(integer) 3
127.0.0.1:6379> sadd set2 e4 e5 e2 e3
(integer) 4
127.0.0.1:6379> smembers set1
1) "e3"
2) "e1"
3) "e2"
127.0.0.1:6379> smembers set2
1) "e3"
2) "e4"
3) "e5"
4) "e2"
127.0.0.1:6379> sunionstore set_all
(error) ERR wrong number of arguments for 'sunionstore' command
127.0.0.1:6379> sunionstore set_all set1 # set1 만 union 하여 set_all 로 저장
(integer) 3
127.0.0.1:6379> smembers set_all
1) "e3"
2) "e1"
3) "e2"
127.0.0.1:6379> smembers set1
1) "e3"
2) "e1"
3) "e2"
127.0.0.1:6379> sunionstore set_all set1 set2 # set1, set2 를 union 하여 set_all 로 저장
(integer) 5
127.0.0.1:6379> smembers set_all
1) "e4"
2) "e1"
3) "e2"
4) "e5"
5) "e3"
127.0.0.1:6379> smembers set1
1) "e3"
2) "e1"
3) "e2"
127.0.0.1:6379> sunionstore set_all set1 set3 # set1 과 존재하지 않는 set3 을 union 하여 set_all 로 저장
(integer) 3
127.0.0.1:6379> smembers set_all # set1 만 union 되어 set_all 로 저장된다.
1) "e3"
2) "e1"
3) "e2"
1.12. SINTERCARD
여러 set 의 교집합을 한 후 해당되는 member 의 갯수를 리턴한다.
127.0.0.1:6379> help sintercard
SINTERCARD numkeys key [key ...] [LIMIT limit]
summary: Intersect multiple sets and return the cardinality of the result
since: 7.0.0
group: set
127.0.0.1:6379> sadd set1 e1 e2 e3
(integer) 3
127.0.0.1:6379> sadd set2 e2 e3 e4
(integer) 3
127.0.0.1:6379> sintercard 2 set1 set2 # e2, e3
(integer) 2
127.0.0.1:6379> smembers set1
1) "e3"
2) "e1"
3) "e2"
127.0.0.1:6379> sadd set1 e4
(integer) 1
127.0.0.1:6379> smembers set1
1) "e3"
2) "e4"
3) "e1"
4) "e2"
127.0.0.1:6379> sintercard 2 set1 set2 # e2, e3, e4
(integer) 3
127.0.0.1:6379> sintercard 1 set1 set2 # numkeys 가 1 인데 연산되는 set 의 갯수가 2개라 오류 발생
(error) ERR syntax error
127.0.0.1:6379> sintercard 3 set1 set2 # numkeys 가 3 인데 연산되는 set 의 갯수가 2개라 오류 발생
(error) ERR Number of keys can't be greater than number of args
참고 사이트 & 함께 보면 좋은 사이트
본 포스트는 주종면 저자의 빅데이터 저장 및 분석을 위한 NoSQL & Redis를 기반으로 스터디하며 정리한 내용들입니다.
- 빅데이터 저장 및 분석을 위한 NoSQL & Redis
- 빅데이터 저장 및 분석을 위한 NoSQL & Redis - 실습파일
- https://redis.io/commands
- https://redis.io/commands - set
- Resit 자료 구조 - Set
- Redis의 SCAN은 어떻게 동작하는가?