一、集合(Set)
概述:
(1)Set是没有排序的字符集合,和list一样。可添加,删除,或判断元素是否存在的操作。
(2)和list类型不同,不允许出现重复的元素。和c++的set容器是完全相同。set类型功能上存在服务器端完成聚合计算。效率很高,节省网络的开销。
(3)最大允许元素4294967295,每个集合可存储40多亿个成员。
(4)set集合支持查找集合中的差集、交集、并集。
(5)通过hash table来实现新增、删除、查找的。
1.1 SADD(sadd)
向集合添加一个或多个成员
Redis Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
假如集合 key 不存在,则创建一个只包含添加的元素作成员的集合。
当集合 key 不是集合类型时,返回一个错误。
**注意:**在Redis2.4版本以前, SADD 只接受单个成员值。
语法
127.0.0.1:6379> SADD KEY_NAME VALUE1..VALUEN
可以版本:
>= 1.0.0
返回值:
被添加到集合中的新元素的数量,不包括被忽略的元素。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset j3_liuliang #向set集合中添加元素 (integer) 1 127.0.0.1:6379> sadd myset xiaowang xiangli #一次性添加多个 (integer) 2 127.0.0.1:6379> smembers myset #获取set中所有值 1) "xiangli" 2) "xiaowang" 3) "j3_liuliang" 127.0.0.1:6379> sadd myset j3_liuliang #向set集合中添加存在的值 (integer) 0 #被忽略,没有任何变化 127.0.0.1:6379> smembers myset 1) "xiangli" 2) "xiaowang" 3) "j3_liuliang" 127.0.0.1:6379>
1.2 SMEMBERS(smembers)
返回集合中的所有成员
Redis Smembers 命令返回集合中的所有的成员。 不存在的集合 key 被视为空集合。
语法
127.0.0.1:6379> SMEMBERS KEY VALUE
可以版本:
>= 1.0.0
返回值:
集合中的所有成员。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset j3_liuliang #向set集合中添加元素 (integer) 1 127.0.0.1:6379> sadd myset xiaowang xiangli #一次性添加多个 (integer) 2 127.0.0.1:6379> smembers myset #获取set中所有值 1) "xiangli" 2) "xiaowang" 3) "j3_liuliang" 127.0.0.1:6379> sadd myset j3_liuliang #向set集合中添加存在的值 (integer) 0 #被忽略,没有任何变化 127.0.0.1:6379> smembers myset 1) "xiangli" 2) "xiaowang" 3) "j3_liuliang" 127.0.0.1:6379>
1.3 SPOP(spop)
移除并返回集合中的一个随机元素
Redis Spop 命令用于移除并返回集合中的一个随机元素。
语法
127.0.0.1:6379> SPOP KEY [count]
count 参数在 3.2+ 版本可用。
可以版本:
>= 1.0.0
返回值:
被移除的随机元素。 当集合不存在或是空集时,返回 nil 。
案例
127.0.0.1:6379> smembers myset #遍历set中的所有元素 1) "xiangli" 2) "xiaowang" 3) "j3_liuliang" 127.0.0.1:6379> spop myset #随机从set集合中移除一个元素 "j3_liuliang" 127.0.0.1:6379> sadd myset wangzhi #向set中添加元素 (integer) 1 127.0.0.1:6379> spop myset 2 #随机向set集合中移除两个元素 2 :代表要随机移除的元素个数 1) "xiangli" 2) "wangzhi" 127.0.0.1:6379> exists names #判断key是否存在 (integer) 0 127.0.0.1:6379> spop names #随机移除不存在set中的元素,返回nil (nil) 127.0.0.1:6379>
1.4 SCARD(scard)
获取集合的成员数
Redis Scard 命令返回集合中元素的数量。
语法
127.0.0.1:6379> SCARD KEY_NAME
可以版本:
>= 1.0.0
返回值:
集合的数量。 当集合 key 不存在时,返回 0 。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd bookname hongloumeng xiyouji shuihuzhuan #向set集合中添加多个值 (integer) 3 127.0.0.1:6379> scard bookname #获取set集合中的元素个数 (integer) 3 127.0.0.1:6379> exists notexistskey #判断key是否存在 (integer) 0 127.0.0.1:6379> scard notexistskey #获取不存在set类型的key的元素个数 (integer) 0 127.0.0.1:6379>
1.5 SRANDMEMBER(srandmember)
返回集合中一个或多个随机
Redis Srandmember 命令用于返回集合中的一个随机元素。
从 Redis 2.6 版本开始, Srandmember 命令接受可选的 count 参数:
如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
该操作和 SPOP 相似,但 SPOP 将随机元素从集合中移除并返回,而 Srandmember 则仅仅返回随机元素,而不对集合进行任何改动。
语法
SRANDMEMBER KEY [count]
可以版本:
>= 1.0.0
返回值:
只提供集合 key 参数时,返回一个元素;如果集合为空,返回 nil 。 如果提供了 count 参数,那么返回一个数组;如果集合为空,返回空数组。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset j3_liuliang xiaozhi yuanyuan #向set集合中添加多个元素 (integer) 3 127.0.0.1:6379> smembers myset #查看set集合元素 1) "yuanyuan" 2) "j3_liuliang" 3) "xiaozhi" 127.0.0.1:6379> srandmember myset #随机取出一个元素,但原set集合数据不变 "xiaozhi" 127.0.0.1:6379> srandmember myset 2 #随机取出两个元素,但原set集合数据不变 1) "j3_liuliang" 2) "yuanyuan" 127.0.0.1:6379> srandmember myset -2 #随机取出两个元素并且有可能元素重复,但原set集合数据不变 1) "xiaozhi" 2) "yuanyuan" 127.0.0.1:6379> smembers myset #查看set集合元素,没有变化 1) "yuanyuan" 2) "j3_liuliang" 3) "xiaozhi" 127.0.0.1:6379>
1.6 SREM(srem)
移除集合中一个或多个成员
Redis Srem 命令用于移除集合中的一个或多个成员元素,不存在的成员元素会被忽略。
当 key 不是集合类型,返回一个错误。
在 Redis 2.4 版本以前, SREM 只接受单个成员值。
语法
127.0.0.1:6379> SREM KEY MEMBER1..MEMBERN
可以版本:
>= 1.0.0
返回值:
被成功移除的元素的数量,不包括被忽略的元素。
案例
127.0.0.1:6379> smembers myset #查看set集合元素 1) "yuanyuan" 2) "j3_liuliang" 3) "xiaozhi" 127.0.0.1:6379> srem myset yuanyuan j3_liuliang #从set集合中移除多个指定的值 (integer) 2 127.0.0.1:6379> srem myset 12423948 #对不存在的值进行忽略 (integer) 0 127.0.0.1:6379> smembers myset #查看set集合元素 1) "xiaozhi" 127.0.0.1:6379>
1.7 SMOVE(smove)
将 member 元素从 source 集合移动到 destination 集合
Redis Smove 命令将指定成员 member 元素从 source 集合移动到 destination 集合。
SMOVE 是原子性操作。
如果 source 集合不存在或不包含指定的 member 元素,则 SMOVE 命令不执行任何操作,仅返回 0 。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。
当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。
当 source 或 destination 不是集合类型时,返回一个错误。
语法
127.0.0.1:6379> SMOVE SOURCE DESTINATION MEMBER
可以版本:
>= 1.0.0
返回值:
如果成员元素被成功移除,返回 1 。 如果成员元素不是 source 集合的成员,并且没有任何操作对 destination 集合执行,那么返回 0 。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd names j3_liuliang xiaowang xiaoli #设置set集合names (integer) 3 127.0.0.1:6379> sadd ordy myordy01 myordy02 xiaoli #设置set集合ordy (integer) 3 127.0.0.1:6379> smove ordy names xiaoli #将ordy中的xiaoli 移动到 names(存在xiaoli)中 (integer) 1 127.0.0.1:6379> smembers ordy #查看set集合元素 1) "myordy01" 2) "myordy02" 127.0.0.1:6379> smembers names #查看set集合元素 1) "xiaowang" 2) "j3_liuliang" 3) "xiaoli" 127.0.0.1:6379> smove ordy names myordy02 #将ordy中的 myordy02 移动到 names(不存在myordy02)中 (integer) 1 127.0.0.1:6379> smembers ordy #查看set集合元素 1) "myordy01" 127.0.0.1:6379> smembers names #查看set集合元素 1) "xiaowang" 2) "j3_liuliang" 3) "myordy02" 4) "xiaoli" 127.0.0.1:6379> smove ordy names myordy0222 #将ordy中不存在的 myordy0222 移动到 names(不存在myordy0222)中 (integer) 0 #无变化 127.0.0.1:6379> smembers ordy #查看set集合元素 1) "myordy01" 127.0.0.1:6379> smembers names 1) "xiaowang" 2) "j3_liuliang" 3) "myordy02" 4) "xiaoli" 127.0.0.1:6379>
1.8 SISMEMBER(sismember)
判断 member 元素是否是集合 key 的成员
Redis Sismember 命令判断成员元素是否是集合的成员。
语法
127.0.0.1:6379> SISMEMBER KEY VALUE
可以版本:
>= 1.0.0
返回值:
如果成员元素是集合的成员,返回 1 。 如果成员元素不是集合的成员,或 key 不存在,返回 0 。
案例
127.0.0.1:6379> smembers names #查看set集合元素 1) "xiaowang" 2) "j3_liuliang" 3) "myordy02" 4) "xiaoli" 127.0.0.1:6379> sismember names j3_liuliang #判断元素是否存在 (integer) 1 127.0.0.1:6379> sismember names 000000 # (integer) 0 127.0.0.1:6379>
1.9 SSCAN(sscan)
迭代集合中的元素
Redis Sscan 命令用于迭代集合键中的元素。
语法
127.0.0.1:6379> SSCAN key cursor [MATCH pattern] [COUNT count]
- cursor - 游标。
- pattern - 匹配的模式。
- count - 指定从数据集里返回多少元素,默认值为 10 。
可以版本:
>= 2.8.0
返回值:
数组列表。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset j3_liuliang xiaohonng huahua tangsheng swk zbj ss #设置数据 (integer) 7 127.0.0.1:6379> sscan myset 0 #迭代set数据集合,游标返回 0 说明迭代完毕 1) "0" 2) 1) "huahua" 2) "tangsheng" 3) "zbj" 4) "ss" 5) "j3_liuliang" 6) "xiaohonng" 7) "swk" 127.0.0.1:6379> sscan myset 0 match *g* #指定规则匹配迭代出符合规则的数据 1) "0" 2) 1) "tangsheng" 2) "j3_liuliang" 3) "xiaohonng" 127.0.0.1:6379>
如果对sscan命令不是很理解,看我得另一篇:SCAN及相关SSCAN,HSCAN和ZSCAN命令解析
1.10 SUNION(sunion)
返回所有给定集合的并集
Redis Sunion 命令返回给定集合的并集。不存在的集合 key 被视为空集。
语法
127.0.0.1:6379> SUNION KEY KEY1..KEYN
可以版本:
>= 1.0.0
返回值:
并集成员的列表。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset01 hello world you #创建set集合 (integer) 3 127.0.0.1:6379> sadd myset02 hello my his (integer) 3 127.0.0.1:6379> sunion myset01 myset02 #获取两个集合的并集元素 1) "hello" 2) "you" 3) "world" 4) "my" 5) "his" 127.0.0.1:6379>
1.11 SINTER(sinter)
返回给定所有集合的交集
Redis Sinter 命令返回给定所有给定集合的交集。 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。
语法
127.0.0.1:6379> SINTER KEY KEY1..KEYN
可以版本:
>= 1.0.0
返回值:
交集成员的列表。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset01 hello world you #创建两个set集合 (integer) 3 127.0.0.1:6379> sadd myset02 hello my his (integer) 3 127.0.0.1:6379> sinter myset01 myset02 #获取两个set集合的交集 1) "hello" 127.0.0.1:6379>
1.12 SDIFF(sdiff)
返回给定所有集合的差集
Redis Sdiff 命令返回给定集合之间的差集。不存在的集合 key 将视为空集。
语法
127.0.0.1:6379> SDIFF FIRST_KEY OTHER_KEY1..OTHER_KEYN
可以版本:
>= 1.0.0
返回值:
包含差集成员的列表。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset01 hello world you #设置两个set集合 (integer) 3 127.0.0.1:6379> sadd myset02 hello my his (integer) 3 127.0.0.1:6379> sdiff myset01 myset02 #用myset01集合去差myset02中的集合,返回myset01中不存在其他集合中的元素(差集) 1) "world" 2) "you" 127.0.0.1:6379>
1.13 SUNIONSTORE(sunionstore)
所有给定集合的并集存储在 destination 集合中
Redis Sunionstore 命令将给定集合的并集存储在指定的集合 destination 中。
语法
127.0.0.1:6379> SUNIONSTORE DESTINATION KEY KEY1..KEYN
可以版本:
>= 1.0.0
返回值:
结果集中的元素数量。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset01 hello world you #设置两个集合 (integer) 3 127.0.0.1:6379> sadd myset02 hello my his (integer) 3 127.0.0.1:6379> sunionstore set01-02sunion myset01 myset02 #将两个集合数据求并集,并存储到set类型的key为set01-02sunion集合中 (integer) 5 127.0.0.1:6379> smembers set01-02sunion #查看该集合数据 1) "hello" 2) "you" 3) "world" 4) "my" 5) "his" 127.0.0.1:6379>
1.14 SINTERSTORE(sinterstore)
返回给定所有集合的交集并存储在 destination 中
Redis Sinterstore 命令将给定集合之间的交集存储在指定的集合中。如果指定的集合已经存在,则将其覆盖。
语法
127.0.0.1:6379> SINTERSTORE DESTINATION_KEY KEY KEY1..KEYN
可以版本:
>= 1.0.0
返回值:
交集成员的列表。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset01 hello world you #设置两个集合 (integer) 3 127.0.0.1:6379> sadd myset02 hello my his (integer) 3 127.0.0.1:6379> sinterstore set01-02inter myset01 myset02 #将两个集合交集的数据存储到set01-02inter的set集合中 (integer) 1 127.0.0.1:6379> smembers set01-02inter #查看set01-02inter的数据 1) "hello" 127.0.0.1:6379>
1.15 SDIFFSTORE(sdiffstore)
返回给定所有集合的差集并存储在 destination 中
Redis Sdiffstore 命令将给定集合之间的差集存储在指定的集合中。如果指定的集合 key 已存在,则会被覆盖。
语法
127.0.0.1:6379> SDIFFSTORE DESTINATION_KEY KEY1..KEYN
可以版本:
>= 1.0.0
返回值:
结果集中的元素数量。
案例
127.0.0.1:6379> flushall OK 127.0.0.1:6379> sadd myset01 hello world you #设置两个集合 (integer) 3 127.0.0.1:6379> sadd myset02 hello my his (integer) 3 127.0.0.1:6379> sdiffstore set01-02diff myset01 myset02 #将集合myset01中的数据与myset02中的数据进行差集,得到的数据放入set01-02diff中存储 (integer) 2 127.0.0.1:6379> smembers set01-02diff #遍历set01-02diff集合数据 1) "world" 2) "you" 127.0.0.1:6379>
二、应用场景
2.1 微信抽奖小程序
相信大家都或多或少的用过这种类似的微信抽奖小程序,反正我我本人时经常用的,但基本没有中过奖,不知道是不是程序和我过不去(肯定是了,我这么帅!)。
其实这种程序实现思路很简单,就是从一个集合中随机抽取若干数据就可以了,至于原本的集合数据要不要改变就要根据具体的业务场景而定了,不过这种微信小程序一般都是一次性的,就是抽过奖后,就不会再对集合有任何操作,只要对原本集合的改变倒是无关紧要,重要的是随机抽取的数据才是抽奖的重点。
下面是一个微信抽奖小程序页面(用Redis实现抽奖,具体如下):
1,点击参与抽奖,加入抽奖集合中
127.0.0.1:6379> sadd choujiang user01
2,查看所有参加抽奖用户
127.0.0.1:6379> smembers choujiang 1) "user04" 2) "user01" 3) "user03" 4) "user05" 5) "user06" 6) "user02" 127.0.0.1:6379>
3,抽取count名用户中奖
127.0.0.1:6379> srandmember choujiang 2 #抽两名用户,用户不踢出抽奖集合 1) "user02" 2) "user06" 127.0.0.1:6379> smembers choujiang 1) "user01" 2) "user03" 3) "user05" 4) "user04" 5) "user06" 6) "user02" 127.0.0.1:6379> spop choujiang 2 #抽两名用户,用户踢出抽奖集合 1) "user03" 2) "user01" 127.0.0.1:6379> smembers choujiang 1) "user05" 2) "user04" 3) "user06" 4) "user02" 127.0.0.1:6379>
2.2 微信微博点赞
点赞功能都用过把!没有的就可以当原始人了
在微信,QQ,微博的动态里都可以对其他用户发出的动态进行点赞(我的博客也是可以点赞的哟!
),并且这类功能的实现方式有很多种,其中set就是一种方式,如下图片和操作:
1,点赞动态
127.0.0.1:6379> sadd dianzan user01 (integer) 1
2,取消点赞
127.0.0.1:6379> srem dianzan user01 (integer) 1 127.0.0.1:6379>
3,检查用户是否点赞
127.0.0.1:6379> sismember dianzan user01 (integer) 0
4,获取用户点赞列表
127.0.0.1:6379> smembers dianzan 1) "user03" 2) "user05" 3) "user04" 4) "user02"
5,获取点赞用户数
127.0.0.1:6379> scard dianzan (integer) 4 127.0.0.1:6379>
2.3 共同关注
大家有没有遇到过这样的场景,就是在关注公众号或者用户的时候都会时不时的弹出一个小提示说你关注的人也关注某某某等信息。
其实这就是一种集合的交集体现,两个人共同关注了某个用户
比如,我的博客里关注了阿里达摩院这个博主,现在我关注了Java3y博主而他也关注了阿里达摩院博主那么就会有提示说,你们共同关注阿里达摩院这个博主的提示。
可能不好理解,我们图文并茂来看看:
1,查看我关注的人
127.0.0.1:6379> smembers j3_liuliang 1) "alidamoyuan" 127.0.0.1:6379>
2,查看Java3y关注的人
127.0.0.1:6379> smembers java3y 1) "alidamoyuan" 127.0.0.1:6379>
3,我关注Java3y
127.0.0.1:6379> sadd j3_liuliang java3y (integer) 1 127.0.0.1:6379>
4,我和Java3y共同关注的人
127.0.0.1:6379> sinterstore j3_liuliang-java3y j3_liuliang java3y #将两个集合的交集存入到一个集合中 (integer) 1 127.0.0.1:6379> smembers j3_liuliang-java3y #遍历结合,这就是两个集合中共同关注的博主 1) "alidamoyuan" 127.0.0.1:6379>
2.4 可能认识的人
从字面上理解,也是很好理解而且如果你QQ添加过好有的话,那它是不是在你添加好友成功之后,会提示我们还可能认识某某某
这个共功能其实也是很好实现的(简单版,简单版,我相信QQ的可能认识的人不会做的如此简单,不然我是不是也可以去入职了呢!),我们可以简单的把我么们的好友列表想象成一个集合,当我们添加一个好有成功之后,是不是就说们我们两个很大一部分时认识的,那我加的那位好友列表里是不是也有可能有我认识的人呢!说不定就有哟~,接着系统内部会将我们两个的好友列表集合进行一次差集得出来的结果就是我可能认识得人。
记住,是新好有得好友列表集合与我得好友列表集合得差集
1,我的好友列表
127.0.0.1:6379> smembers j3_liuliang #我的好友列表 1) "A2" 2) "A1" 3) "A3"
2,妹子得好友列表
127.0.0.1:6379> smembers meizi #妹子的好友列表 1) "meizi03" 2) "meizi02" 3) "meizi01" 127.0.0.1:6379>
3,添加妹子好友
127.0.0.1:6379> sadd j3_liulinag meizi #添加被子到我的好有列表 (integer) 1
4,列表做差集先是可能认识得妹子
127.0.0.1:6379> sdiff meizi j3_liuliang #显示可能认识得人给我,让我多加几个妹子,嘻嘻! 1) "meizi03" 2) "meizi01" 3) "meizi02" 127.0.0.1:6379>
结束语
- 本文结合Redis中文网和博主的实践案例所写,下期写Sorted Set类型
- 由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。
- 如果你觉得文章还不错,你的转发、分享、点赞、留言就是对我最大的鼓励。
- 感谢您的阅读,十分欢迎并感谢您的关注。