深入Redis之数据类型 — Set

不积跬步无以至千里,这一篇set继续走起,set底层原理也是并不复杂,还是先来基本操作,再来原理解析。

 

目录

一、概述及基本操作

二、存储原理

三、应用场景


一、概述及基本操作

set存储String类型的无序集合,最大存储数量(2^32) - 1 个元素(40亿左右)元素不可以重复。

操作命令:

1、Sadd:将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。

假如集合 key 不存在,则创建一个只包含添加的元素作成员的集合。当集合 key 不是集合类型时,返回一个错误。

a、语法:SADD KEY_NAME VALUE1..VALUEN

b、返回值:被添加到集合中的新元素的数量,不包括被忽略的元素。

c、实例解释:127.0.0.1:6379> SADD  set1  "a"

运行上面命令,会将a添加到keyname = set1 的集合中,返回1,可以理解为,添加成功就返回1,添加失败就返回0。

2、Scard:返回集合中元素的数量。

a、语法:SCARD KEY_NAME

b、返回值:集合中元素的数量, 当集合 key 不存在时,返回 0 。

c、实例解释:127.0.0.1:6379> SCARD set1

运行上面命令,将返回set1集合中元素的个数。

3、Sdiff:返回给定集合之间的差集。不存在的集合 key 将视为空集。

差集的结果来自前面的 FIRST_KEY ,而不是后面的 OTHER_KEY1,也不是整个 FIRST_KEY OTHER_KEY1..OTHER_KEYN 的差集。

a、语法:SDIFF FIRST_KEY OTHER_KEY1..OTHER_KEYN

b、返回值:第一个集合中不存在于后面其他集合中的元素组成的列表。

c、实例解释:有集合 k1 = {a,b,c}   、 k2 = {b,c,d,e}

则:127.0.0.1:6379> SDIFF k1 k2

运行上面命令,将返回一个k1相对于k2不同的元素组成的集合,k1中只有"a"不在k2集合中,所以返回集合{a}。

4、Sdiffstore:将给定集合之间的差集存储在指定的集合中。如果指定的集合 key 已存在,则会被覆盖。

a、语法:SDIFFSTORE  DESTINATION_KEY  KEY1...KEYN

b、返回值:结果集中的元素数量。

c、实例解释:有集合 k1 = {a,b,c}   、 k2 = {b,c,d,e}

则:127.0.0.1:6379> SDIFFSTORE   k3   k1  k2

运行上面命令,此时将会把k1相对于k2不同的元素存储在k3中,如果之前k3已经存在,则会覆盖k3的内容,此时k3 = {a},并返回k3的元素个数1。

5、Sinter:返回给定所有给定集合的交集。 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。

a、语法:SINTER KEY KEY1..KEYN

b、返回值:交集成员的列表。

c、实例解释:有集合 k1 = {a,b,c}   、 k2 = {b,c,d,e}

则:127.0.0.1:6379> SINTER k1 k2

运行上面命令,将返回k1、k2的交集,即返回:{b,c}

6、Sinterstore:将给定集合之间的交集存储在指定的集合中。如果指定的集合已经存在,则将其覆盖。

a、语法:SINTERSTORE DESTINATION_KEY KEY KEY1..KEYN

b、返回值:返回存储交集的集合的元素数量。

c、实例解释:127.0.0.1:6379> SINTERSTORE k3 k1 k2

运行上面命令,将k1、k2的交集元素存储在k3中,并返回k3集合的元素个数。

7、Sismember:判断成员元素是否是集合的成员。

a、语法:SISMEMBER KEY VALUE

b、返回值:如果成员元素是集合的成员,返回 1 。 如果成员元素不是集合的成员,或 key 不存在,返回 0 。

c、实例解释:127.0.0.1:6379> SISMEMBER k1 "a"

运行上面命令,判定a是否在k1集合中,在集合中返回1,不在集合中返回0。

8、Smembers:返回集合中的所有的成员。 不存在的集合 key 被视为空集合。

a、语法:SMEMBERS key

b、返回值:集合中的所有成员。

c、实例解释:127.0.0.1:6379> SMEMBERS  k1

运行上面命令,返回k1中的所有元素。

9、Smove:将指定成员 member 元素从 source 集合移动到 destination 集合。

SMOVE 是原子性操作。

如果 source 集合不存在或不包含指定的 member 元素,则 SMOVE 命令不执行任何操作,仅返回 0 。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。

当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。

当 source 或 destination 不是集合类型时,返回一个错误。

a、语法:SMOVE  SOURCE  DESTINATION  MEMBER

b、返回值:如果成员元素被成功移除,返回 1 。 如果成员元素不是 source 集合的成员,并且没有任何操作对 destination 集合执行,那么返回 0 。

