|
跳跃表:
- typedef struct zskiplist {
- // 表头节点和表尾节点
- struct zskiplistNode *header, *tail;
- // 表中节点的数目
- unsigned long length;
- // 表中层数最大的节点的层数
- int level;
- } zskiplist;
它有几个观念:
4.2.1 层(level[])
层,也就是level[]字段,层的数目越多,会见节点速率越快。(由于它相等于是索引,层数越多,它索引就越细,就能很快找到索引值)
4.2.2 提高指针(forward)
层中有一个forward字段,用于从表头向表尾偏向会见。
4.2.3 跨度(span)
用于记录两个节点之间的间隔
4.2.4 退却指针(backward)
用于从表尾向表头偏向会见。
案例
- level0 1---------->5
- level1 1---->3---->5
- level2 1->2->3->4->5->6->7->8
好比我要找键为6的元素,在level0中直接定位到5,然后再今后走一个元素就找到了。
5. 整数荟萃(intset)
Reids对整数存储专门作了优化,intset就是redis用于生涯整数值的荟萃数据布局。当一个团结中只包括整数元素,redis就会用这个来存储。
- 127.0.0.1:6379[2]> sadd number 1 2 3 4 5 6
- (integer) 6
- 127.0.0.1:6379[2]> object encoding number
- "intset"
源码
intset数据布局:
- typedef struct intset {
- // 编码方法
- uint32_t encoding;
- // 荟萃包括的元素数目
- uint32_t length;
- // 生涯元素的数组
- int8_t contents[];
- } intset;
你必定很好奇编码方法(encoding)字段是干嘛用的呢?
- 假如 encoding 属性的值为 INTSET_ENC_INT16 , 那么 contents 就是一个 int16_t 范例的数组, 数组里的每个项都是一个 int16_t 范例的整数值 (最小值为 -32,768 ,最大值为 32,767 )。
- 假如 encoding 属性的值为 INTSET_ENC_INT32 , 那么 contents 就是一个 int32_t 范例的数组, 数组里的每个项都是一个 int32_t 范例的整数值 (最小值为 -2,147,483,648 ,最大值为 2,147,483,647 )。
- 假如 encoding 属性的值为 INTSET_ENC_INT64 , 那么 contents 就是一个 int64_t 范例的数组, 数组里的每个项都是一个 int64_t 范例的整数值 (最小值为 -9,223,372,036,854,775,808 ,最大值为 9,223,372,036,854,775,807 )。
说白了就是按照contents字段来判定用哪个int范例更好,也就是对int存储作了优化。
说到优化,那redis怎样作的呢?就涉及到了进级。
5.1 encoding进级
假如我们有个Int16范例的整数荟萃,此刻要将65535(int32)加进这个荟萃,int16是存储不下的,以是就要对整数荟萃举办进级。
它是怎么进级的呢(进程)?
若是此刻有2个int16的元素:1和2,新插手1个int32位的元素65535。
- 内存重分派,新插手后应该是3个元素,以是分派3*32-1=95位。
- 选择最大的数65535, 放到(95-32+1, 95)位这个内存段中,然后2放到(95-32-32+1+1, 95-32)位...依次类推。
进级的甜头是什么呢?
- 进步了整数荟萃的机动性。
- 尽也许节省内存(能用小的就不消大的)。
5.2 不支持降级
凭证上面的例子,假如我把65535又删掉,encoding会不会又回到Int16呢,谜底是不会的。官方没有给出来由,我认为应该是低落机能耗损吧,事实调解一次是O(N)的时刻伟大度。
6. 压缩列表(ziplist)
ziplist是redis为了节省内存而开拓的次序型数据布局。它被用在列表键和哈希键中。一样平常用于小数据存储。 (编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|