redis 从0到1完整学习 (五):集合 IntSet 数据结构

news2024/12/26 20:59:23

文章目录

  • 1. 引言
  • 2. redis 源码下载
  • 3. IntSet 数据结构
  • 4. 参考


1. 引言

前情提要:
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
本文主要结合源码来介绍 Redis IntSet 的数据结构

2. redis 源码下载

Redis 源码可以点击这里下载,方便查看其中定义的一些数据结构。
在这里插入图片描述

3. IntSet 数据结构

Redis 的 IntSet 是一个整数 set 数据结构,用于存储一系列整数值。它具有以下特点:

  • 有序性:IntSet 中的元素按照升序排列。
  • 唯一性:IntSet 中的元素是唯一的,不会出现重复的值。
  • 空间效率:IntSet 使用紧凑的存储方式,元素之间没有额外的空间开销。

Redis 的 IntSet 数据结构常用于需要存储和快速查找整数集合的场景。它提供了一组操作命令,可以对 IntSet 进行插入、删除、查找等操作。
在这里插入图片描述
encoding 表示编码方式,支持16位、32位、64位整数;
length 表示元素的个数;
contents 整数数组,保存数据。

下面从源码来分析,Intset 是如何自动升级编码方式到合适的大小的:

// 插入到 IntSet 中
intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {
    // 获取当前值需对应的编码
    uint8_t valenc = _intsetValueEncoding(value);
    uint32_t pos;
    if (success) *success = 1;

    if (valenc > intrev32ifbe(is->encoding)) {
		// 如果超出了之前的编码,则需要调整之前的编码跟当前一致
        return intsetUpgradeAndAdd(is,value);
    } else {
		// 查找当前值应该放置的位置,如果返回1,表示已经存在一样的值
        if (intsetSearch(is,value,&pos)) {
            if (success) *success = 0; // 如果
            return is;
        }
		// 数组扩容 + 移动原先的元素
        is = intsetResize(is,intrev32ifbe(is->length)+1);
        if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);
    }
	// 插入新元素到指定位置
    _intsetSet(is,pos,value);
    // 元素长度+1
    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
    return is;
}

static intset *intsetUpgradeAndAdd(intset *is, int64_t value) {
    uint8_t curenc = intrev32ifbe(is->encoding);
    uint8_t newenc = _intsetValueEncoding(value);
    int length = intrev32ifbe(is->length);
    // 出现了新的编码,要么是数字太小了(负数),要么是数字太大(正数)
    int prepend = value < 0 ? 1 : 0;

    // 重设编码以及size
    is->encoding = intrev32ifbe(newenc);
    is = intsetResize(is,intrev32ifbe(is->length)+1);

	// 从后往前倒序将元素挪到指定位置
    while(length--)
        _intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));

   	// prepend=1表示为负数,最小的,应该放置到队首
    if (prepend)
        _intsetSet(is,0,value);
    else // prepend=0表示为正数,最大的,应该放置到队尾
        _intsetSet(is,intrev32ifbe(is->length),value);
    // 数组长度+1
    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
    return is;
}

// 计算 value 插入的位置 pos,同时返回0表示未找到一样的值,1表示找到一样的值
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
    int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
    int64_t cur = -1;

    /* The value can never be found when the set is empty */
    if (intrev32ifbe(is->length) == 0) {
        if (pos) *pos = 0;
        return 0;
    } else {
		// 比最大的还大,比最小的还小,则可以直接返回要插入的位置
        if (value > _intsetGet(is,max)) {
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        } else if (value < _intsetGet(is,0)) {
            if (pos) *pos = 0;
            return 0;
        }
    }
	// 常见的二分法找值
    while(max >= min) {
        mid = ((unsigned int)min + (unsigned int)max) >> 1;
        cur = _intsetGet(is,mid);
        if (value > cur) {
            min = mid+1;
        } else if (value < cur) {
            max = mid-1;
        } else {
            break;
        }
    }
	// 找到了,则返回1
    if (value == cur) {
        if (pos) *pos = mid;
        return 1;
    } else { // 没找到,返回要插入的地方
        if (pos) *pos = min;
        return 0;
    }
}

4. 参考

《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》

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

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

相关文章

JavaOOP篇----第十篇

系列文章目录 文章目录 系列文章目录前言一、构造方法能不能显式调用?二、什么是方法重载?三、构造方法能不能重写?能不能重载?四、内部类与静态内部类的区别?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,…

