前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis:11---Set对象

Redis:11---Set对象

作者头像
用户3479834
发布2021-02-03 14:23:50
1K0
发布2021-02-03 14:23:50
举报
文章被收录于专栏:游戏开发司机

集合类型 (Set) 是一个无序并唯一的键值集合。它的存储顺序不会按照插入的先后顺序进行存储。

集合类型和列表类型的区别如下:

  • 列表可以存储重复元素,集合只能存储非重复元素;
  • 列表是按照元素的先后顺序存储元素的,而集合则是无序方式存储元素的。

一、集合对象概述

  • 特点:
    • 集合通过散列表来保证自己存储的元素不能重复
    • 列表中的元素是根据插入、删除元素时来对数据进行排序,但是集合中的元素在插入或删除时是无序的,所以集合中的元素是无序排列的
    • 和列表一样都可以存储多个字符串
    • 与列表的不同:
  • 一个集合最多可以存储 2<<32 -1个元素
  • Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并 集、差集,合理地使用好集合类型,能在实际开发中解决很多实际问题

二、命令

常用命令

  • sadd:添加元素。返回结果为添加成功的元素个数
代码语言:javascript
复制
sadd key element [element ...]

smembers:获取所有元素,返回的结果是无序的。smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用sscan来完成.

sscan:sscan 命令用于迭代集合中键的元素

redis Sscan 命令基本语法如下:

代码语言:javascript
复制
SSCAN key cursor [MATCH pattern] [COUNT count]

cursor - 游标。

pattern - 匹配的模式。

count - 指定从数据集里返回多少元素,默认值为 10 。

可用版本

>= 2.8.0

返回值

数组列表。

代码语言:javascript
复制
> SADD myset1 "Google"
(integer) 1
> SADD myset1 "Runoob"
(integer) 1
> SADD myset1 "Taobao"
(integer) 1
> SSCAN myset1 0 match R*
1) "0"
2) 1) "Runoob"

代码语言:javascript
复制
smembers key
  • sismember:判断元素是否在集合中。如果给定元素element在集合内返回1,反之返回0
代码语言:javascript
复制
sismember key element
  • srem:删除元素。返回结果为成功删除元素个数
代码语言:javascript
复制
srem key element [element ...]
  • scard:计算集合中元素个数。scard的时间复杂度为O(1),它不会遍历集合所有元素,而是直接用 Redis内部的变量
  • srandmember:随机从集合返回指定个数元素,只返回元素不删除元素。[count]是可选参数,如果不写默认为1
代码语言:javascript
复制
srandmember key [count]
  • spop:从集合随机弹出元素,弹出的元素会被删除。需要注意的是Redis从3.2版本开始,spop也支持[count]参数
代码语言:javascript
复制
spop key [count]

其他命令

  • 现在有两个集合,它们分别是user:1:follow和user:2:follow
  • sinter:求多个集合的交集
代码语言:javascript
复制
sinter key [key ...]
  • sunion:求多个集合的并集
代码语言:javascript
复制
sunion key [key ...]
  • sdiff:求多个集合的差集
代码语言:javascript
复制
sdiff key [key ...]
  • 上面的3个元素演示如下:
  • sinterstore、suionstore、sdiffstore:将交集、并集、差集的结果保存。集合间的运算在元素较多的情况下会比较耗时,所以Redis提供了这三个个命令(原命令+store)将集合间交集、并集、差集的结果保存在destination key中
代码语言:javascript
复制
sinterstore destination key [key ...]suionstore destination key [key ...]sdiffstore destination key [key ...]
  • 例如下面操作将user:1:follow和user:2:follow两个集 合的交集结果保存在user:1_2:inter中,user:1_2:inter本身也是集合类 型:
  • 集合对象命令的复杂度如下:

命 令

时间复杂度

saddkeyelement[element...]

0(k),k是元素个数

sremkeyelement[element...]

0(k),k是元素个数

scardkey

0(1)

sismemberkeyelement

O(1)

