【Redis】set 类型

article/2025/6/6 4:33:41

set

  • 一. set 类型介绍
  • 二. set 命令
    • sadd、smembers、sismember
    • scard、spop、srandmember
    • smove、srem
    • 集合间操作
      • 交集:sinter、sinterstore
      • 并集:sunion、sunionstore
      • 差集:sdiff、sdiffstore
  • 三. set 命令小结
  • 四. set 内部编码方式
  • 五. set 使用场景
    • 用户标签
    • 共同好友
    • 统计 UV

一. set 类型介绍

  • 集合就是把一些有关联的数据放到一起,保存多个字符串类型的元素的 (可以使用 JSON 这样的格式,让 string 存储结构化数据),但和列表类型不同的是:
    • 元素之间是无序的。
      • 此处说的无序和之前 list 说的有序是对应的。
      • 有序:顺序很重要,变换一下顺序,就是不同的列表。
      • 无序:顺序不重要,变换一下顺序,还是那个集合。
      • list:[1, 2, 3] 和 [2, 1, 3] 是不同的 list
      • set:[1, 2, 3] 和 [2, 1, 3] 是相同的 set
    • 元素不允许重复。
    • 一个集合中最多可以存储 2^32 - 1 个元素。
  • Redis 除了支持集合内的增删查改操作,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多问题。

集合类型:

在这里插入图片描述

二. set 命令

在 set 中的元素叫做 member,就像在 hash 中的元素叫做 field、value 类似。

sadd、smembers、sismember

  • sadd:添加⼀/多个元素到 set 中。注意:重复的元素无法添加到集合中。
  • 语法:sadd key member [member ...]
  • 时间复杂度:添加一个元素是 O(1),添加 N 个元素是 O(N)
  • 返回值:本次添加成功的元素个数。

在这里插入图片描述

  • smembers:获取一个 set 中的所有元素。注意:元素间的顺序是无序的。
  • 语法:smembers key
  • 时间复杂度:O(N),N 是集合中元素的个数。
  • 返回值:所有元素的列表。

在这里插入图片描述

  • sismember:判断一个元素在不在 set 中。
  • 语法:sismember key member
  • 时间复杂度:O(1)
  • 返回值:元素在 set 中,返回 1;元素不在 set 中或者 key 不存在,返回 0

在这里插入图片描述

scard、spop、srandmember

  • scard:获取一个 set 的基数 (cardinality),即 set 中的元素个数。
  • 语法:scard key
  • 时间复杂度:O(1)
  • 返回值:set 内的元素个数。

在这里插入图片描述

  • spop:从 set 中删除并返回一个或者多个元素。注意:由于 set 内的元素是无序的,所以取出哪个元素实际是未定义行为,即可以看作随机的。
  • 语法:spop key [count]
  • 时间复杂度:O(N),N 是 count 的个数。
  • 返回值:取出的元素。

在这里插入图片描述

  • srandmember:从 set 中返回一个或者多个随机的元素。
  • 语法:srandmember key [count]
  • 时间复杂度:O(N),N 是 count 的个数。
  • 返回值:取出的元素。

在这里插入图片描述

在 Redis 源码中,针对 spop 实现的时候,就采取了 “生成随机数” srandmember 的方式。

smove、srem

  • smove:将一个元素从源 set 取出并放入目标 set 中。
  • 语法:smove source destination member
  • 时间复杂度:O(1)
  • 返回值:移动成功时,返回 1;移动失败时,返回 0

在这里插入图片描述

如果我给 key1 里再添加一个 1,再次把这个 1 移动给 key2,此时 smove 不会视为出错,也会按照 删除-插入 进行执行。

在这里插入图片描述

  • srem:将指定的元素从 set 中删除
  • 语法:srem key member [member ...]
  • 时间复杂度:O(N),N 是要删除的元素个数。
  • 返回值:删除成功的元素个数。

在这里插入图片描述

不同操作的返回值,含义差别还是挺大的,需要用的时候,多翻文档即可。

