Redis整数集合

前言

        整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。

一. 整数集合的实现

        1.1 结构

        整数集合(intset)是Redis用于保存整数值的集合抽象数据结构,它可以保存类型为int16_t,int32_t或者int64_t的整数值,并且保证集合中不会出现重复元素。

        每个intset.h/intset结构表示一个整数集合:

typedef struct intset {//编码方式uint32_t encoding;//集合中包含元素的个数uint32_t length;//保存元素的数组int8_t contents[];
} intset;

        content数组是整数集合的底层实现:整数集合的每一个元素都是contents数组的一个数组项。各个项在数组中按值的大小从小到大有序地排列,并且数组中不包含任何重复项。

        length属性记录了整数集合包含的元素数量,也即是contents数组长度。

        虽然intset结构contents属性声明为int8_t类型的数组。但是实际上contents数组并不保持任何int8_t类型的值。contents数组的真正类型取决于encoding属性值。

  • 如果encoding属性值为INTSET_ENC_INT16,那么contents就是一个int16_t类型的数组。数组里的每一项都是int16_t类型的整数值。
  • 如果encoding属性值为INTSET_ENC_INT32,那么contents就是一个int32_t类型的数组。数组里的每一项都是int32_t类型的整数值。
  • 如果encoding属性值为INTSET_ENC_INT64,那么contents就是一个int64_t类型的数组。数组里的每一项都是int64_t类型的整数值。

        下图展示了一个encoding为INTSET_ENC_INT64,length等于4的整数集合。contents数组按从小到大的顺序保存集合中的四个元素。因为每一个元素是int64_t类型的整数值,所以contents数组大小为sizeof(int64_t) * 4 = 64 * 4 = 256位。

        虽然contents数组保存的四个整数值中,只有-2675256175807981027真正需要int64_t类型来进行保存,而其他的1,3,4可以使用int16_t类型保存。不过根据整数集合的升级规则,当向一个底层位int16_t数组的整数集合添加一个int64_t类型的整数值时,整数集合中的所有元素都会被转化成int64_t类型。

        1.2 升级

        每当我们要将一个新元素添加到整数集合中,并且新元素的类型比整数集合现有的所有元素类型都要长时,整数集合需要先进行升级(upgrade),然后才能将新元素添加到整数集合中。

        升级步骤:

  1. 根据新元素类型,扩展整数集合底层数组的空间大小,并为新元素分配空间。
  2. 将底层数组现有元素都转化成与新元素相同的类型,并将类型转化后的元素放置到正确位置上。而在放置元素过程中,需要维持底层数组有序性不变。
  3. 将新元素添加到底层数组里。

        举个例子:

        现在有一个INTSET_ENC_INT16编码的整数集合,集合中包含三个int16_t类型的元素。纵隔占16*3=48位。

        现在要将类型int32_t的整数值65535添加到整数集合中。因为65535的类型int32_t比整数集合中的所有元素都长,所以需要对整数集合进行升级。

        升级首先要做的是,根据新类型长度,以及集合中元素数量(包括新元素),对底层数组空间进行重新分配。

        现在整数集合中又四个元素,类型需要升级位int32_t,需要空间32 * 4 = 128位,如下图。虽然程序对底层数组进行了空间重新分配,但是,数组中原有的三个元素1,2,3类型仍然是int16_t。这些元素还是保存在数组contents的前48位。

        所以程序接下来需要做的是,将原来的三个元素转化成int32_t类型。并且将转化后的元素放置到正确的位上,并且需要维持底层数组的有序性。

        首先,因为元素3在1,2,3,65535四个元素中排第三。所以它被移动到contents数组的索引2的位置上,也就是数组64位至95位的空间内。

         接着,因为元素2在1,2,3,65535四个元素中排第二。所以它被移动到contents数组的索引1的位置上,也就是数组32位至63位的空间内。

        之后, 因为元素1在1,2,3,65535四个元素中排第一。所以它被移动到contents数组的索引0的位置上,也就是数组0位至31位的空间内。

        然后, 因为元素65535在1,2,3,65535四个元素中排第四。所以它被移动到contents数组的索引3的位置上,也就是数组96位至127位的空间内。

        最后,程序将encoding属性值从INTSET_ENC_INT16修改为INTSET_ENC_INT32,并将length属性值从3修改为4。

         因为每次向整数集合中添加新元素可能会引起升级,每次升级都需要对底层数组中已有元素进行类型转换,所以向整数集合添加新元素的时间复杂度为O(N)。

