2.redis学习笔记:redis List底层数据实现(通用双端链表)

本文深入探讨了redis List数据结构的底层实现,重点在于双端链表。除了作为List的基础,双端链表还在事务、服务器、订阅/发送模块和事件模块等多个内部组件中发挥作用。redis的双端链表实现包含控制信息和链表节点信息,接口定义和实现位于src/adlist.c和src/adlist.h。虽然迭代器设计相对不那么优雅,但通过宏封装的指针操作提供了便利。文章最后简要总结,强调了redis通用双端链表设计的简洁性和灵活性。
摘要由CSDN通过智能技术生成

redis List底层数据实现


redis列表使用两种数据结构左为底层实现:
1.双端链表
2.压缩列表

今天我们来介绍redis中的双端链表,在前边的数据结构章节中已经介绍了通用双端链表的实现,在redis数据库中,双端链表还被很多内部模块所应用:
1.事务模块使用双端链表依序保存输入的命令;
2.服务器模块使用双端链表来保存多个客户端;
3.订阅/发送模块使用双端链表来保存订阅模式的多个客户端;
4.事件模块使用双端链表来保存时间事件(time event);

在redis的双端链表中,数据结构可以分为两个部分,一个是控制信息,一个是链表节点信息

关于redis双端链表的定义和实现在其根目录src/adlist.csrc/adlist.h上进行定义和实现。

//链表控制信息
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;
//链表节点信息
typedef struct listNode {
    struct listNode *prev;    //前驱节点
    struct listNode *next;    //后继节点
    void *value;              //数据域
} listNode;

//迭代器的迭代方向
#define AL_START_HEAD 0
#define AL_START_TAIL 1

值的一提的是链表的遍历操作采用的是迭代器操作,关于迭代器的定义如下所示:

//迭代器定义
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

不过比较其他开源库的迭代器设计,redis的迭代器设计并不算优雅,在博客<5.数据结构之通用动态数组>章节中,我们介绍了acl库中迭代器的操作,有兴趣的同学可以参考一下。

redis把指针的操作封装成了宏的类型,方便了程序员的使用,不过如果你习惯指针写法也可以采用指针的方式:

//宏定义操作
#define listLength(l) ((l)->len)
#define listFirst(l) ((l)->head)
#define listLast(l) ((l)->tail)
#define listPrevNode(n) ((n)->prev)
#define listNextNode(n) ((n)->next)
#define listNodeValue(n) ((n)->value)

#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))

#define listGetDupMethod(l) ((l)->dup)
#define listGetFree(l) ((l)->free)
#define listGetMatchMethod(l) ((l)->match)

redis通用双端链表接口

//接口声明
list *listCreate(void)                        ;    //链表的创建
void listRelease(list *list)                  ;    //链表的释放
list *listAddNodeHead(list *list, void *value);    //链表的头部添加
list *listAddNodeTail(list *list, void *value);    //链表的尾部添加
list *listInsertNode(list *list, listNode *old_node, void *value, int after);    //链表的节点插入
void     listDelNode(list *list, listNode *node)        ;    //链表节点删除
listIter *listGetIterator(list *list, int direction)    ;    //初始化链表迭代器(可以通过direction调整初始化方向,头部或者尾部)
listNode *listNext(listIter *iter)                      ;    //链表的下一个节点(有direction确定是向前遍历还是向后遍历)
void     listReleaseIterator(listIter *iter)            ;    //链表迭代器的释放
list     *listDup(list *orig)                           ;    //链表的拷贝
listNode *listSearchKey(list *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值