0
点赞
收藏
分享

微信扫一扫

Redis整数集合的实现


参考链接:



-- 《Redis设计与实现》


-- 结构说明:​​https://redissrc.readthedocs.io/en/latest/compress-datastruct/intset.html​​


intset.c



数据结构概述说明:



- 是集合的底层实现之一



- 底层实现是数组(连续的内存结构),有序、无重复



- 整数集合类型可升级(16位->32位->64位),不可降级,可提升灵活性,尽可能节省内存



其核心结构源码如下: 


typedef struct intset {// 整数集合


uint32_t encoding;// 编码方式:16位(-32768~32767)、32位(-2147483648~2147483647)、64位(-9223372036854775808~9223372036854775807)


uint32_t length;// 集合元素数量


int8_t contents[];// 保存数据的数组


} intset;


 



下面我们大概说说核心方法的执行方式(具体看gitee源码解析,链接: ​​https://gitee.com/lidishan/redis-source-code-analysis/blob/master/src/intset.c​​



1 根据编码和pos偏移量获取对应元素(函数:_intsetGetEncoded)



根据编码方式和偏移量获取指定元素



2 调整整数集合内存空间大小(函数:intsetResize)



根据传值的编码和长度计算调整分配新的内存大小



3 在集合中查找对应的值(函数:intsetSearch)



 底层数组是有序、无重复的,所以用二分查找法来查数据



4 找出整型集合中的元素(函数:intsetFind)



如果查找的值编码 小于等于 整型集合编码 并且 能搜到到值在里面,就返回存在



5 插入一个其他编码数据,判断是否需要升级并添加(函数:intsetUpgradeAndAdd)



如果判断需要升级,就进行升级,然后添加



-- 整数集合具体是怎么升级?(会降级吗?不会,升级了就不会降级了)



1 假设一开始如下



- 编码:16位



- length:3



所以总位数为48位,即0~47



 



2 后来有一个超过16位编码的数字进来了,这时候进行扩容



- 编码:32位



- length:4



所以总位数为128位,即0~127



分配过程是先把第三个元素分配到64~95位区间,第二个元素分配到32~63位区间,第一个元素分配到0~31位区间,然后将新增元素分配到96~127位空间



备注:当前新增的元素因为由于是升级,所以要么是大于当前元素最大值,放在最后一个位置,要是是小于最小,放在0位置。



6 插入一个编码元素(函数:intsetAdd)



判断编码是否需要升级,需要就调用intsetUpgradeAndAdd。不需要就调用intsetSearch查找是否存在,不存在就新增,存在就直接



7 删除集合中元素(函数:intsetRemove)



小于等于整数集合编码



其他自己看gitee~~~~~~~~~~~



 



 

举报

相关推荐

0 条评论