Redis数据结构之Set

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。相对于列表,集合也有两个特点:无序、不可重复

一个集合最多可以存储 2^32-1 个元素。概念和数学中个的集合基本类似,数学集合的概念是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。

简而言之,Redis 集合就是一些不重复值的组合。利用集合(Set)这个数据结构,Redis 可以存储一些集合类型的数据,Redis也通过一些简便的命令很好的支持了交集、并集和差集等集合的基本运算。


文章目录

    • @[toc]
        • 1、Set数据类型
          • 1.1、Set类型简介
          • 1.2、Set应用场景
        • 2、Set底层结构
          • 2.1、List底层结构介绍
          • 2.2、整数集合IntSet
          • 2.3、哈希表HashTable
        • 3、Set常用命令
          • 3.1、添加集合元素
          • 3.2、查看集合所有值
          • 3.3、判断一个值是否在集合中
          • 3.4、查看某集合的存值的数量
          • 3.5、删除集合中指定值的元素
          • 3.6、随机选出某集合中一个元素
          • 3.7、随机删除某集合中一个元素
          • 3.8、将一个集合中的某值移动至另一个集合
          • 3.9、集合运算:差集
          • 3.10、集合运算:交集
          • 3.11、集合运算:并集

1、Set数据类型

1.1、Set类型简介

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。相对于列表,集合也有两个特点:无序、不可重复

一个集合最多可以存储 2^32-1 个元素。概念和数学中个的集合基本类似,数学集合的概念是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。

简而言之,Redis 集合就是一些不重复值的组合。利用集合(Set)这个数据结构,Redis 可以存储一些集合类型的数据,Redis也通过一些简便的命令很好的支持了交集、并集和差集等集合的基本运算。

1.2、Set应用场景

常见的应用场景有:投票系统、标签系统、共同好友、共同关注、共同爱好、抽奖、商品筛选栏,访问 IP 统计等

使用场景:

  • 点赞、踩、收藏:Set 类型可以保证一个用户只能点一个赞;
  • 共同关注、标签:Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等;
  • 抽奖活动:存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次

2、Set底层结构

2.1、List底层结构介绍

Redis Set 的底层存储采用 整数集合 IntSet 和哈希表,二者是相互转换的,使用 IntSet 存储必须满足下面两个条件,否则使用 HashTable,条件如下:

  • 结合对象保存的所有元素都是整数值;
  • 集合对象保存的元素数量不超过 512 个

以 Set 的 SADD 命令为例子,整个添加过程如下:

  • 检查 Set 是否存在不存在则创建一个 Set 结合。
  • 根据传入的 Set 集合一个个进行添加,添加的时候需要进行内存压缩。
  • setTypeAdd 执行 Set 添加过程中会判断是否进行编码转换
void saddCommand(redisClient *c) {robj *set;int j, added = 0;// 取出集合对象set = lookupKeyWrite(c->db,c->argv[1]);// 对象不存在,创建一个新的,并将它关联到数据库if (set == NULL) {set = setTypeCreate(c->argv[2]);dbAdd(c->db,c->argv[1],set);// 对象存在,检查类型} else {if (set->type != REDIS_SET) {addReply(c,shared.wrongtypeerr);return;}}// 将所有输入元素添加到集合中for (j = 2; j < c->argc; j++) {c->argv[j] = tryObjectEncoding(c->argv[j]);// 只有元素未存在于集合时,才算一次成功添加if (setTypeAdd(set,c->argv[j])) added++;}// 如果有至少一个元素被成功添加,那么执行以下程序if (added) {// 发送键修改信号signalModifiedKey(c->db,c->argv[1]);// 发送事件通知notifyKeyspaceEvent(REDIS_NOTIFY_SET,"sadd",c->argv[1],c->db->id);}// 将数据库设为脏server.dirty += added;// 返回添加元素的数量addReplyLongLong(c,added);
}