c、实例解释:127.0.0.1:6379> SMOVE k1 k2 "a"

运行上面命令,将元素a从k1中移动到k2中,即将a元素从k1集合中删除,并在k2集合中添加a元素。

10、Spop:用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。

a、语法:SPOP key [count],其中 count 参数(要移除的个数)在 3.2+ 版本可用。

b、返回值:集合中元素的数量, 当集合 key 不存在时,返回 0 。

c、实例解释:

127.0.0.1:6379> SPOP k1 

127.0.0.1:6379> SPOP k1  2

运行上面2条命令,第一条命令将会从k1中随机移除一个元素,并返回该元素。第二条命令将会从k1中随机移除2个元素,并返回这两个元素。

11、Srandmember:用于返回集合中的一个随机元素。

从 Redis 2.6 版本开始, Srandmember 命令接受可选的 count 参数:

  • 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
  • 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

该操作和 SPOP 相似,但 SPOP 将随机元素从集合中移除并返回,而 Srandmember 则仅仅返回随机元素,而不对集合进行任何改动。

a、语法:SRANDMEMBER KEY [count]

b、返回值:只提供集合 key 参数时,返回一个元素;如果集合为空,返回 nil 。 如果提供了 count 参数,那么返回一个数组;如果集合为空,返回空数组。

c、实例解释:

127.0.0.1:6379> SRANDMEMBER k1

127.0.0.1:6379> SRANDMEMBER k1 2

运行上面2条命令,第一条命令将会从k1中随机获取一个元素,并返回该元素。第二条命令将会从k1中随机获取2个元素,并返回这两个元素组成的集合。命令均不会对k1集合本身产生影响。

12、Srem:用于移除集合中的一个或多个成员元素,不存在的成员元素会被忽略。

当 key 不是集合类型,返回一个错误。在 Redis 2.4 版本以前, SREM 只接受单个成员值。

a、语法: SREM KEY MEMBER1..MEMBERN

b、返回值:被成功移除的元素的数量,不包括被忽略的元素。

c、实例解释:127.0.0.1:6379> SREM k1 a b

运行上面命令,会将a,b元素从k1中删除掉,并返回删掉元素的数量。

13、Sunion:返回给定集合的并集。不存在的集合 key 被视为空集。

a、语法:SUNION KEY KEY1..KEYN

b、返回值:并集成员的列表。

c、实例解释:有集合 k1 = {a,b}   、 k2 = {b,c,d}

则:127.0.0.1:6379> SUNION  k1 k2

运行上面命令,将返回k1、k2的并集{a,b,c,d}。

14、Sunionstore:将给定集合的并集存储在指定的集合 destination 中。如果 destination 已经存在,则将其覆盖。

a、语法:SUNIONSTORE DESTINATION KEY KEY1..KEYN

b、返回值:结果集中的元素数量。

c、实例解释:127.0.0.1:6379> SUNIONSTORE k3 k1 k2

运行上面命令,将k1、k2的交集存储在k3中,并返回k3的元素数量。

15、Sscan:用于迭代集合中键的元素。

a、语法:SSCAN key cursor [MATCH pattern] [COUNT count]

b、返回值:数组列表。

c、实例解释:sscan 命令以及其相关命令一两句话不是很容易将明白,详细了解可以查看:https://www.cnblogs.com/meowyeon/p/8627779.html

二、存储原理

1、Redis用intset或hashtable存储set。如果元素都是整数类型,就用inset存储。如果不是整数类型,就用hashtable(数组+链表的存来储结构)。

对于redis这种存储KV数据形式的而言,它是怎么存储set的元素的呢?set在存储元素时,key就是元素的值,value为null。

另外对于intset和hashtable存在编码转换,使用intset存储必须满足下面两个条件,否则使用hashtable,条件如下:

a、集合保存的所有元素都是整数值

b、集合保存的元素数量不超过512个

2、intset数据结构

intset内部是一个数组(int8_t coentents[]数组),而且存储数据的时候是有序的,因为在查找数据的时候是通过二分查找来实现的。

typedef struct intset {
    
    // 编码方式
    uint32_t encoding;
 
    // 集合包含的元素数量
    uint32_t length;
 
    // 保存元素的数组
    int8_t contents[];
 
} intset;

三、应用场景

1、抽奖:利用 spop 命令可以实现抽奖功能。

2、点赞、签到、打卡功能:

例如,微博的ID是t1001,用户ID是u3001。用like:t1001来维护t1001这条微博的所有点赞用户。

点赞了这条微博:sadd like:t1001 u3001

取消点赞:srem like:t1001 u3001

是否点赞:sismember like:t1001 u3001

点赞的所有用户:smembers like:t1001

点赞数:scard like:t1001

3、还有其他功能,例如相互关注、商品筛选、商品标签等都可以利用set来完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值