TL;DR
数据结构 | 重点 | 难点 |
---|---|---|
跳表 | 跳表/节点 结构体,查找复杂度 | 节点的插入/删除 |
hashset | 结构体 | 动态扩缩容,key冲突overflow,动态refresh机制 |
intset | 使用场景 ,结构体 | encoding更新 |
ziplist | 使用场景,结构体 | 连锁更新场景复杂度 |
sds | string,emstr结构体,扩容/缩容 | float/int-string转换 |
object | 结构体 | 编码转换,类型检查与命令多态,GC与对象共享 |
跳表(skiplist)
两个结构:
zskiplist: 跳表结构体,记录头尾节点head/tail,长度len,最大层数level。
zskiplist_node: 跳表节点结构体,记录当前节点的层数、上一个节点BW(所以这是一个双向链表),当前节点的score,每一个节点最多有level个指向下一个节点的指针(当然可以比这个量少)
下图每一列都可以认为是一个zskiplist_node,找到73需要21 - 62 - 70 - 73三次即可
hashset
intset
intset是set的健的底层实现,顾名思义是int的set,包括int编码(int16,int64),长度,实际的int数组
encoding=INTSET_ENC_INT16,length=5时,content占字节 165 = 80 B
encoding=INTSET_ENC_INT64,length=4时,content占字节 644 = 256 B
如果往encoding=INTSET_ENC_INT16的intset添加int64,会导致intset的encoding升级INTSET_ENC_INT64,造成content变为4倍;但是删掉这个int64后,encoding不会变回去
ziplist
ziplist是list键/hash键的实现(value是int/短string时),创建之后就是只读不写的结构体了
包括zlbytes 占字节数,zltail 尾节点offset,zllen 节点数,zlend 结尾
连锁更新 O(N^2): 在节点len<254链表头插入节点len>254的节点,造成所有节点的previous_entry_length从1B升级到2B
字符串SDS
free 可用空间,len 分配空间,buf 实际的char数组,用’\0’结尾
对象
主要是type(什么)、encoding(编码方式)、ptr(指向数据结构的指针)
redisstring、list、hash、set、zset 5种对象,同样的对象,在不同的条件下编码方式会不一样,并且在满足特定条件的时候,编码方式会从占地方小的升级到占地方大的。
类型检查和命令多态
DEL, EXPIRE, TYPE,OBJECT 可以对所有key执行
对特定类型的命令也要兼容不同的编码方式,比如LLEN => ziplist.ziplistLen / linkedlist.listLength
GC与对象共享
使用引用计数的GC机制,共享对象不包括字符串对象(只有整数字符串对象共享)