稍微深入分析一下set的单个元素的添加过程,首先如果已经是 HashTable 的编码,那么我们就走正常的 HashTable 的元素添加,如果原来是 IntSet 的情况,那么我们就需要进行如下判断:

  • 如果能够转成 int 的对象(isObjectRepresentableAsLongLong),那么就用 IntSet 保存。
  • 如果用 IntSet 保存的时候,如果长度超过5 12(REDIS_SET_MAX_INTSET_ENTRIES)就转为 HashTable 编码。
  • 其他情况统一用 HashTable 进行存储。
2.2、整数集合IntSet

整数集合 IntSet 是 Redis用来保存整数值的集合的一种数据结构,可以用来保存 int 类型数据,并且可以保证不会出现重复元素。因此当一个集合中只包含整数元素且数量不多的时候,Redis 会选择使用整数集合作为底层实现。

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

img

如果你的集合只有整数值元素,并且数量是轻量的,这时候 Redis 会使用使用整数集合作为 Redis 集合的底层数据结构。参考如下代码:

typedef struct IntSet{// 编码格式uint32_t encoding;// 集合中的元素个数uint32_t length;// 保存元素数据int8_t contents[];
} IntSet;

我们拆解下:

属性说明
“encoding”编码方式
“length”数组中元素个数,也就是数组的整体长度
“contents[]”整数集合,集合的每个元素都是数组的一个数组项(item)。具有特点:按值的大小增序排列、不包含任何重复项

“contents” 是整数集合的底层实现,保存了整数集合的每一个元素,每个元素在该数组中从小到大有序排列,并且不重复(如何保证有序性和唯一性我们后面讨论插入的时候在说)。“contents” 数组虽然声明为 int8_t 类型,但其实真正的类型取决于 “encoding” 的值。在操作一个整数集合的时候,会首先获取 “encoding” 的值。

举个栗子,当我们执行 SADD numbers 1 3 5 向集合对象插入数据时,该集合对象在内存的结构如下:

image-20230823235054892

2.3、哈希表HashTable

Redis 中的 key-value 是通过 dictEntry 对象来实现的,而哈希表就是将 dictEntry 进行了再一次的包装得到的,这就是哈希表对象 dictht:

typedef struct dictht {dictEntry **table;//哈希表数组unsigned long size;//哈希表大小unsigned long sizemask;//掩码大小,用于计算索引值,总是等于size-1unsigned long used;//哈希表中的已有节点数
} dictht;

PS:table 是一个数组,其每个元素都是一个 dictEntry 对象。

hashtable 编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象对应一个集合元素,字典的值都是 NULL。当我们执行 SADD fruits "apple" "banana" "cherry" 向集合对象插入数据时,该集合对象在内存的结构如下:

image-20230823235716144


3、Set常用命令

3.1、添加集合元素

使用 SADD 命令添加集合元素

SADD set value

若值已存在,则不进行添加,并返回 0

image-20230821235344528

3.2、查看集合所有值

使用 SMEMBERS 命令查看集合所有值

SMEMBERS set

image-20230821235614136

3.3、判断一个值是否在集合中

使用 SISMEMBER 命令判断一个值是否在集合中

image-20230821235954832

3.4、查看某集合的存值的数量

使用 SCARD 命令查看某集合的存值的数量

SCARD set

image-20230822000410786

3.5、删除集合中指定值的元素

使用 SREM 删除集合中指定值的元素

SREM set value

image-20230822000710429

3.6、随机选出某集合中一个元素

使用 SRANDMEMBER 命令随机选出某集合中一个元素

SRANDMEMBER set

image-20230822000949807

3.7、随机删除某集合中一个元素

使用 SPOP 命令随机删除某集合中一个元素

SPOP set

image-20230822001227634

3.8、将一个集合中的某值移动至另一个集合

使用 SMOVE 命令 将一个集合中的某值移动至另一个集合

SMOVE source target value

image-20230822001457709

3.9、集合运算:差集

使用 SDIFF 命令进行集合运算:差集

SDIFF set1 set2

image-20230822001906994

3.10、集合运算:交集

使用 SINTER 命令进行集合运算:交集

SINTER set1 set2