srandmemberkey[count]

O(count)

spopkey

0(1)

smemberskey

0(m),n是元素总数

sinterkey[key...]或者sinterstore

O(m*k),k是多个集合中元素最少的个数,m是键个数

suinonkey[key...]或者suionstore

0(k),k是多个集合元素个数和

sdiffkey[key...]或者sdiffstore

0(k),k是多个集合元素个敷和g.csdn.netqq_.41453285

三、内部编码

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

演示说明

  • 当元素个数较少且都为整数时,内部编码为intset:
  • 当元素个数超过512个,内部编码变为hashtable
  • 当某个元素不为整数时,内部编码也会变为hashtable:

四、使用场景

唯一计数器

  • 举个例子,一个网站的受欢迎程度通常可以用浏览量和用户数量这两个指标进行描述:
    • 浏览量记录的是网站页面被用户访问的总次数,网站的每个用户都可以重复地对同一个页面进行 多次访问,而这些访问会被浏览量计数器一个不漏地记下来
    • 用户数量记录的是访问网站的 IP 地址数量,即使同一个 IP 地址多次访问相同的页面,用户数量 计数器也只会对这个 IP 地址进行一次计数
  • 网站浏览量可以使用字符串键是的计数器进行计数,但想要记录网站的用户数量,就需要构建一个 新的计数器,可以用 SET 集合
    • 加入 IP:SADD users:count 202.177.2.232
    • 计算总数:SCARD users:count

朋友圈点赞

  • ①点赞
代码语言:javascript
复制
sadd like:{消息 Id} {点赞用户 Id}
  • ②取消点赞
代码语言:javascript
复制
srem like:{消息 Id} {点赞用户 Id}
  • ③检查用户是否点过赞
代码语言:javascript
复制
sismember like:{消息 Id} {点赞用户 Id}
  • ④获取点赞用户列表
代码语言:javascript
复制
smembers like:{消息 Id}
  • ⑤获取点赞用户数量
代码语言:javascript
复制
scard like:{消息 Id}

共同关注和推荐关注

  • ①darren 老师关注的人
代码语言:javascript
复制
sadd darrenSet qiuxiang lee king
  • ②qiuxiang 老师关注的人
代码语言:javascript
复制
sadd qiuxiangSet darren ting lee king
  • ③king 老师关注的人
代码语言:javascript
复制
sadd kingSet qiuxiang darren ting buding
  • ④我和 qiuxiang 老师共同关注(交集)
代码语言:javascript
复制
sinter darrenSet qiuxiangSet - {lee,king}
  • ⑤我关注的人是否也关注他(king 老师)
代码语言:javascript
复制
sismember qiuxiangSet king
  • ⑥我可能认识的人(钉钉 脉脉)
代码语言:javascript
复制
sdiff qiuxiangSet darrenSet - {darren, ting}

投票

  • 问答网站、文章推荐网站、论坛这类注重内容质量的网站上通常都会提供投票功能,用户可以通过投票来支持一项内容或者反对一项内容:
    • 一项内容获得的支持票数越多,就会被网站安排到越明显的位置,使得网站的用户可以更快速地 浏览到高质量的内容
    • 与此相反,一项内容获得的反对票数越多,它就会被网站安排到越不明显的位置,甚至被当作广 告或者无用内容隐藏起来,使得用户可以忽略这些低质量的内容
  • 赞同的时候将用户SADD到赞同集合,并将用户从反对集合删除 SREM

标签

集合类型比较典型的使用场景是标签(tag)。例如一个用户可能对娱 乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共 同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。例如一 个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产 品,通常会为网站带来更多的利益。

下面使用集合类型实现标签功能的若干功能

  • 给用户添加标签。 Copy sadd user:1:tags tag1 tag2 tag5 sadd user:2:tags tag2 tag3 tag5 ... sadd user:k:tags tag1 tag2 tag4 ...
  • 使用sinter命令,可以来计算用户共同感兴趣的标签 Copy sinter user:1:tags user:2:tags