集合间操作

  • 交集 (inter):最终结果同时出现在两个集合中。
  • 并集 (union):把多个集合中的数据都集中放在一起,如果元素有重复,也最终只保留一份。
  • 差集 (diff):A 和 B 做差集,就是找出 A 中存在,但是 B 中不存在的元素。

在这里插入图片描述

交集:sinter、sinterstore

  • sinter:获取给定 set 的交集中的元素。
  • 语法:sinter key [key ...]
  • 时间复杂度:O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数。
  • 返回值:交集的元素。

在这里插入图片描述

  • sinterstore:获取给定 set 的交集中的元素并保存到目标 set 中。
  • 语法:sinterstore destination key [key ...]
  • 时间复杂度:O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数。
  • 返回值:交集的元素个数。

在这里插入图片描述

并集:sunion、sunionstore

  • sunion:获取给定 set 的并集中的元素。
  • 语法:sunion key [key ...]
  • 时间复杂度:O(N),N 是给定的所有集合的总的元素个数。
  • 返回值:并集的元素。

在这里插入图片描述

  • sunionstore:获取给定 set 的并集中的元素并保存到目标 set 中。
  • 语法:sunionstore destination key [key ...]
  • 时间复杂度:O(N),N 是给定的所有集合的总的元素个数。
  • 返回值:并集的元素个数。

在这里插入图片描述

差集:sdiff、sdiffstore

  • sdiff:获取给定 set 的差集中的元素。
  • 语法:sdiff key [key ...]
  • 时间复杂度:O(N),N 是给定的所有集合的总的元素个数。
  • 返回值:差集的元素。

在这里插入图片描述

  • sdiffstore:获取给定 set 的差集中的元素并保存到目标 set 中。
  • 语法:sdiffstore destination key [key ...]
  • 时间复杂度:O(N),N 是给定的所有集合的总的元素个数。
  • 返回值:差集的元素个数。

在这里插入图片描述

三. set 命令小结

命令执行效果时间复杂度
sadd key member [member …]向集合中添加元素O(K),K 是元素的个数
smembers key求集合中的元素O(K),K 是元素的个数
sismember key member判断元素是否在集合中O(1)
scard key获取集合中元素的个数O(1)
spop key [count]随机删除 count 个元素O(N),N 是 count
srandmember key [count]随机删除 count 个元素O(N),N 是 count
smove source destination member移动源集合中的一个元素到目标集合O(1)
srem key member [member …]删除集合中的元素O(K),K 是元素的个数
sinter key [key …]获取集合的交集O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数
sinterstore destination key [key …]存储集合的交集到目标集合中O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数
sunion key [key …]获取集合的并集O(N),N 是所有集合的元素个数
sunionstore destination key [key …]存储集合的并集到目标集合中O(N),N 是所有集合的元素个数
sdiff key [key …]获取集合的差集O(N),N 是所有集合的元素个数
sdiffstore destination key [key …]存储集合的差集到目标集合中O(N),N 是所有集合的元素个数

四. set 内部编码方式

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

  • intset (整数集合):当集合中的元素都是整数并且元素的个数小于 set-max-intset-entries 配置 (默认 512 个) 时,Redis 会选用 intset 来作为集合的内部实现,从而减少内存的使用。
    • Redis 是内存数据库,当元素均为整数,并且元素的个数不是很多的时候,为了节省空间,做出的特点优化。
  • hashtable (哈希表):当集合类型无法满足 intset 的条件时,Redis 会使用 hashtable 作为集合的内部实现。

使用 object encoding key 可以查看集合内部的编码方式,如下:

在这里插入图片描述

五. set 使用场景

用户标签

