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有了以下优点:

  1. 双向:可以灵活的访问前置或者后置节点
  2. list头指针和尾指针:可以方便的获取头尾节点或者从头尾遍历查找
  3. len:使获取listO(N)变为O(1)
  4. 通过void实现多态:不同的实例化链表对象可以持有不同的值,其对应的3个操作函数也可以自定义,是不是有点interface的感觉!

3、链表迭代器

除了双向链表的定义外,redis 还定义了一个迭代器,用于遍历链表:

typedef struct listIter {   // 列表迭代器
    listNode *next;
    int direction;  // 迭代器遍历方向
} listIter;

其中direction用于标识迭代器的遍历方向:

#define AL_START_HEAD 0     // 从头遍历
#define AL_START_TAIL 1     // 从尾遍历

通过定义listIterredis 在需要遍历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、总结

  1. redis 的链表是双向无环的
  2. ADList持有链表的头尾节点指针,链表长度以及链表操作函数
  3. listNode的值为void,可以保存任意类型的值
  4. 通过实现不同的操作函数,ADlist可以保存各种不同类型的数据
  5. 迭代操作由专门的迭代器实现

其他一些api就不做深入解析了,ADList相关的定义都在adlist.hadlist.c文件中,如果感兴趣可以自行查看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值