关于redis:Redis原码阅读intset100

5次阅读

共计 1262 个字符,预计需要花费 4 分钟才能阅读完成。

整数 (intset)

整数汇合是汇合键的底层实现之一,当一个汇合只蕴含整数元素,并且元素数量不多时,就会用它

整数汇合时 Redis 用于保留数值的,它能够保留 int16_t、int32_t、nt64_t

别离对应 short int long

insert.h

typedef struct intset {
    
    // 编码方式
    uint32_t encoding;

    // 汇合蕴含的元素数量
    uint32_t length;

    // 保留元素的数组
    int8_t contents[];} intset;

/*
 * intset 的编码方式
 */
#define INTSET_ENC_INT16 (sizeof(int16_t))
#define INTSET_ENC_INT32 (sizeof(int32_t))
#define INTSET_ENC_INT64 (sizeof(int64_t)

整数汇合的每个元素都是 contents 数组的一个数组项, 它是从小到大排列的,并且不蕴含反复。

你会发现这里的 contents 是 int8_t 也就是 char、然而实际上 contents 不保留任何的 char、contents 数组真正类型却决与 encoding 属性的值。

  1. 如果 encoding 为 INTSET_ENC_INT16、那么 contents 就是一个 int16_t 类型的数组,short(最小值 -32768、最大值 32767)
  2. 如果 encoding 为 INTSET_ENC_INT32、那么 contents 就是一个 int32_t 类型的数组,int(最小值 -2147483648、最大值 2147483647)
  3. 如果 encoding 为 INTSET_ENC_INT64、那么 contents 就是一个 int64_t 类型的数组,long(太多了)

降级

如果你向一个 int 类型的数组中,插入了一个 long 怎么解决?降级!!!

1、更具新类型的元素,扩大底层数组空间

2、将底层数组现有所有元素都转换为与新元素雷同的类型,而后进行一个排序,因为 contents 是有序不反复的

3、最初才是将新元素增加进去

 原数组【1】,【2】,【3】int16_t   16*3=48
插入 65535 int32_t
1、重新分配空间大小   32*4=128  但此时之前的数据地位不变,而是在前面增加空间 

2、上面就是将转换后元素放到正确的地位,并且要放弃有序性不变
先挪动 3 到    32*2 ~~~ 32*3-1   64 ~~ 95  

 因为 3 的地位换了, 所有会有肯定的空间空进去 48-63
之后同样的情理挪动 1 和 2
最初剩下的地位就是留给新元素的
将 encoding 从 int16_t 变为 int32_t

每次向整数汇合增加元素都可能引起降级,所有增加时 O(N)

元素如果很小比方 -12145641 会呈现在头部,元素很大 1231564 会呈现在尾部。

这样的作法就时节约内存,有须要才会降级

整数的汇合是不反对降级操作的,一旦降级,encoding 就不可能变小了

所有这里就呈现一个问题,如果一个数组 100 个元素,有 99 个 int16,一个 int32,那么数组类型就会降级为 int32 这也时一种节约,这能不能想方法解决呢?

正文完
 0