打卡深入~《通俗易懂的Redis数据结构基础教程》|青训营笔记

150 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第四篇笔记

本文主要记录redis中基础的数据结构

1、string:sds字符串,一个可变的字符数组,而且获取长度是O(1)操作,扩容最多到512m

深入:在结构体中,string其实有种编码格式。

当存的是一个在long值范围内的数字时,string的编码格式并不是sds,而就是一个long。

而当string使用sds字符串时,也根据字符串的长度(32字节为边界)决定是将sds跟redisobject一起存还是分开存。存在一起的话访问速度更快,但是扩容的时候需要跟redisobject一起重新分配空间,反过来,分开存虽然访问慢了些,但是扩容时无需考虑redisobject。

2、list:在老版本,list是用的双向链表或压缩表,但节点数小于512个,且每个结点大小都小于64字节时,使用压缩列表,因为压缩列表在这种低数量的情况下,有着非常好的效率,但是一旦数量上升,效率就随着下降。

所以在高版本中,list用的数据结构改为了quicklist,quicklist其实还是双向链表,但是结点存的是一个压缩表,这样就兼顾了链表和压缩表的优点与一身了。

3、hash:hash的底层用的是hash表,在对象头结构体中,有两个hash表的指针,一个指向了正在使用的hash表,另一个是null,只有扩容时才会创建,用来做一个渐进式的rehash。补充一点的是,在数据量少时,hash用的也是压缩表,高版本改进后改名listpack。还有一点要提的是,hashmap有缩容机制!

4、set:set的底层用的是hashmap,但是如果元素都是整数,用的是一个叫整数集合的东西:底部是一个整形数组,至于是int16还是int32还是其它取决于数组中最长的那个

5、zset:zset用的底层结构是跳表,它其实是一个多层的链表,按权重进行排序。它能让查询变成O(logn),redis的层数是随机的,在0-1间取值,在0-0.25内就升一层。这里要补充的是,zset在数据量小的时,用的还是压缩表,现在改进的listpack

为什么怎么压缩表怎么受青睐呢?5个基本类型居然有3个使用到了它,而又为什么在在数量一多之后立马抛弃它?

压缩表使用的是连续的内存空间,很好的使用了cpu缓存,而且还可以针对不同长度的数据进行对应编码,节省内存开销。但是压缩表的查询其实是遍历,节点数量一旦变多,查询效率就变慢,而且一旦插入或更新某个节点时,就需要重新分配内存空间,甚至引起连锁更新。