• 原理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.底层采用二分查找方式来查询
  • 相关阅读:
    真香!宝藏学习方式还可以这样,家人们绝不能错过
    Nginx的请求处理流程
    【LeetCode动态规划#08】完全背包问题实战与分析(零钱兑换II--求组合、组合总和IV--求排列)
    UR机器人RTDE(Real-Time Data Exchange,实时数据交换)
    基于Java的校友录
    5. web信息收集(OWASP实战训练)
    Windows主机信息收集
    实践分享!GitLab CI/CD 快速入门
    408王道数据结构强化——应用题
    LeetCode·297.二叉树的序列化与反序列化·DFS·BFS
  • 原文地址:https://blog.csdn.net/weixin_46926189/article/details/134498925