多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
`linkedlist`是一个双向列表,每个节点都会存储指向上一个节点和指向下一个节点的指针。`linkedlist`因为每个节点之间的空间是不连续的,所以可能会造成过多的内存空间碎片。 #### linkedlist 存储结构 链表中每一个节点都是一个`listNode`对象(源码`adlist.h`内),不过需要注意的是,列表中的`value`其实也是一个字符串对象,其它几种数据类型其内部最终也是会嵌套字符串对象,字符串对象也是唯一一种会被其它对象引用的基本类型: ~~~c typedef struct listNode { struct listNode *prev;//前一个节点 struct listNode *next;//后一个节点 void *value;//值(字符串对象) } listNode; ~~~ 然后会将其再进行封装成为一个`list`对象(源码`adlist.h`内): ~~~c typedef struct list { listNode *head;//头节点 listNode *tail;//尾节点 void *(*dup)(void *ptr);//节点值复制函数 void (*free)(void *ptr);//节点值释放函数 int (*match)(void *ptr, void *key);//节点值对比函数 unsigned long len;//节点数量 } list; ~~~ `Redis`中对`linkedlist`的访问是以`NULL`值为终点的,因为`head`节点的`prev`节点为`NULL`,`tail`节点的`next`节点也为`NULL`,所以从头节点开始遍历,当发现`tail`为`NULL`时,则可以认为已经到了列表末尾。 当我们设置一个列表对象时,在`Redis 3.2`版本之前我们可以得到如下存储示意图: ![](https://img.kancloud.cn/ef/22/ef22b74eb6d60d71aac4a1fa2d916e33_816x444.png)