深入底层C源码 Redis核心设计原理( 八 )

【3】图示:

深入底层C源码 Redis核心设计原理

文章插图
【4】说明
1.通过控制ziplist 的大小 , 则很好的解决了超大ziplist 的拷贝情况下对性能的影响 。每次改动只需要针对具体的小段ziplist 进行操作 。
4)发现说明
【1】为什么不采用两个指针指向前后数据的方式 , 而是要采用复合的数据结构完成?
1.采用双指针的方式 , 那就必须赋予两个指针pre和next , 一个指针占据了8byte , 故两个指针就需要消耗16byte 。如果list存在大量数据 , 所以就需要消耗相当多的内存在指针方面(胖指针问题) 。
2.采用双链表的话数据可能会分的很散 , 因为指针就是采用不连续的存储空间来存储数据 , 容易造成大量的内存碎片 。
3.采用quicklist 和 ziplist 混合 , 达到减少指针消耗的空间 , 其次连续的存储空间读取起来效率高于不连续的存储空间 , 节省IO 。
4.通过控制ziplist 的大小 , 则很好的解决了超大ziplist 的拷贝情况下对性能的影响 。每次改动只需要针对具体的小段ziplist 进行操作 。
5.Hash 数据结构1)介绍
【1】Hash 数据结构底层实现为一个字典( dict ),也是RedisBb用来存储K-V的数据结构,当数据量比较小 , 或者单个元素比较小时 , 底层用ziplist存储 , 数据大小和元素数量阈值可以通过如下参数设置 。
hash-max-ziplist-entries512//ziplist 元素个数超过 512  , 将改为hashtable编码hash-max-ziplist-value64//单个元素大小超过 64 byte时 , 将改为hashtable编码2)发现说明
【1】为什么数据量小的时候采用ziplist存储?
1.ziplist使用紧凑的连续内存块顺序存储数据 , 在list或者hash结构中 , 未使用listNode(24字节)和dictEntry(24字节)结构体来存储元素项 , 因此会节省内存 。
2.ziplist结构元素访问采用的是后向遍历(从后往前) , 因此在hash中可将热点的key或者在list中将热点的元素项放在最后 , 可以提升性能 。
3.因为ziplist的内存结构中 , 仅仅只使用了额外的11个字节来存储ziplist的属性 , 另外很重要的是ziplist使用后向遍历 , 当list或者hash中的元素较多时 , 可以根据元素的冷热性调整元素存储顺序 。
4.而在dictht结构体中 , 存储属性需要32个字节 , 其中元素dictEntry也是每个占用24个字节 。
6.Set 数据结构1)介绍
【1】Set 为无序的 , 自动去重的集合数据类型 , Set 数据结构底层实现为一个value 为 null 的 字典( dict ),当数据可以用整形表示时 , Set集合将被编码为intset数据结构 。
//在配置文件中设置set-max-intset-entries 512// intset 能存储的最大元素个数 , 超过则用hashtable编码【2】两个条件任意满足时Set将用hashtable存储数据 。1 ,  元素个数大于 set-max-intset-entries , 2  ,  元素无法用整形表示 。
2)intset数据结构
//intset内部其实是一个数组(int8_t coentents[]数组) , 而且存储数据的时候是有序的 , 因为在查找数据的时候是通过二分查找来实现的 。typedef struct intset {uint32_t encoding;// 编码方式uint32_t length;// 集合包含的元素数量int8_t contents[];// 保存元素的数组} intset;3)set存储过程

经验总结扩展阅读