zoukankan      html  css  js  c++  java
  • Redis源码剖析(六)整数集合

    整数集合的实现

    整数集合(intset)是 Redis 用于保存整数值的集合抽象数据结构, 它可以保存类型为 int16_t 、 int32_t 或者 int64_t 的整数值, 并且保证集合中不会出现重复元素,同时底层数组中的元素按从小到大的顺序排列。

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

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

    以下展示了一个整数集合的示例:

    • encoding 属性的值为 INTSET_ENC_INT16 ,表示集合保存的都是 int16_t 类型的整数值。
    • length 属性的值为 5 , 表示整数集合包含五个元素。
    • contents 数组按从小到大的顺序保存着集合中的五个元素。

    升级

    升级分为以下几步进行:

    • 根据新元素的类型, 扩展底层数组的空间大小, 并为新元素分配空间。
    • 将底层数组的元素都转换成与新元素相同的类型, 并将类型转换后的元素放置到正确的位上。
    • 添加新元素到底层数组。
    static intset *intsetUpgradeAndAdd(intset *is, int64_t value) {
        
        // 当前的编码方式
        uint8_t curenc = intrev32ifbe(is->encoding);
    
        // 新值所需的编码方式
        uint8_t newenc = _intsetValueEncoding(value);
    
        // 当前集合的元素数量
        int length = intrev32ifbe(is->length);
    // 进行升级时,value 要么大于集合中的所有元素,要么小于集合中的所有元素
       int prepend = value < 0 ? 1 : 0; // 更新集合的编码方式 is->encoding = intrev32ifbe(newenc); // 根据新编码对集合(的底层数组)进行空间调整 is = intsetResize(is,intrev32ifbe(is->length)+1); //原先元素类型转换 while(length--) _intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc)); // 设置新值,根据 prepend 的值来决定是添加到数组头还是数组尾 if (prepend) _intsetSet(is,0,value); else _intsetSet(is,intrev32ifbe(is->length),value); // 更新整数集合的元素数量 is->length = intrev32ifbe(intrev32ifbe(is->length)+1); return is; }

    对于是否升级在添加元素时进行判断:

    intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {
    
        .......
    
        // 如果 value 的编码比整数集合现在的编码要大,进行升级
        if (valenc > intrev32ifbe(is->encoding)) {
    return intsetUpgradeAndAdd(is,value);
    }
    else { // 运行到这里,表示整数集合现有的编码方式适用于 value // 正常插入元素操作 }
      ....... }

    需要注意的是,整数集合不支持降级操作,一旦升级,编码会一直保持升级后的状态。

    整数集合的编码有以下几种:

    /*
     * intset 的编码方式
     */
    #define INTSET_ENC_INT16 (sizeof(int16_t))
    #define INTSET_ENC_INT32 (sizeof(int32_t))
    #define INTSET_ENC_INT64 (sizeof(int64_t))
  • 相关阅读:
    spring MVC的启动过程详解
    BeanFactory和applicationContext之间的区别
    spring的事务管理
    通用Mybatis的Crud搭建
    spring的IOC原理
    spring的AOP原理
    TortoiseSVN使用简介
    SVN简明教程
    POJO
    velocity 框架
  • 原文地址:https://www.cnblogs.com/lizhimin123/p/10154098.html
Copyright © 2011-2022 走看看