集合类型比较典型的使用场景是标签 (tag),使用 set 来保存用户的 “标签”

  • 例如 A 用户对娱乐、体育板块比较感兴趣,B 用户对历史、新闻比较感兴趣,这些兴趣点可以被抽象为标签。例如一个电子商务网站会对不同标签的用户做不同的产品推荐。
  • 有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于增强用户体验和用户黏度都非常有帮助。分析出你这个人的一些特征,分析清楚之后,再投其所好。
  • 上述用户数据,很多公司都在共享。
    • 两个程序,两个账号,如何知道这两个账号是一个人?
    • 现在的程序登入,主要就是两个入口,手机号、微信。
  • 通过上述过程,搜集到的用户特征,就会转换成 “标签” (简短的字符串),此时就可以把标签保存到 Redis 的 set 中。
    • 用户画像,这种事情其实是挺复杂的事情,一般一个大厂都会有专门的团队做这样工作。
    • 上述玩法,抖音玩的是最好的,其它互联网大厂一看这么搞真好,于是纷纷效仿。
    • 但是存在 “信息茧房” 问题:你看到的内容始终就是一个小圈子,看不到其它圈子中的事物。
    • 当你很认真的看了一个视频之后,人家的服务器就判定你,非常爱看这种类型的视频,接下来就给你疯狂推送。

下面的演示通过集合类型来实现标签的若干功能。

  • 给用户添加标签
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
sadd user:k:tags tag1 tag2 tag4
  • 给标签添加用户
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
sadd tagk:users user:1 user:4 user:9 user:28
  • 删除用户下的标签
srem user:1:tags tag1 tag5
...
  • 删除标签下的用户
srem tag1:users user:1
srem tag5:users user:1
...
  • 计算用户的共同兴趣标签
sinter user:1:tags user:2:tags

共同好友

使用 set 来计算用户之间的公共好友,基于 “集合求交集”

  • 例如:QQ,我这边加了很多好友,你那边也加了很多好友。
  • 基于上述还可以做一些好友推荐:A 和 B 是好友,A 和 C 是好友,B 和 C 和 D 都是好友,此时系统就会把 D 推荐给 A

统计 UV

一个互联网产品,如何衡量用户量,用户规模?主要的指标,是两方面:

  • PV (page view):用户每次访问该服务器,都会产生一个 PV
  • UV (user view):每个用户访问该服务器,都会产生一个 UV,但是同一个用户多次访问,不会增加 UV 的个数。
    • UV 需要按照用户进行去重,上述的去重功能,就可以使用 set 来实现。

http://www.hkcw.cn/article/foNGZXDqXL.shtml

相关文章

006网上订餐系统技术解析:打造高效便捷的餐饮服务平台

网上订餐系统技术解析:打造高效便捷的餐饮服务平台 在数字化生活方式普及的当下,网上订餐系统成为连接餐饮商家与消费者的重要桥梁。该系统以菜品分类、订单管理等模块为核心,通过前台展示与后台录入的分工协作,为管理员和会员提…

Python趣学篇:Pygame重现经典打砖块游戏

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《Python星球日记》 目录 一、游戏背景与技术选型1. 打砖块游戏…

Transformer学习资料

​​核心论文​​ 原论文标题:《Attention Is All You Need》(Transformer原始论文) ​​Transformer学习资源​​ 视频教程: B站中文视频:Transformer详解 中文教程: GitHub项目:learn-nlp-wi…

AIGC 基础篇 高等数学篇 02导数与微分

声明:本文章仅用于复习,请不要将本文章当做预习篇或者讲解篇 此外,此文章不会包含全部的高等数学知识,仅仅是为了学习AI而进行的前期学习,因此知识含量不会很多,另外补充一句,博主已经对上一篇…

MQTTX连接阿里云的物联网配置

本文的目标是通过MQTTX的客户端,连接到阿里云的物联网的平台,发送温度信息,在阿里云的平台中显示出来。阿里云免费注册,免费有一个MQTT的服务器。有数量限制,但是对于测试来讲,已经足够。 1、注册阿里云的物…

06-排序

排序 1. 排序的概念及其应用 1.1 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键…

MS1023/MS1224——10MHz 到 80MHz、10:1 LVDS 并串转换器(串化器)/串并转换器(解串器)

产品简述 MS1023 串化器和 MS1224 解串器是一对 10bit 并串 / 串并转 换芯片,用于在 LVDS 差分底板上传输和接收 10MHz 至 80MHz 的并行字速率的串行数据。起始 / 停止位加载后,转换为负载编 码输出,串行数据速率介于 120Mbps…

Cyber Weekly #58