Springboot启动异常 OgnlException: sqlSelect [java.lang.NoSuchMethodError

完整的日志如下&#xff1a; Invocation of init method failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression ew ! null and ew.sqlSelect ! null. Cause…

协作机器人(Collaborative-Robot)安全碰撞的速度与接触力

协作机器人&#xff08;Collaborative-Robot&#xff09;的安全碰撞速度和接触力是一个非常重要的安全指标。在设计和使用协作机器人时&#xff0c;必须确保其与人类或其他物体的碰撞不会对人员造成伤害。 对于协作机器人的安全碰撞速度&#xff0c;一般会设定一个上限值&…

Excel排序怎么做?记好这些正确操作!

“我是个职场新手&#xff0c;对excel的使用还不是很熟悉。但是我需要处理一份文件。有朋友可以简单介绍一下excel排序的操作方法吗&#xff1f;” Excel作为一个实用的办公工具&#xff0c;给用户带来了很多的方便。在使用excel时&#xff0c;排序功能是比较重要且常用的。我们…

轴承故障诊断分类模型全家桶-最全教程

Python轴承故障诊断 (一)短时傅里叶变换STFT-CSDN博客 Python轴承故障诊断 (二)连续小波变换CWT-CSDN博客 Python轴承故障诊断 (三)经验模态分解EMD-CSDN博客 Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客 Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客 Pytorch-Trans…

打造明厨亮灶工程,需要哪些AI视频智能算法助力?

旭帆科技AI智能监控可以通过摄像头、传感器和数据处理等技术手段&#xff0c;实时监测厨房人员着装、行为与烟火等&#xff0c;对厨房实时监控进行分析与记录&#xff0c;从而实现明厨亮灶场景的搭建&#xff0c;保障食品安全和服务质量。 1、烟火识别 对于后厨来说&#xff0…

搭建动态网站之——基于Redhat8.6搭建Discuz论坛

目录 一、动态网站与静态网站区别 1、提供用户互动接口的动态网站 2、搭建动态网站的需求&#xff1a; 二、搭建步骤 第一步&#xff1a;www服务器配置 第二步;编辑网页文件 第三步&#xff1a;使用xftp 将Discuz包传到/discuz解压 1、将Discuz包移动到/discuz 2、解压…

双燃料发动机,预计2025年市场规模将达到39亿美元

双燃料发动机是一种可以使用两种不同类型的燃料&#xff08;通常是天然气和柴油&#xff09;运行的发动机&#xff0c;具有更大的灵活性和更低的排放。近年来&#xff0c;在对更清洁、更高效能源的需求不断增长的推动下&#xff0c;双燃料发动机市场增长迅速。 全球市场&#x…

End-to-End Object Detection with Transformers(2020)

文章目录 AbstractIntroductionThe DETR modelObject detection set prediction loss二元匹配匈牙利损失如下Bounding box loss DETR architecture Conclusion hh 源代码 Abstract 我们提出了一种将目标检测视为直接集预测问题的新方法。我们的方法简化了检测管道&#xff0c;…

VUE中的index.html、App.vue和main.js的关系

VUE中的index.html、App.vue和main.js的关系&#xff0c;个人理解。 javascriptCopy code import Vue from vue; import App from ./App.vue;new Vue({render: h > h(App), }).$mount(#app);

【工具与中间件】通过飞书应用操作云文档

文章目录 前言1. 准备工作1.1 创建应用1.2 创建文件夹 2. 测试租户/个人版实践2.1 权限配置2.2 控制台调试2.3 协作文档添加应用2.4 CRUD2.4.1 根据文档描述选择token并生成2.4.2 新增多维表格数据API2.4.3 删除多维表格数据API2.4.4 查询多维表格数据API2.4.5 修改多维表格数据…

CentOS7 安装 DockerCompose

目录 一、安装Docker 二、安装步骤 2.1 卸载 2.2 安装docker 2.3 启动docker 2.4 配置镜像加速器 一、安装Docker Docker 分为 CE 和 EE 两大版本。 CE 即社区版(免费&#xff0c;支持周期7个月)EE 即企业版强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月…

java连接PRINTRONIX T8000打印机打印标签及常见打印错误说明

需要注意的点&#xff1a;数据拼接时一定要在数据两边加上双引号&#xff0c;否则打印出来的东西会报错&#xff01;&#xff01;&#xff01; package com.tscsdk;import java.io.IOException; import java.net.Socket; import java.text.SimpleDateFormat; import java.util…

速度超快的单图像生成3D目标方案,创新的One-2-3-45++来了!

论文链接&#xff1a; https://arxiv.org/pdf/2311.07885 github链接&#xff1a; https://sudo-ai-3d.github.io/One2345plus_page/ Demo链接&#xff1a; https://www.sudo.ai/3dgen 最近在开放世界的3D目标生成方面取得了显著的进展&#xff0c;图像到3D的方法&#xff0c…

Datawhale聪明办法学Python(task6字符串)及作业题解版

一、课程基本结构 课程开源地址&#xff1a; 课程进度列表 - 聪明办法学 Python 第二版 章节结构&#xff1a; Chapter 0 安装 InstallationChapter 1 启航 Getting StartedChapter 2 数据类型和操作 Data Types and OperatorsChapter 3 变量与函数 Variables and Functions…

在雷电模拟器中安装apk包使用charles抓包详细教程

背景 由于手头没有多余的平板&#xff0c;所以用模拟器来安装应用进行测试&#xff0c;有时候想要知道是前端问题还是后端问题&#xff0c;需要安装charles来进行抓包&#xff1b; 最终效果 模拟器上浏览应用&#xff0c;能抓到应用数据&#xff1b; 具体步骤 模拟器开启ro…

达梦兼容MySQL问题

问题 客户开发商 反馈 两台达梦数据库 执行相同SQL&#xff0c; 100.90.34.131上的 SQL语法 不支持。反馈是版本低导致的 分析 版本 100.90.34.131 10.74.28.22 发现 两个数据库大版本 一致&#xff0c;排除 版本原因。 开发环境 开发商 使用 10.74.28.22 的达梦。使用的是 …

MySQL增删改查(增加)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f649; 内容推荐:MySQL数据库和表操作&#x1f649; &#x1f439;今日诗词:父兵诛卓起长沙,直取江东作帝家&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&…

基于Java SSM框架实现咖啡馆管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现咖啡馆管理系统演示 摘要 2021是网络科技的时代 &#xff0c;众多的软件被开发出来&#xff0c;给客户带来了很大的选择余地&#xff0c;而且客户越来越追求更个性的需求。在这种时代背景下&#xff0c;客户对咖啡馆管理系统越来越重视&#xff0c;使更好…

使用terraform 来创建GCP的instance template 和基于它的vm

本人在上一篇的文章中已经介绍了如何去创建 google cloud的 vm 的image 和 instance template了 url&#xff1a; 快速构建自定义配置好的VM - 使用GCP instance-template 和 custom-image 但是里面的操作是基于gcloud CLI的。 在实际项目上&#xff0c; 我们对google cloud …