redis源码剖析(2):基础数据结构ADLIST
目录
1、ADList概述
2、链表和链表节点定义
3、链表迭代器
4、总结
1、ADList概述
ADList(A generic doubly linked list)是 redis 自定义的一种双向链表,广泛运用于 redisClients 、 redisServer 、发布订阅、慢查询、监视器等(注:3.0及以前还会被运用于list
结构中,在3.2以后被quicklist
取代)。
链表是最常用的数据结构之一了,对于其算法和ADT就不做赘述,不了解的同学可以google、百度或者参考《数据结构:C语言版》等书籍。
2、链表和链表节点定义
每个链表节点都是用一个listNode
表示
typedef struct listNode { // 双向节点struct listNode *prev;struct listNode *next;void *value; // 空指针,可以被指向任何类型
} listNode;
在简单的链表定义中,只用节点结构就已经能够满足链表的需求了,但是 redis 通过list
结构体持有链表,使得链表操作更加方便、规范。
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长度
} list;
dup
为节点复制函数free
为节点释放函数match
为节点比较函数
通过这样的定义,adlist
有了以下优点:
- 双向:可以灵活的访问前置或者后置节点
list
头指针和尾指针:可以方便的获取头尾节点或者从头尾遍历查找len
:使获取list
由O(N)变为O(1)- 通过
void
实现多态:不同的实例化链表对象可以持有不同的值,其对应的3个操作函数也可以自定义,是不是有点interface
的感觉!
3、链表迭代器
除了双向链表的定义外,redis 还定义了一个迭代器,用于遍历链表:
typedef struct listIter { // 列表迭代器listNode *next;int direction; // 迭代器遍历方向
} listIter;
其中direction
用于标识迭代器的遍历方向:
#define AL_START_HEAD 0 // 从头遍历
#define AL_START_TAIL 1 // 从尾遍历
通过定义listIter
,redis 在需要遍历list
时,不需要再复制各种tmp值,只需要调用listIter
的遍历函数。 以listSearchKey
为例:
listNode *listSearchKey(list *list, void *key) // list查找key
{listIter iter;listNode *node;listRewind(list, &iter); // 初始化迭代器while((node = listNext(&iter)) != NULL) { // 迭代器遍历if (list->match) { // 如果定义了match函数if (list->match(node->value, key)) {return node;}} else { // 直接进行值比较if (key == node->value) {return node;}}}return NULL;
}
所有和遍历有关的行为都收敛到了listIter
中,list
就专注负责存储。
4、总结
- redis 的链表是双向无环的
ADList
持有链表的头尾节点指针,链表长度以及链表操作函数listNode
的值为void,可以保存任意类型的值- 通过实现不同的操作函数,
ADlist
可以保存各种不同类型的数据 - 迭代操作由专门的迭代器实现
其他一些api就不做深入解析了,ADList
相关的定义都在adlist.h
和adlist.c
文件中,如果感兴趣可以自行查看
redis源码剖析(2):基础数据结构ADLIST相关推荐
- redis源码剖析(3):基础数据结构dict
目录 1.dict概述 2.字典的定义 3.哈希算法 4.字典的初始化及新增键值对 4.1 字典初始化 4.2 新增键值对 5.rehash(重新散列)操作 5.1 rehash操作方式 5.2 re ...
- 【Redis源码剖析】 - Redis内置数据结构之压缩列表ziplist
在前面的一篇文章[Redis源码剖析] - Redis内置数据结构之双向链表中,我们介绍了Redis封装的一种"传统"双向链表list,分别使用prev.next指针来指向当前节点 ...
- 【Redis源码剖析】 - Redis持久化之RDB
原创作品,转载请标明:http://blog.csdn.net/xiejingfa/article/details/51553370 Redis源码剖析系列文章汇总:传送门 Redis是一个高效的内存 ...
- redis源码剖析(十五)——客户端思维导图整理
redis源码剖析(十五)--客户端执行逻辑结构整理 加载略慢
- Redis源码剖析和注释(十六)---- Redis输入输出的抽象(rio)
Redis源码剖析和注释(十六)---- Redis输入输出的抽象(rio) . https://blog.csdn.net/men_wen/article/details/71131550 Redi ...
- 【Redis源码剖析】 - Redis IO操作之rio
原创作品,转载请标明:http://blog.csdn.net/xiejingfa/article/details/51433696 Redis源码剖析系列文章汇总:传送门 Reids内部封装了一个I ...
- Redis源码剖析之GEO——Redis是如何高效检索地理位置的?
Redis GEO 用做存储地理位置信息,并对存储的信息进行操作.通过geo相关的命令,可以很容易在redis中存储和使用经纬度坐标信息.Redis中提供的Geo命令有如下几个: geoadd:添加经 ...
- Redis源码剖析之内存淘汰策略(Evict)
文章目录 何为Evict 如何Evict Redis中的Evict策略 源码剖析 LRU具体实现 LFU具体实现 LFU计数器增长 LFU计数器衰减 evict执行过程 evict何时执行 evict ...
- Redis源码分析:基础概念介绍与启动概述
Redis源码分析 基于Redis-5.0.4版本,进行基础的源码分析,主要就是分析一些平常使用过程中的内容.仅作为相关内容的学习记录,有关Redis源码学习阅读比较广泛的便是<Redis设计与 ...
- redis源码剖析(7):基础数据结构quicklist
目录 1.quicklist概述 2.quicklist源码分析 2.1 定义 2.2 push操作 2.3 节点压缩 3.总结 1.quicklist概述 quicklist是一个3.2版本之 ...
最新文章
- 今年端午节,想回家看看父母...
- [HAOI2008][BZOJ1042] 硬币购物
- ashx PHP文件 优劣,.NET_后缀为 ashx 与 axd 的文件区别浅析,唯一不同的地方是:axd扩展名 - phpStudy...
- linux 父子进程 资源_linux 父子进程 资源_实验4 Linux父子进程同步
- html分块时边距的设置,html – 文本节点后第一个块的边距(垂直空间)?
- PRML5-神经网络(1)
- Mail: JMail, System.Net.Mail, System.Web.Mail
- 【softmax分类】基于matlab梯度下降softmax回归minist数据分类【含Matlab源码 1645期】
- 242.有效的字母异位词
- 基于RV1126平台imx291分析 --- media部件注册 rkcif_mipi
- php支付接口要改动的参数,京东支付接口2.0PHP集成遇到的一些问题:所有参数必须是string!...
- 如何创建一个vue项目(详细步骤)
- iOS非常全的第三方库
- Docker安装ElasticSearch 版本7.6.2
- quickchm乱码问题
- 解决sqllite的'unable to open database file'错误
- phalapi可以依赖注入么_phalapi-进阶篇2(DI依赖注入和单例模式)
- XenDesktop7.15CU3 文件重定向Bug
- python音频转文字腾讯_使用Python三步完成文本到语音的转换
- 均值不等式中考_数学不等式解题技巧