赛博新闻 1、DeepSeek新版R1更新,幻觉率大幅降低 5月28日,DeepSeek-R1模型已升级至DeepSeek-R1-0528版本,核心在于显著提升模型的思维深度与推理能力。该版本基于DeepSeek V3 Base模型,通过强化后训练显著优化了在数学、编程及通…

换一条宽带ip地址会变吗?同一个宽带如何不同ip地址

宽带IP地址是否变化取决于更换的方式,以及你使用的是公网IP还是内网IP。以下是具体分析,并附上同一个宽带下切换IP的实用方法: 🌐 一、更换宽带是否会改变IP地址? 1. 更换宽带线路(如从电信换到移动&#x…

环境对象以及回调函数

1.环境对象 2.回调函数

SQL Indexes(索引)

目录 Indexes Using Clustered Indexes Using Nonclustered Indexes Declaring Indexes Using Indexes Finding Rows Without Indexes Finding Rows in a Heap with a Nonclustered Index Finding Rows in a Clustered Index Finding Rows in a Clustered Index with …

graphviz, dot, Error: lost rA sA edge; 独立的模块

1) 有向图dot文件 digraph R { node [shaperecord]; { ranksame rA sA tA } { ranksame uB vB wB } rA -> sA; sA -> vB; t -> rA; uB -> vB; wB -> u; wB -> tA; } 2)出现报警信息 Warning: flat edge between adjacent …

SpringBoot接入Kimi实践记录轻松上手

kimi简单使用 什么是Kimi API 官网:https://platform.moonshot.cn/ Kimi API 并不是一个我所熟知的广泛通用的术语。我的推测是,你可能想问的是关于 API 的一些基础知识。API(Application Programming Interface,应用程序编程接…

Windows版PostgreSQL 安装 vector 扩展

问题 spring-ai在集成PGVector向量存储的时候会报错如下,那么就需要安装pgsql的vector扩展。 SQL [CREATE EXTENSION IF NOT EXISTS vector]; 错误: 无法打开扩展控制文件 "C:/Program Files/PostgreSQL/9.6/share/extension/vector.control": No such …

【操作系统原理08】文件管理

文章目录 零.大纲一.文件管理0.大纲1.文件管理1.1 **文件属性**1.2 文件内部数据组织1.3 文件之间的组织1.4操作系统提供功能1.5 文件在外存存放 二.文件的逻辑结构0.大纲1.无结构文件2.有结构文件 三.文件目录0.大纲1.文件控制块2.目录结构3.索引节点(FCB改进) 四.文件共享0.大…

力扣面试150题--二叉搜索树中第k小的元素

Day 58 题目描述 思路 直接采取中序遍历,不过我们将k参与到中序遍历中,遍历到第k个元素就结束 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* …

Linux网络基础概念(1)

文章目录 前言一、计算机网络背景网络发展认识协议 二、网络协议协议分层OSI七层模型TCP/IP五层(或四层)模型 三、网络传输基本流程同局域网的两台主机通信跨网络的两台主机通信 四、网络中的地址管理认识IP地址认识MAC地址 总结 前言 到网络喽&#xff…

【Typst】6.布局函数

概述 上节我们介绍了文档结构元素的函数,本节介绍一些控制布局使用的函数,掌握他们之后你可以更进一步的控制页面元素的布局。 系列目录 1.Typst概述2.Typst标记语法和基础样式3.Typst脚本语法4.导入、包含和读取5.文档结构元素与函数6.布局函数 对齐…

初识高通camx

一、chi和camx之间如何通信: Chi对Camx的操作,需要通过 ExtensionModule 进行操作,因此,CamX对外提供的接口扩展需要通过ExtensionModule进行,里面一个重要的变量就是g_chiContextOps。 Camx对Chi的操作,是…

NebulaAI V2.6.0发布:工作流功能正式上线!

2025年5月30日,NebulaAI V2.6.0版本正式上线! 在V2.6.0版本中,NBAI团队对工作流功能进行了重磅升级,用户可以通过创建工作流来与大模型交互: 支持选择常用大模型进行工作流的交互; 支持文件上传&#…