升级后新元素的摆放位置:

        因为引发升级的新元素的长度总是比整数集合现有所有元素的长度都大。所以这个新元素要么大于所有现有元素,要么小于所有现有元素。

        在新元素小于所有现有元素的情况下,新元素会被放置在底层数组的最开头(索引为0)

        在新元素大于所有现有元素的情况下,新元素会被放置在底层数组的最末尾(索引为length-1)

        1.3 升级的好处

        整数集合的升级策略有两个好处,一个是提升整数集合的灵活性,二是尽可能地节约内存。

  • 提升灵活性

        因为C语言是静态类型语言,为了避免类型错误,我们一般不会将两种不同类型地值放在同一个数据结构里面。例如:我们只会用int16_t类型地数组来保存int16_t类型的值,只使用int32_t类型的数组来保存int32_t类型的值。

        因为整数集合可以通过自动升级底层数组来适应新元素,我们可以随意将int16_t,int_32_t或int64_t类型的整数添加到集合中,而不用担心类型错误。

  • 节约内存

        让一个数组既能保存int16_t,int32_t或者int64_t类型的值最简单的做法就是直接使用int64_t类型的数组作为整数集合底层数组的实现。但是,这样一来,即使添加到整数集合里面的都是int16_t类型的值或者int32_t类型的值,数组都会需要用int64_t类型来保存,从而出现浪费内存的问题。

        而整数集合的做法既可以让集合同时保存三个类型的值,又可以确保升级操作只会在有需要的时候进行,这样实现尽可能地节约内存。

            1.4 降级

        整数集合不支持降级操作,一旦数组进行升级,编码就会一直保存升级后地状态。

        举个例子,即使我们将集合中唯一一个真正需要int64_t类型来保存地元素删除了,整数集合地编码(encoding)仍然会保持INTSET_ENC_INT64,底层数组地类型仍然是int64_t类型。

         1.5 整数集合API

 int intsetValidateIntegrity(const unsigned char *is, size_t size, int deep): 验证数据结构的完整性。当“deep”为0时,仅验证标头的完整性。当“deep”为1时,我们会确保没有重复或无序的记录。

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

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

相关文章

【漏洞复现】DPTech VPN存在任意文件读取漏洞

漏洞描述 DPtech是在网络、安全及应用交付领域集研发、生产、销售于一体的高科技企业。DPtech VPN智能安全网关是迪普科技面向广域互联应用场景推出的专业安全网关产品,集成了IPSec、SSL、L2TP、GRE等多种VPN技术,支持国密算法,实现分支机构…

redis的性能管理、主从复制和哨兵模式

一、redis的性能管理 redis的数据时缓存在内存中的 查看系统内存情况 info memory used_memory:853688 redis中数据占用的内存 used_memory_rss:10522624 redis向操作系统申请的内存 used_memory_peak:853688 redis使用内存的峰值 系统巡检:硬件巡检、数据库 n…

el-input限制输入整数等分析

文章目录 前言1、在 Vue 中,可以使用以下几种方式来限制 el-input 只能输入整数1.1 设置input 的 type为number1.2 使用inputmode1.3 使用自定义指令1.4 使用计算属性1.5 使用 onafterpaste ,onkeyup1.6 el-input-number 的precision属性 总结 前言 input 限制输入…

wvp分享视频访问页面

先登录查看视频 输入用户名密码登录 国标设备--点击通道 点击播放 点击复制 打开分享链接查看视频 直接在浏览器中打开 可以直接预览 原有标签退出登录 刷新分享的视频链接依然可以查看视频 iframe内嵌网页查看视频 获取iframe代码 点击复制 打开vscode,新建一…

有哪些好用的CFD软件?怎么选?

ANSYS Fluent和COMSOL Multiphysics以及OpenFOAM这3款CFD软件哪个好?cfd软件中哪款最实用?cfd软件有哪些?今天就给大家带来这几款CFD软件对比分析,一起来看看吧。 ANSYS Fluent ANSYS Fluent 是一种流行的计算流体动力学 (CFD) …

<MySQL> 什么是JDBC?如何使用JDBC进行编程?

