Redis 7.x 系列【9】数据类型之自动排重集合(Set)

有道无术,术尚可求,有术无道,止于术。

本系列Redis 版本 7.2.5

源码地址:https://gitee.com/pearl-organization/study-redis-demo

文章目录

    • [1. 前言](#1. 前言)
    • [2. 常用命令](#2. 常用命令)
      • [2.1 SADD](#2.1 SADD)
      • [2.2 SCARD](#2.2 SCARD)
      • [2.3 SISMEMBER](#2.3 SISMEMBER)
      • [2.4 SREM](#2.4 SREM)
      • [2.5 SSCAN](#2.5 SSCAN)
      • [2.6 SDIFF](#2.6 SDIFF)
      • [2.7 SUNION](#2.7 SUNION)
      • [2.8 SINTER](#2.8 SINTER)
      • [2.10 SRANDMEMBER](#2.10 SRANDMEMBER)
    • [3. 应用场景](#3. 应用场景)
      • [3.1 随机抽奖](#3.1 随机抽奖)
      • [3.2 共同关注](#3.2 共同关注)
      • [3.3 可能认识的人](#3.3 可能认识的人)
      • [3.4 点赞](#3.4 点赞)

1. 前言

Redis Set 数据类型是一种无序集合,它不允许重复的元素,可以类比 Java 中的 HashSet。

2. 常用命令

Set 相关所有命令:

命名 描述
SADD 向集合添加一个或多个成员
SCARD 获取集合的成员数
SDIFF 返回给定所有集合的差集
SDIFFSTORE 返回给定所有集合的差集并存储在 destination 中
SINTER 返回给定所有集合的交集
SINTERCARD 类似于 SINTER,但它不返回结果集,而是只返回结果的基数。返回集合的基数,该基数将由所有给定集合的交集产生
SINTERSTORE 返回给定所有集合的交集并存储在 destination 中
SISMEMBER 判断 member 元素是否是集合 key 的成员
SMEMBERS 获取一个集合的所有成员
SMISMEMBER 从存储在 key 处的集合值中返回一个随机元素
SMOVE 将 member 元素从 source 集合移动到 destination 集合
SPOP 移除并返回集合中的一个随机元素
SRANDMEMBER 返回集合中一个或多个随机数
SREM 移除集合中一个或多个成员
SSCAN 迭代集合中的元素
SUNION 返回所有给定集合的并集
SUNIONSTORE 所有给定集合的并集存储在 destination 集合中

2.1 SADD

SADD 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素。

注意事项:

  • 假如集合 key 不存在,则创建一个只包含被添加的元素作为成员的集合。
  • 当集合 key 不是集合类型时,返回一个错误。
  • 在 Redis 2.4 版本以前, 只接受单个成员值。

基本语法:

java 复制代码
SADD key member [member ...]

示例:

java 复制代码
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SADD myset "World"
(integer) 0
redis> SMEMBERS myset
1) "Hello"
2) "World"

2.2 SCARD

SCARD 命令返回集合中元素的数量,当集合 key 不存在时,返回 0 。

基本语法:

java 复制代码
SCARD key

示例:

java 复制代码
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SCARD myset
(integer) 2

2.3 SISMEMBER

SISMEMBER 命令返回存储在 key 中的集合的所有的成员。

注意事项:

  • 不存在的集合被视为空集合
  • 与运行带有一个参数 key 的 SINTER 有同样的效果。

基本语法:

java 复制代码
SMEMBERS key

示例:

java 复制代码
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SMEMBERS myset
1) "Hello"
2) "World"

2.4 SREM

SREM 用于在集合中删除指定的元素,返回值为被删除元素个数,不含不存在的元素。

注意事项:

  • 如果指定的元素不是集合成员则被忽略。
  • 如果集合 key 不存在则被视为一个空的集合,该命令返回 0。
  • 如果key的类型不是一个 Set ,则返回 ERR WRONGTYPE Operation against a key holding the wrong kind of value 错误。

基本语法:

java 复制代码
SREM key member [member ...]

示例:

bash 复制代码
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SREM myset "one"
(integer) 1
redis> SREM myset "four"
(integer) 0
redis> SMEMBERS myset
1) "two"
2) "three"

2.5 SSCAN

SSCAN 命令用于遍历集合中键的元素,继承自 SCAN。

基本语法:

java 复制代码
SSCAN key cursor [MATCH pattern] [COUNT count]

命令参数:

  • cursor:游标。
  • pattern :匹配的模式。
  • count :指定从数据集里返回多少元素,默认值为 10 。

示例:

bash 复制代码
> SADD myset1 "Google"
(integer) 1
> SADD myset1 "Redis"
(integer) 1
> SADD myset1 "Taobao"
(integer) 1
> SSCAN myset1 0 match R*
1) "0"
2) 1) "Redis"

2.6 SDIFF

SDIFF 命令返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。不存在的集合 key 将视为空集。

基本语法:

java 复制代码
SDIFF key [key ...]

示例:

bash 复制代码
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SDIFF key1 key2
1) "a"
2) "b"

2.7 SUNION

SUNION 命令用于返回所有给定集合的并集。

基本语法:

java 复制代码
SUNION key [key ...]

示例:

bash 复制代码
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SUNION key1 key2
1) "b"
2) "c"
3) "a"
4) "d"
5) "e"

2.8 SINTER

SINTER 返回所有给定集合的成员交集。

