redis面试
数据结构(数据类型和数据结构:sds,zipList,quickList,skipList)
String
String:String是redis最根本的类型,一个key对应一个value。redis的string类型能够蕴含任何数据,比方jpg图片或者序列化的对象。string类型的值最大能存储512M。
String底层采纳了SDS设计。
SDS 结构设计:
len:SDS 所保留的字符串长度。
alloc:调配给字符数组的空间长度。批改字符串的时候,能够通过 alloc - len 计算 察看是否须要对空间扩容。
flags:数据类型。
buf[]:保留理论数据。
SDS理论益处:
1、SDS保留了数据长度,所以工夫复杂度就是O(1)。
2、空间预调配:SDS 被批改后,程序不仅会为 SDS 调配所须要的必须空间,还会调配额定的未应用空间。
3、惰性空间开释:当数据进行缩短操作,多余空间不会被回收,前面须要增长时,就不必额定去拓展空间。
List
List:是一个链表。一个key对应一个链表。先入先出,能够通过索引查问,不便新增和删除。
List底层数据结构又两种:
ZipList(压缩表):列表对象保留的所有字符串元素的长度都小于 64 字节并且保留的元素数量小于 512 个。
QuickList(疾速表):应用quicklist,它是一个双向链表,而且是一个基于ziplist的双向链表,quicklist的每个节点都是一个ziplist。
ZipList数据结构:
zlbytes,记录整个压缩列表占用对内存字节数;
zltail,记录压缩列表「尾部」节点间隔起始地址由多少字节,也就是列表尾的偏移量;
zllen,记录压缩列表蕴含的节点数量;
zlend,标记压缩列表的完结点,非凡值 OxFF(十进制255)。
Entry节点形成:
prevlen,记录了前一个节点的长度;
encoding,记录了以后节点理论数据的类型以及长度;
data,记录了以后节点的理论数据;
压缩表长处:将长度较短的数据用压缩链表,可能时内存更紧凑,节约内存。
为什么数据量较大和数据长度较长不适宜应用ZipList?
压缩表每个Entry的prevlen都记录了上一个节点的长度。
如果前一个节点的长度小于 254 字节,那么 prevlen 属性须要用 1 字节的空间来保留这个长度值;
如果前一个节点的长度大于等于 254 字节,那么 prevlen 属性须要用 5 字节的空间来保留这个长度值;
假如呈现了间断多个节点长度在250~253字节的数据,忽然新增了也该字节长度超过了254数据,会导致后续节点的prevlen都
从原来的1个字节拓展到4个字节,该节点就须要拓展空间。而后又导致了该节点的后续节点的prevlen长度变更......而后始终继续上来,这种就叫连锁更新。
quickList长处:
quicklist 是 ziplist 和 linkedlist 的混合体,它将 linkedlist 按段切分,每一段应用 ziplist 来紧凑存储,多个 ziplist 之间应用双向指针串接起来。
对于quickList曾经将ZipList分成了很多小片区,在小片区内产生连锁更新也是能够承受的。
Hash
相似Java的HashMap,数组+链表。
1:当Hash抵触时将具备雷同哈希值的数据链接起来,以便这些数据在表中依然能够被查问到。
2:当Hash抵触过多,导致数据链表太长就会产生rehash.
渐进式 Rehash:
为了防止 rehash 在数据迁徙过程中,因拷贝数据的耗时,影响 Redis 性能的状况,所以 Redis 采纳了渐进式 rehash,也就是将数据的迁徙的工作不再是一次性迁徙实现,而是分屡次迁徙。
渐进式 rehash 步骤如下:
给「哈希表 2」 调配空间;
在 rehash 进行期间,每次哈希表元素进行新增、删除、查找或者更新操作时,Redis 除了会执行对应的操作之外,还会程序将「哈希表 1 」中索引地位上的所有 key-value 迁徙到「哈希表 2」 上;
随着解决客户端发动的哈希表操作申请数量越多,最终会把「哈希表 1 」的所有 key-value 迁徙到「哈希表 2」,从而实现 rehash 操作。
rehash 触发条件:
负载因子 = 保留节点数/哈希表大小
当负载因子大于等于 1 ,并且 Redis 没有在执行 bgsave 命令或者 bgrewiteaof 命令,也就是没有执行 RDB 快照或没有进行 AOF 重写的时候,就会进行 rehash 操作。
当负载因子大于等于 5 时,此时阐明哈希抵触十分重大了,不论有没有有在执行 RDB 快照或 AOF 重写,都会强制进行 rehash 操作。