image-20230822002039149

3.11、集合运算:并集

使用 SUNION 命令进行集合运算:并集

SUNION set1 set2

image-20230822001939037

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/51586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js reverse实现数据的倒序

2023.8.25今天我学习了如何在数组顺序进行倒序排列&#xff0c;如&#xff1a; 原数组为&#xff1a; 我们只需要对数组使用reverse()方法 let demo [{id: 1, name: 一号},{id: 2, name: 二号},{id: 3, name: 三号},]demo.reverse()console.log(demo) 扩展&#xff1a; 当我…

jmeter入门:接口压力测试全解析

一.对接口压力测试 1.配置 1.添加线程组&#xff08;参数上文有解释 这里不介绍&#xff09; 2.添加取样器 不用解释一看就知道填什么。。。 3.添加头信息&#xff08;否则请求头对不上&#xff09; 也不用解释。。。 4.配置监听器 可以尝试使用这几个监听器。 2.聚合结果…

Tushare入门小册

Tushare入门小册 一、Tushare平台介绍 Pro版数据更稳定质量更好了&#xff0c;我们提供的不再是直接从互联网抓取&#xff0c;而是通过社区的采集和整理存入数据库经过质量控制后再提供给用户。但Pro依然是个开放的&#xff0c;免费的平台&#xff0c;不带任何商业性质和目的…

什么是服务端渲染?前后端分离的优点和缺点?

一.概念 服务端渲染简单点就是服务端直接返回给客户端一个完整的页面&#xff0c;也就是一个完整的html页面&#xff0c;这个页面上已经有数据了。说到这里你可能会觉得后端怎么写页面啊&#xff0c;而且服务端返回页面不是加载更慢吗&#xff1f;错了&#xff0c;因为我们现在…

4.网络设计与redis、memcached、nginx组件(一)

网络组件系列文章目录 第四章 网络设计与redis、memcached、nginx组件 文章目录 网络组件系列文章目录文章的思维导图前言一、网络相关的问题&#xff0c;网络开发中要处理那些问题&#xff1f;网络操作IO连接建立连接断开消息到达消息发送网络操作IO特性 二、网络中IO检测IO函…

VR、AR、MR 傻傻分不清楚?区别的底层逻辑?

VR是一种能够制作虚拟物体并与人互动的基础技术。它与操作者所处的环境无关。AR可以让在特定位置出现或消失。MR可以让虚拟物体与真实物体进行互动。 AR和MR的大部分应用场景都是随机的&#xff0c;所以硬件基本都采用手机和眼镜。提升了便携性。牺牲了性能。这就导致了AR与MR…

基于Springboot+vue的宠物服务管理系统——LW模板

摘 要 21世纪的今天&#xff0c;随着人类生活从低层次不断向高层次跃进&#xff0c;人类和宠物的关系已经密不可分。人们生活水平的进步进而带来了宠物生活水平的进步&#xff0c;因此对于宠物的管理也愈发的丰富起来&#xff0c;宠物的膳食安排&#xff0c;宠物的医疗安排等都…

罗勇军 →《算法竞赛·快冲300题》每日一题:“乘积” ← 动态规划

【题目来源】http://oj.ecustacm.cn/problem.php?id1781http://oj.ecustacm.cn/viewnews.php?id1023【题目描述】 给你一个长度为 n 的序列&#xff0c;序列中的元素只包括 1 和 -1。 请问有多少个连续的子序列乘积为正数。【输入格式】 输入第一行为正整数 n。&#xff08;n…

SpringBoot概述SpringBoot基础配置yml的使用多环境启动

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 SpringBoot简介 一、 SpringBoot概述1.1 起步依赖…

【深度学习】实验01 波士顿房价预测

文章目录 波士顿房价预测SklearnKeras 波士顿房价预测 Sklearn # 导入机器学习库 from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, LogisticRegression, RidgeCV from sklearn.datasets import load_boston from sklearn.model_selection import t…

ProxySQL+MGR高可用搭建