开发提示:用户和标签的关系维护应该在一个事务内执行,防止部分命令失败造成的数据不一致

③删除用户下的标签

代码语言:javascript
复制
srem user:1:tags tag1 tag5...
  • ④删除标签下的用户
代码语言:javascript
复制
srem tag1:users user:1srem tag5:users user:1...
  • ③和④也是尽量放在一个事务执行
  • ⑤计算用户共同感兴趣的标签。可以使用sinter命令,来计算用户共同感兴趣的标签,如下代码所示:
代码语言:javascript
复制
sinter user:1:tags user:2:tags
  • 开发提示:前面只是给出了使用Redis集合类型实现标签的基本思路,实际上一个标签系统远比这个要复杂得多,不过集合类型的应用场景通常为以下几种:
    • sadd=Tagging(标签)
    • spop/srandmember=Random item(生成随机数,比如抽奖)
    • sadd+sinter=Social Graph(社交需求)

这种标签系统在电商系统、社交系统、视频网站,图书网站,旅游网站等都有着广泛的应用。例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。例如一个社交系统可以根据用户的标签进行好友的推荐,已经用户感兴趣的新闻的推荐等,一个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产品,通常会为网站带来更多的利益。

抽奖系统

Redis集合的 SPOP(随机移除并返回集合中一个或多个元素) 和 SRANDMEMBER(随机返回集合中一个或多个元素) 命令可以帮助我们实现一个抽奖系统

如果允许重复中奖,可以使用SRANDMEMBER 命令

代码语言:javascript
复制
Copy
//添加抽奖名单
127.0.0.1:6379> SADD lucky:1 Tom
(integer) 1
127.0.0.1:6379> SADD lucky:1 Jerry
(integer) 1
127.0.0.1:6379> SADD lucky:1 John
(integer) 1
127.0.0.1:6379> SADD lucky:1 Marry
(integer) 1
127.0.0.1:6379> SADD lucky:1 Sean
(integer) 1
127.0.0.1:6379> SADD lucky:1 Lindy
(integer) 1
127.0.0.1:6379> SADD lucky:1 Echo
(integer) 1

//抽取三等奖3个
127.0.0.1:6379> SRANDMEMBER lucky:1 3
1) "John"
2) "Echo"
3) "Lindy"
//抽取二等奖2个
127.0.0.1:6379> SRANDMEMBER lucky:1 2
1) "Sean"
2) "Lindy"
//抽取一等奖1个
127.0.0.1:6379> SRANDMEMBER lucky:1 1
1) "Tom"    

如果不允许重复中奖,可以使用 SPOP 命令

代码语言:javascript
复制
Copy
//添加抽奖名单
127.0.0.1:6379> SADD lucky:1 Tom
(integer) 1
127.0.0.1:6379> SADD lucky:1 Jerry
(integer) 1
127.0.0.1:6379> SADD lucky:1 John
(integer) 1
127.0.0.1:6379> SADD lucky:1 Marry
(integer) 1
127.0.0.1:6379> SADD lucky:1 Sean
(integer) 1
127.0.0.1:6379> SADD lucky:1 Lindy
(integer) 1
127.0.0.1:6379> SADD lucky:1 Echo
(integer) 1

//抽取三等奖3个
127.0.0.1:6379> SPOP lucky:1 3
1) "John"
2) "Echo"
3) "Lindy"
//抽取二等奖2个
127.0.0.1:6379> SPOP lucky:1 2
1) "Sean"
2) "Marry"
//抽取一等奖1个
127.0.0.1:6379> SPOP lucky:1 1
1) "Tom"   
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 游戏开发司机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二、命令
    • 常用命令
      • 可用版本
        • 返回值
          • 其他命令
          • 三、内部编码
            • 演示说明
            • 四、使用场景
              • 唯一计数器
                • 朋友圈点赞
                  • 共同关注和推荐关注
                    • 投票
                      • 标签
                      相关产品与服务
                      云数据库 Redis®
                      腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档