1.集合定义
集合类型也是用来保存多个字符串元素,但和列表类型不一样的是,
集合中不允许有重复元素,并且元素是无序的,不能通过索引下表获取元素。
一个集合最多可以存储2^32-1个元素。redis除了支持集合内的增删改查,
同时还支持多个集合取交集,并集,差集。
2.使用集合
(1)添加元素
192.168.1.51:6379> exists myset
(integer) 0
192.168.1.51:6379> sadd myset a b c
(integer) 3
192.168.1.51:6379> sadd myset a b --重复的就加不进去。
(integer) 0
(2)删除元素
--查看元素。
192.168.1.51:6379> smembers myset
1) "b"
2) "c"
3) "a"
--返回结果为成功删除的个数。
192.168.1.51:6379> srem myset a b
(integer) 2
192.168.1.51:6379> srem myset hello
(integer) 0
192.168.1.51:6379> smembers myset
1) "c"
(3)计算元素个数
192.168.1.51:6379> scard myset
(integer) 2
scard:不会遍历所有集合元素,而是直接用redis的内部变量。
(4)判断元素是否在集合中
192.168.1.51:6379> sismember myset hello
(integer) 1
--返回1,表示元素在集合中。
(5)随机取几个元素
--任意取两个。
192.168.1.51:6379> srandmember myset 2
1) "hello"
2) "c"
--随机取一个
192.168.1.51:6379> srandmember myset
"c"
(6)从集合随机删除元素。
192.168.1.51:6379> smembers myset
1) "g"
2) "c"
3) "a"
4) "d"
5) "e"
6) "hello"
7) "f"
8) "b"
--会返回弹出的元素。
192.168.1.51:6379> spop myset
"c"
--随机删除两个元素。
192.168.1.51:6379> spop myset 2
1) "f"
2) "e"
192.168.1.51:6379> smembers myset
1) "g"
2) "a"
3) "d"
4) "hello"
5) "b"
redis从3.2版本开始,spop支持[count]参数,指定随机弹出x个元素。
(7)查看集合所有元素
192.168.1.51:6379> smembers myset
1) "g"
2) "a"
3) "d"
4) "hello"
5) "b"
smembers 和lrange,hgetall 都属于比较重的命令,如果元素过多存在阻塞
redis的可能,这时候可以使用sscan来完成。
3.集合间操作
192.168.1.51:6379> sadd user:1:follow it music his sports
(integer) 4
192.168.1.51:6379> sadd user:2:follow it news ent sports
(integer) 4
(1)求多个集合的交集
192.168.1.51:6379> sinter user:1:follow user:2:follow
1) "sports"
2) "it"
(2)求集合的并集
192.168.1.51:6379> sunion user:1:follow user:2:follow
1) "it"
2) "sports"
3) "ent"
4) "his"
5) "news"
6) "music"
(3)求多个集合的差集
--前面的减去后面的。
192.168.1.51:6379> sdiff user:1:follow user:2:follow
1) "his"
2) "music"
(4)将交集,并集,差集的结果保存。
sinterstore user:1_2:inter user:1:follow user:2:follow
--两个结合的交集保存在 user:1_2:inter
192.168.1.51:6379> sinterstore user:1_2:inter user:1:follow user:2:follow
(integer) 2
192.168.1.51:6379> smembers user:1_2:inter
1) "sports"
2) "it"
集合间的运算在元素较多的情况会比较耗时,所以redis提供了上面三个命令
将交集,并集,差集的结果保存;
192.168.1.51:6379> type user:1_2:inter
set
--并集保存
192.168.1.51:6379> sunionstore user:1_2:union user:1:follow user:2:follow
(integer) 6
192.168.1.51:6379> smembers user:1_2:union
1) "it"
2) "sports"
3) "ent"
4) "his"
5) "news"
6) "music"
--差集保存
192.168.1.51:6379> sdiffstore user:1_2:diff user:1:follow user:2:follow
(integer) 2
192.168.1.51:6379> smembers user:1_2:diff
1) "his"
2) "music"
4.内部编码
集合类型的内部编码有两种
intset(整数集合);
当元素中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512)
时,redis会选用 intset 来作为集合的内部实现,从而减少内存的使用。
hashtable(哈希表):
当集合无法满足intset的条件时,redis会使用hashtable作为集合的内部实现。
当元素不为整数时,内部编码也会变成hashtable;
5.使用场景
集合类型比较典型的使用场景是标签。一个人的不同标签放在一起。
实现精准营销。
(1)给用户添加标签
192.168.1.51:6379> sadd user:1:tags tag1 tag2 tag3
(integer) 3
192.168.1.51:6379> smembers user:1:tags
1) "tag3"
2) "tag2"
3) "tag1"
(2)给标签添加用户
192.168.1.51:6379> sadd tag1:users user:1 user:2 user:3
(integer) 3
192.168.1.51:6379> smembers tag1:users
1) "user:3"
2) "user:2"
3) "user:1"
用户和标签的关系维护应该放在一个事务内完成,防止部分命令失败造成的数据不一致。
(3)删除用户下标签
192.168.1.51:6379> srem user:1:tags tag1 tag2
(integer) 2
192.168.1.51:6379> smembers user:1:tags
1) "tag3"
其他说明:
sadd=tagging(标签)
spop/srandmember=Random item(生成随机数,比如抽奖)
sadd+sinter=Socal Graph(社交需求)