这块倒是跟HashMap一样是2
倍扩容
缩容
当hash表中元素被删除到元素个数小于数组长度的10%,就会去缩容。
是什么
类似于Java中的HashSet
,内部实现是一个特殊的字典,字典中所有的value都是null,常被用于去重功能。
底层采用了intset
整数集合和hashtable
字典两种方式来实现的,当满足如下两个条件的时候,采用整数集合实现,否则用哈希表。
-
集合中的
所有元素都为整数
-
集合中的
元素个数不大于 512
可以通过修改 set-max-intset-entries调整集合大小,默认512
set-max-inset-entries 512
其中hashtable
的key
为set
中元素的值,而value
为null
,inset
为可以理解为数组。
intset
sadd key6 1 2 3
3
debug object key6
Value at:0x7f21f2eaddd0 refcount:1 encoding:intset serializedlength:15 lru:13223640 lru_seconds_idle:7
hashtable
sadd key6 a b c
3
debug object key6
Value at:0x7f21f2eaddd0 refcount:1 encoding:hashtable serializedlength:13 lru:13223654 lru_seconds_idle:5
为什么
为什么要优先使用intset
整数集合?
-
intset
是非常紧凑的数据结构,占用的内存已经压缩的非常小了,可以提高内存的利用率。 -
查询方式一般采用二分查找法,实际查询复杂度也就在log(n).
-
intset
底层是连续的内存空间,对CPU高速缓存支持更友好,提高查询效率。
如何实现
typedef struct intset {
// 编码方式
uint32_t encoding;
// 集合包含的元素数量
uint32_t length;
// 保存元素的数组
int8_t contents[];
}
intset
底层实现为有序
,无重复数组
保存集合元素。 intset这个结构里的整数数组的类型可以是16位的,32位的,64位的。如果数组里所有的整数都是16位长度的,如果新加入一个32位的整数,那么整个16的数组将升级成一个32位的数组。升级可以提升intset的灵活性,又可以节约内存,但不可逆。
是什么
类似Java中的TreeMap
,用set
保证value一致性
,给每个value
一个score
属性代表排序权重。
zset
为有序,自动去重的集合数据类型,其底层实现为 ziplist
+ skiplist
跳跃表,当数据比较少的时候用ziplist编码结构存储,否则改为跳跃表。
默认按照score排序,score相同则按照元素字典序
同时满足以下两个条件采用ziplist存储:
-
有序集合保存的元素数量小于默认值128个
-
有序集合保存的所有元素的长度小于默认值64字节
可以通过修改redis.conf修改默认值
zset-max-ziplist-entries 128 #配置元素个数最多512个
zset-max-ziplist-value 64 #配置value最大为64字节
ziplist
zadd key7 1 a 2 b
2
debug object key7
Value at:0x7f21f2eade10 refcount:1 encoding:ziplist serializedlength:22 lru:13224623 lru_seconds_idle:6
skiplist
zadd key7 1 a 2 b67777777777777777777777777777777777777777777777777777777777777777777777777777777
1
debug object key7
Value at:0x7f21f2eade10 refcount:1 encoding:skiplist serializedlength:43 lru:13224690 lru_seconds_idle:2
怎么实现
ziplist,之前讲不过,zskiplist编码其实就是zset
typedef struct zset {
// 字典,键为成员,值为分值
// 用于支持 O(1) 复杂度的按成员取分值操作
dict *dict;
// 跳跃表,按分值排序成员
// 用于支持平均复杂度为 O(log N) 的按分值定位成员操作
// 以及范围操作
zskiplist *zsl;
}
typedef struct zskiplist {
// 表头节点和表尾节点
struct zskiplistNode *header, *tail;
// 表中节点的数量
unsigned long length;
// 表中层数最大的节点的层数
int level;
} zskiplist;
typedef struct zskiplistNode {
// 成员对象
robj *obj;
// 分值
double score;
// 后退指针
struct zskiplistNode *backward;
// 层
struct zskiplistLevel {
// 前进指针
struct zskiplistNode *forward;
// 跨度—前进指针所指向节点与当前节点的距离
unsigned int span;
} level[];
} zskiplistNode;
zskiplist编码
分为两部分,dict
+ zskiplist
,dict
和跳跃表
都存储数据,实际上 dict 和跳跃表最终使用指针都指向了同一份数据,即数据是被两部分共享的,dict结构,主要key是其集合元素,而value就是对应分值,而zkiplist作为跳跃表,按照分值排序,方便定位成员。
盗个图:
来源:https://juejin.cn/post/6863258283483807752
skiplist的查找时间复杂度是 O(log N),可以和平衡二叉树相当,但实现起来又比它简单。
为什么
这里redis为什么用跳表而不像Java的TreeMap
一样用红黑树呢?
对于这个问题,Redis的作者 @antirez 是怎么说的:
There are a few reasons:
1) They are not very memory intensive. It’s up to you basically. Changing parameters about the probability of a node to have a given number of levels will make then less memory intensive than btrees.
2) A sorted set is often target of many ZRANGE or ZREVRANGE operations, that is, traversing the skip list as a linked list. With this operation the cache locality of skip lists is at least as good as with other kind of balanced trees.
3) They are simpler to implement, debug, and so forth. For instance thanks to the skip list simplicity I received a patch (already in Redis master) with augmented skip lists implementing ZRANK in O(log(N)). It required little changes to the code.
简单概括下:
-
内存占用相比于树更少,跳跃表使用的指针比树更少,64位操作系统每个指针占用8字节
-
跳跃表范围查询支持更友好
-
算法实现难度上相比于树实现起来更简单
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
最后
本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们:
目录:
Java面试核心知识点
一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!
Java面试核心知识点
uf9aXKK3-1711200481714)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-9nejEY9v-1711200481715)]
最后
本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们:
目录:
[外链图片转存中…(img-8dfRKH7m-1711200481715)]
Java面试核心知识点
一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!
[外链图片转存中…(img-gfzygCRK-1711200481716)]
Java面试核心知识点