企业级Redis开发运维从入门到实践 (7)— set数据结构的内部编码及相关命令详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zx711166/article/details/82744461

集合的内部编码

集合类型的内部编码有两种:

  • intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合内部实现,从而减少内存的使用。
  • hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

下面用示例来说明:

当元素个数较少且都为整数时,内部编码为intset:
127.0.0.1:6379> sadd setkey 2 3 4 5
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"
当元素个数超过512个,内部编码变为hashtable:
127.0.0.1:6379>sadd setkey2 1 2 3 4 5 6 7...  511 512 513
OK
127.0.0.1:6379> object encoding setkey2
"hashtable"
当某个元素不为整数时,内部编码也会变为hashtable:
127.0.0.1:6379> sadd setkey3 a b c
(integer) 3
127.0.0.1:6379> object encoding setkey2
"hashtable"

集合结构

结构依然还是key-value的结构,key还是字符串类型,value是一个集合,可以将若干字符串进行一个组合。

这里写图片描述

  • 可以使用sadd向集合增加数据。

这里写图片描述

  • 集合中不能存在重复数据,向集合中插入重复数据将会失败。

这里写图片描述

  • 可是使用srem key music,删除集合中的数据。

这里写图片描述

  • redis中还支持集合间的API操作,sinter实现集合间相同的元素(交集),sdiff实现集合间不同的元素(差集),sunion实现集合间所有的元素(并集)。

这里写图片描述

特点

  • 无序
  • 无重复
  • 支持集合间操作

集合类型的相关命令

sadd、srem

  • sadd key element:向聚合key添加element(如果element已经存在,添加失败),时间复杂度O(N),N 是被添加的元素的数量。
# 添加单个元素
redis> sadd bbs "discuz.net"
(integer) 1

# 添加重复元素
redis> sadd bbs "discuz.net"
(integer) 0

# 添加多个元素
redis> sadd bbs "tianya.cn" "groups.google.com"
(integer) 2

redis> smembers bbs
1) "discuz.net"
2) "groups.google.com"
3) "tianya.cn"
  • srem key element:将集合key中的element移除掉,时间复杂度O(N),N 为给定 member 元素的数量。
# 测试数据
redis> smembers languages
1) "c"
2) "lisp"
3) "python"
4) "ruby"

# 移除单个元素
redis> srem languages ruby
(integer) 1

# 移除不存在元素
redis> srem languages non-exists-language
(integer) 0

# 移除多个元素
redis> srem languages lisp python c
(integer) 3

redis> smembers languages
(empty list or set)
scard、sismember、srandmember、smembers、spop
  • scard key:返回集合 key 的基数(集合中元素的数量),时间复杂度O(1)。
redis> sadd tool pc printer phone
(integer) 3

redis> scard tool   # 非空集合
(integer) 3

redis> del tool
(integer) 1

redis> scard tool   # 空集合
(integer) 0
  • sismember key member:判断 member 元素是否集合 key 的成员,时间复杂度O(1)。
redis> smembers joe's_movies
1) "hi, lady"
2) "Fast Five"
3) "2012"

# member 元素不是集合的成员,或 key 不存在,返回 0。
redis> sismember joe's_movies "bet man"
(integer) 0

# member 元素是集合的成员,返回 1。
redis> sismember joe's_movies "Fast Five"
(integer) 1
  • srandmember key [count]:只提供了 key 参数,那么返回集合中的一个随机元素。时间复杂度只提供 key 参数时为 O(1) 。如果提供了 count 参数,那么为 O(N) , N 为返回数组的元素个数。
# 添加元素
redis> sadd fruit apple banana cherry
(integer) 3

# 只给定 key 参数,返回一个随机元素
redis> srandmember fruit
"cherry"

redis> srandmember fruit
"apple"

# 给定 3 为 count 参数,返回 3 个随机元素
# 每个随机元素都不相同
redis> srandmember fruit 3
1) "apple"
2) "banana"
3) "cherry"

# 给定 -3 为 count 参数,返回 3 个随机元素
# 元素可能会重复出现多次
redis> srandmember fruit -3
1) "banana"
2) "cherry"
3) "apple"

redis> srandmember fruit -3
1) "apple"
2) "apple"
3) "cherry"

# 如果 count 是整数,且大于等于集合基数,那么返回整个集合
redis> srandmember fruit 10
1) "apple"
2) "banana"
3) "cherry"

# 如果 count 是负数,且 count 的绝对值大于集合的基数
# 那么返回的数组的长度为 count 的绝对值
redis> srandmember fruit -10
1) "banana"
2) "apple"
3) "banana"
4) "cherry"
5) "apple"
6) "apple"
7) "cherry"
8) "apple"
9) "apple"
10) "banana"

# srandmember 并不会修改集合内容
redis> smembers fruit
1) "apple"
2) "cherry"
3) "banana"

# 集合为空时返回 nil 或者空数组
redis> srandmember not-exists
(nil)

redis> srandmember not-eixsts 10
(empty list or set)
  • smembers key:返回集合 key 中的所有成员(无序,返回所有数据—单线程、要小心使用),不存在的 key 被视为空集合。时间复杂度O(N),N 为集合的基数。
# key 不存在或集合为空
redis> exists not_exists_key
(integer) 0

redis> smembers not_exists_key
(empty list or set)

# 非空集合
redis> sadd language Ruby Python Clojure
(integer) 3

redis> smembers language
1) "Python"
2) "Ruby"
3) "Clojure"
  • spop key:移除并返回集合中的一个随机元素。如果只想获取一个随机元素,但不想该元素从集合中被移除的话,可以使用 srandmembers 命令。时间复杂度O(1)。
redis> smembers db
1) "MySQL"
2) "MongoDB"
3) "Redis"

redis> spop db
"Redis"

#当 key 不存在或 key 是空集时,返回 nil 。
redis> spop not_exists_key
(nil)

redis> smembers db
1) "MySQL"
2) "MongoDB"

redis> spop db
"MySQL"

redis> smembers db
1) "MongoDB"
srandmember和spop的区别
  • spop从集合弹出,每次只能弹出一个。
  • srandmember不会破坏集合。

实战

  • 给用户添加标签、给标签添加用户
    这里写图片描述

集合间APi

这里写图片描述

  • sinter user:1:follow user:2:follow = it sports:交集
  • sdiff user:1:follow user:2:follow = music his:差集
  • sunion user:1:follow user:2:follow = it music sports new ent:并集
  • sdiff | sinter | sunion + destkey …:将差集、交集、并集结果保存在destkey中。

TIPS

  • sadd = tagging(标签相关场景)。
  • spop / srandmember = random item(数据数的相关场景)。
  • sadd + sinter = social graph(社交相关场景)。

猜你喜欢

转载自blog.csdn.net/zx711166/article/details/82744461