uint8_t len;
uint8_t alloc;
unsigned char flags;
char buf[];
};
struct attribute ((packed)) sdshdr16 {
uint16_t len;
uint16_t alloc;
unsigned char flags;
char buf[];
};
struct attribute ((packed)) sdshdr32 {
uint32_t len;
uint32_t alloc;
unsigned char flags;
char buf[];
};
struct attribute ((packed)) sdshdr64 {
uint64_t len;
uint64_t alloc;
unsigned char flags;
char buf[];
};
除掉第一个结构体(已经弃用),sds具体类型的结构可以分为以下部分:
-
len:已使用的长度,即字符串的真实长度
-
alloc:除去标头和终止符(’\0’)后的长度
-
flags:低3位表示字符串类型,其余5位未使用(我暂时没发现redis在哪里使用过这个属性)
-
buf[]:存储字符数据
这里和老版本做一下对比,因为我手头只有4.x和5.x的版本,它们sds的实现是一致的,但是据其他人说sds之前的版本实现方式不同,有时间我会去下载下来看一下,其将字符串分为以下部分:
-
len:buf中已经占有的长度(表示此字符串的实际长度)
-
free:buf中未使用的缓冲区长度
-
buf[]:实际保存字符串数据的地方
redis同时写重写了大量的与sds类型相关的方法,那redis为什么要这么下功夫呢,有以下4个优点:
-
降低获取字符串长度的时间复杂度到O(1)
-
减少了修改字符串时的内存重分配次数
-
兼容c字符串的同时,提高了一些字符串工具方法的效率
-
二进制安全(数据写入的格式和读取的格式一致)
list
我们查看源文件可以看到有两个list,一个是ziplist,字面意是压缩列表,另一个是quicklist,字面意是快速列表,在redis中直接使用的是quicklist,但是我们先来看ziplist
ziplist
ziplist并不是一个类名,其结构是下面这样的: …
其中各部分代表的含义如下:
-
zlbytes:4个字节(32bits),表示ziplist占用的总字节数
-
zltail:4个字节(32bits),表示ziplist中最后一个节点在ziplist中的偏移字节数
-
entries:2个字节(16bits),表示ziplist中的元素数 entry:长度不定,表示ziplist中的数据
-
zlend:1个字节(8bits),表示结束标记,这个值固定为ff(255)
这些数据均为小端存储,所以可能有些人查看数据的二进制流与其含义对应不上,其实是因为读数据的方式错了
ziplist内部采取数据压缩的方式进行存储,压缩方式就不是重点了,我们仅从宏观来看,ziplist类似一个封装的数组,通过zltail可以方便地进行追加和删除尾部数据、使用entries可以方便地计算长度
但是其依然有数组的缺点,就是当插入和删除数据时会频繁地引起数据移动,所以就引出了quicklist数据类型
quicklist
其核心数据结构如下:
typedef struct quicklist {
quicklistNode *head;
quicklistNode *tail;
unsigned long count; /* ziplist所有节点的个数 */
unsigned long len; /* quicklistNode节点的个数 */
int fill : 16; /* 单个节点的填充因子 */
unsigned int compress : 16; /* 压缩端结点的深度 */
} quicklist;
我们可以明显地看出,quicklist是一个双向链表的结构,但是内部又涉及了ziplist,我们可以这么说,在宏观上,quicklist是一个双向链表,在微观上,每一个quicklist的节点都是一个ziplist
在redis.conf中,可以使用下面两个参数来进行优化:
-
list-max-ziplist-size:表示每个quicklistNode的字节大小。默认为2,表示8KB
-
list-compress-depth:表示quicklistNode节点是否要压缩。默认为0,表示不压缩
这种存储方式的优点和链表的优点一致,就是插入和删除的效率很高,而链表查询的效率又由ziplist来进行弥补,所以quicklist就成为了list数据结构的首选
hash
hash这种结构在redis的使用时最为常见,在redis中,hash这种结构有两种表示:zipmap和dict
zipmap
zipmap其格式形如下面这样: <zmlen><len>"foo"<len><free>"bar"<len>"hello"<len><free>"world"
各部分的含义如下:
-
zmlen:1个字节,表示zipmap的总字节数
-
len:1~5个字节,表示接下来存储的字符串长度
-
free:1个字节,是一个无符号的8位数,表示字符串后面的空闲未使用字节数,由于修改与键对应的值而产生
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
最后总结我的面试经验
2021年的金三银四一眨眼就到了,对于很多人来说是跳槽的好机会,大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。
另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。
BAT面试经验
实战系列:Spring全家桶+Redis等
其他相关的电子书:源码+调优
面试真题:
edis等**
[外链图片转存中…(img-WCaBrbur-1711177355818)]
其他相关的电子书:源码+调优
[外链图片转存中…(img-cLpIx4M4-1711177355819)]
面试真题:
[外链图片转存中…(img-TcEVDMcb-1711177355820)]
[外链图片转存中…(img-9kqHA9FF-1711177355820)]