• 原理Redis-IntSet


    IntSet


    IntSet是Redis中set集合的一种实现方式,基于整数数组来实现,并且具备长度可变、有序等特征。

    结构如下:

    typedef struct intset {
        uint32_t encoding; /* 编码方式,支持存放16位、32位、64位整数*/
        uint32_t length; /* 元素个数 */
        int8_t contents[]; /* 整数数组,保存集合数据*/
    } intset;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其中的encoding包含三种模式,表示存储的整数大小不同:

    /* Note that these encodings are ordered, so:
     * INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */
    #define INTSET_ENC_INT16 (sizeof(int16_t)) /* 2字节整数,范围类似java的short*/
    #define INTSET_ENC_INT32 (sizeof(int32_t)) /* 4字节整数,范围类似java的int */
    #define INTSET_ENC_INT64 (sizeof(int64_t)) /* 8字节整数,范围类似java的long */
    
    • 1
    • 2
    • 3
    • 4
    • 5

    为了方便查找,Redis会将intset中所有的整数按照升序依次保存在contents数组中,结构如图:

    在这里插入图片描述

    现在,数组中每个数字都在int16_t的范围内,因此采用的编码方式是INTSET_ENC_INT16,每部分占用的字节大小为:

    • encoding:4字节
    • length:4字节
    • contents:2字节 * 3 = 6字节

    IntSet升级

    现在,假设有一个intset,元素为{5,10,20},采用的编码是INTSET_ENC_INT16,则每个整数占2字节:

    在这里插入图片描述

    我们向该其中添加一个数字:50000,这个数字超出了int16_t的范围,intset会自动升级编码方式到合适的大小。以当前案例来说流程如下:

    • 1.升级编码为INTSET_ENC_INT32, 每个整数占4字节,并按照新的编码方式及元素个数扩容数组

    • 2.倒序依次将数组中的元素拷贝到扩容后的正确位置

    • 3.将待添加的元素放入数组末尾

    • 4.最后,将inset的encoding属性改为INTSET_ENC_INT32,将length属性改为4

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    Intset可以看做是特殊的整数数组,具备一些特点:

    • 1.Redis会确保Intset中的元素唯一、有序
    • 2.具备类型升级机制,可以节省内存空间
    • 3.底层采用二分查找方式来查询
  • 相关阅读:
    电子眼与无人机在城市安防中的协同应用研究
    深入理解前端缓存
    Gartner权威报告解读:探究应用可观测性的发展
    SpringMVC---SSM整合&&异常处理&&拦截器
    UCloud 对象存储使用
    【仿牛客网笔记】 Spring Boot进阶,开发社区核心功能-事务管理
    探究SpringWeb对于请求的处理过程
    JavaScript:实现AvlTree树算法(附完整源码)
    【 Maven 】花式玩法之多模块项目
    拓扑排序算法
  • 原文地址:https://blog.csdn.net/weixin_46926189/article/details/134498925