目录 一、JDBC是什么? 二、JDBC常用接口和类 2.1 DataSource 2.2 Connection 2.3 Statement 2.4 ResultSet 三、JDBC的使用 3.1 获得数据库驱动包 3.2 添加到项目依赖 3.3 描述数据库服务器 3.4 建立数据库连接 3.6 执行SQL语句和接收返回数据 3.7 释放…

busybox制作根文件系统1

使用Busybox构建根文件系统 **环境:**Ubuntu 20.04 ​ 野火imx6ull pro开发板 根文件系统里都有什么内容 在构建根文件系统之前,先来看一下根文件系统里面大概都有些什么内容,以Ubuntu为例,根文件系统的目录名字为/&#xff0…

581. 最短无序连续子数组

581. 最短无序连续子数组 题目: 给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。 请你找出符合题意的 最短 子数组,并输出它的长度。 示例&…

数字化非遗之光:十八数藏的文化保护之道

在当今数字化的时代,文化传承正经历着一场前所未有的转变,而十八数藏以其独特的方式成为数字化非遗的典范。这个项目不仅仅是数字技术的应用,更是一种文化的使命,一道保护非物质文化遗产的光芒。 十八数藏以数字化的手段保护非遗&…

五金零件经营小程序商城的效果如何

五金零件无论批发还是零售都有很高的需求度,传统消费者往往是线下门店寻找购买,但如今更多的客户选择线上消费,而商家们也选择线上开店拓展更广的客源及生意增长。 除了第三方平台进驻外,私域开店对商家来说也是一种方式。微信场…

如何用惯性动作捕捉系统,快速创建数字人三维动画?

在动画制作领域,惯性动作捕捉技术已经逐渐成为一种重要的制作手段。通过动捕设备能够将动捕演员真实的动作转化为数字数据,然后在动画中再现这些动作。为了创造出逼真、流畅的数字人动画,惯性动作捕捉系统成为了一大工具。 根据采集方式的不…

Vulnhub 解决虚拟机网络问题

前言: 有的时候,我们从vulnhub官网下载ovf文件导入到虚拟机后,使用扫描器扫描存活的时候发现扫不到靶机的IP,这是因为虚拟机的网卡配置有问题。我们需要进安全模式修改一些配置。 1. 在虚拟机开机的时候按一下上下键,让…

Wagtail-基于Python Django的内容管理系统CMS如何实现公网访问

Wagtail-基于Python Django的内容管理系统CMS实现公网访问 文章目录 Wagtail-基于Python Django的内容管理系统CMS实现公网访问前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 前言 Wagtail是一个…

代码随想录二刷 | 链表 |链表相交

代码随想录二刷 | 链表 |链表相交 题目描述解题思路 & 代码实现 题目描述 160.链表相交 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。 题目数据 保…

万界星空科技QMS质量管理系统功能

QMS质量管理系统结合质量决策、综合质量管理、过程质量控制三个层次要素,帮助企业实现产品全寿命周期质量数据的及时、灵活、准确和全面采集。 通过质量管理软件能够实现质量数据科学处理和应用,包括数据的系统化组织、结构化存贮、便捷式查询、定制化统…

什么是搜索相关性?AI如何驱动搜索相关性?

训练数据驱动机器学习,机器学习促进丰富的人机交互体验。在快速迭代的互联网时代,我们不断被各种广告铺盖,甚至经常细思极恐,“天呐,小红书怎么知道我面膜没了。”这都是算法和机器学习的鬼斧神工洞察着用户的搜索意图…

低代码:数字化转型趋势下的快速开发方式

目录 一、前言 二、低代码是什么? 三、低代码如何提高生产力 开发工具JNPF介绍 产品分析 1可视化应用开发 2流程管理 3整个平台源码合作 四、小结 一、前言 通常,开发一个大型的企业级系统,公司往往需要大量的人力做支持后盾,如需…

时态图根据时间轴动态播放热力图

效果图如下&#xff1a; <!DOCTYPE html> <html><head><title>时态图</title><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><!-- 引入样式 --&g…

【高级网络程序设计】Week3-2 Servlet

一、 What are servlets? 1. 定义 &#xff08;1&#xff09;Servlets are Java’s answer to CGI&#xff1a; programs that run on a web server acting as middle layer between HTTP request and databases or other applications.Used for client requests that cann…