基本语法:

java 复制代码
SINTER key [key ...]

示例:

bash 复制代码
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SINTER key1 key2
1) "c"

2.10 SRANDMEMBER

SRANDMEMBER 命令随机返回集合 key 中的一个或多个随机元素。

注意事项:

  • 如果 key 不存在则返回 nil 。
  • 使用 count 参数,则返回一个随机的元素数组,如果 key 不存在则返回一个空的数组。

基本语法:

java 复制代码
SRANDMEMBER key [count]

示例:

bash 复制代码
redis> SADD myset one two three
(integer) 3
redis> SRANDMEMBER myset
"two"
redis> SRANDMEMBER myset 2
1) "two"
2) "three"
redis> SRANDMEMBER myset -5
1) "one"
2) "three"
3) "two"
4) "one"
5) "two"

3. 应用场景

Set 数据类型除了普通的存储功能外,还提供了交集、并集、差集操作,可用于以下场景:

  • 抽奖系统、随机点名
  • 共同关注、共同粉丝、共同喜好、共同好友等
  • 数据不能重复的场景,例如点赞
  • 可能认识的人

3.1 随机抽奖

用户点击参与抽奖时,添加到抽奖集合中:

bash 复制代码
localhost:0>SADD join_user_set 1
"1"
localhost:0>SADD join_user_set 2
"1"
localhost:0>SADD join_user_set 3
"1"

查看抽奖总参与人数:

bash 复制代码
localhost:0>SCARD join_user_set
"3"

随机抽取两人(不删除元素):

java 复制代码
localhost:0>SRANDMEMBER key 2

随机抽取两人(删除元素):

java 复制代码
localhost:0>SRANDMEMBER join_user_set 2

3.2 共同关注

我的关注:

bash 复制代码
localhost:0>SADD my_follow_set u1 u2 u3 
"3"

贾乃亮的关注:

bash 复制代码
localhost:0>SADD jianailiang_follow_set u2 u3 u4
"3"

查看共同关注:

bash 复制代码
localhost:0>SINTER my_follow_set  jianailiang_follow_set
 1)  "u2"
 2)  "u3"

3.3 可能认识的人

在社交平台中,添加好友时,系统会推荐可能认识的人,例如抖音:

例如快手:

一般有以下规则:

  • 手机号匹配:社交平台都要求使用手机号注册,在读取你的通讯录后,会根据通讯录手机号查询用户
  • 附近的人:通过定位权限获取定理位置,并筛选出附近的人
  • 好友差集:计算用户之间的共同好友,如果共同好友超过一定数量,说明两个人是同一个圈子的人,例如同一个班级,两个学生之间的共同好友肯定很多。然后通过计算两人好友之间的差集,进行推荐
  • 标签:例如通过相同的兴趣爱好进行推荐

例如,当前我的好友列表:

bash 复制代码
localhost:0>SADD my_friend_set u1 u2 u3 u5 
"4"

我的好友 u1 的好友列表:

bash 复制代码
localhost:0>SADD u1_frieng_set  u1 u2 u3 u6
"4"

我和 u1 的共同好友:

bash 复制代码
localhost:0>SINTER my_friend_set u1_frieng_set
 1)  "u1"
 2)  "u2"
 3)  "u3"

将我有但是 u1 没有的好友推荐给 u1 :

bash 复制代码
localhost:0>SDIFF u1_frieng_set my_friend_set
 1)  "u5"

将 u1 有但是我没有的好友推荐给我:

java 复制代码
localhost:0>SDIFF  my_friend_set u1_frieng_set
 1)  "u6"

3.4 点赞

新增点赞用户:

bash 复制代码
localhost:0>SADD msg_1 u1 u2
"2"

取消点赞:

bash 复制代码
localhost:0>SREM msg_1 u1
"1"

查看所有点赞用户:

java 复制代码
localhost:0>SMEMBERS msg_1
 1)  "u2"

查看点赞总数:

java 复制代码
localhost:0>SCARD msg_1
"1"
相关推荐
imDwAaY1 天前
操作系统如何管理程序运行?从线程、进程到内存隔离与用户态切换:CS162 Note2
android·java·redis
码途行者1 天前
处理超时未支付订单:两套轻量化方案,附 PHP 极简实现
开发语言·redis·php
草莓熊Lotso1 天前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
Chenyu_3101 天前
DPDK、TC 和 XDP:Linux 高性能网络到底在优化什么
linux·服务器·网络·缓存
我不会起名字3221 天前
Redis 突然只能读不能写:MISCONF 报错的 3 类触发条件与 4 步恢复
运维·redis·持久化·排查·misconf
我不会起名字3222 天前
Redis 从 0 到 1(九):主库宕机 30 秒自动切主——1 主 2 从 3 哨兵 + Go 客户端
redis·docker·sentinel·高可用·哨兵
毕业设计7032 天前
(免费领源码)SSM董家湾线上点餐系统04682- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
java·redis·mysql·tomcat·maven·mybatis·ssm
用户094248568032 天前
第1章:Redis 术语全景与单线程工作原理
redis·快应用·源码阅读
hflmwl82 天前
RedisDesktopManager安装包中文版官方下载,redis可视化客户端工具下载
数据库·redis·缓存·可视化客户端工具
一枕槐安4872 天前
大模型应用后端设计:上下文管理、缓存、降级策略的工程方案总结
java·spring·缓存