服务器点位 NODEIPmgr_node0192.165.26.200mgr_node1192.165.25.201mgr_node2192.165.26.202proxysql192.165.26.199 修改主机名 # 登录192.165.26.200 hostnamectl set-hostname mgr_node0 # 登录192.165.26.201 hostnamectl set-hostname mgr_node1 # 登录192.165.26.202 …

后端项目开发:集成接口文档(swagger-ui)

swagger集成文档具有功能丰富、及时更新、整合简单&#xff0c;内嵌于应用的特点。 由于后台管理和前台接口均需要接口文档&#xff0c;所以在工具包构建BaseSwaggerConfig基类。 1.引入依赖 <dependency><groupId>io.springfox</groupId><artifactId>…

Docker自学:利用FastAPI建立一个简单的web app

环境配置&#xff1a;下载Docker Desktop 文件一&#xff1a;main.py from typing import Unionfrom fastapi import FastAPIimport uvicornapp FastAPI()app.get("/") def read_root():return {"Hello": "World"}app.get("/items/{item…

线性代数的学习和整理10:各种特殊类型的矩阵(草稿-----未完成 建设ing)

目录 1 图形化分类 1.1对称矩阵 1.2 梯形矩阵 1.3 三角矩阵 1.3.1 上三角矩阵 1.4 对角线矩阵 2 按各自功能分 2.1 等价矩阵 2.2 增广矩阵 2.3 伴随矩阵 2.4 正交矩阵 2.5 正交矩阵 2.6 相似矩阵 1 图形化分类 1.1对称矩阵 1.2 梯形矩阵 1.3 三角矩阵 1.3.1 上…

有序充电运营管理平台是基于物联网和大数据技术的充电设施管理系统-安科瑞黄安南

随着我国能源战略发展以及低碳行动的实施&#xff0c;电动汽车已逐步广泛应用&#xff0c;而电动汽车的应用非常符合当今社会对环保意识的要求&#xff0c;以及有效节省化石燃料的消耗。 由于其没有污染排放的优点以及政府部门的关注&#xff0c;电动汽车将成为以后出行的重要…

OnePlus Open可折叠手机:规格、价格、发布日期等详细信息汇总!

我们知道OnePlus可折叠手机即将问世,无论它是否被命名为OnePlus Open。我们迫不及待地想让它到来,为该公司再添一根弦,为最好的可折叠手机增添一个新的竞争对手。 OnePlus以前没有生产过任何可折叠产品,但它确实拥有合作伙伴公司Oppo的丰富知识,并可以向三星、摩托罗拉和…

maven无法从阿里云中央仓库下载jar包的解决方法

这个方法不一定适用于所有人。 问题描述&#xff1a;启动公司的SpringBoot项目时&#xff0c;maven爆红提示从阿里云中央仓库找不到目标jar包&#xff0c;但我本地maven仓库是有这个jar包的&#xff08;版本也对的上&#xff09;&#xff0c;我就好奇maven为什么不从本地获取ja…

支持dolby vision的盒子接支持dolby vision的电视,在adaptive hdr时,播放非dv的hdr视频,输出sdr

支持dolby vision的盒子接支持dolby vision的电视&#xff0c;setting选择adaptive hdr&#xff0c;按照这个配置在播放非dv的hdr视频时&#xff0c;会输出sdr。 看起来是很不合理的&#xff0c;高级的产品播放高级的片源&#xff0c;却输出低级的画质。 想要搞清楚这个问题&am…

前端食堂技术周刊第 95 期:Fresh 1.4、Rollup 迁移至 SWC计划、RSC Devtools、使用开源库的边界、AI 帮你讲论文

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;冰葡美式 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来看下…

一文读懂 Nuxt.js 服务端组件

服务端组件在 Web 开发生态系统中变得越来越普遍。传统上&#xff0c;在单页面应用中&#xff0c;即使是服务端渲染的应用&#xff0c;服务端仅与第一次加载相关&#xff0c;之后将由客户端接管。这意味着 Web 应用的每个部分都必须能够在客户端和服务端上渲染。 相反&#xf…