Redis 源码分析链表(list)

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: Redis 源码分析链表(list)

list 简介



redis 的链表没有什么特别之处,就是普通的双向链表 adlist.c/listNode。


typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;


多个 listNode 可以通过 prev 和 next 组成双端链表,如下所示:


image.png


说明:头节点和尾节点的 prev, next 分别指向 null。


可以通过 listNode 结构来组成链表,但使用 adlist.c/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 结构和三个 listNode 结构的链表


image.png


链表特征


  • 双端:链表节点带有 prev 和 next 指针, 获取某个节点的前置节点和后置节点的复杂度都是 O(1).


  • 无环:头节点的 prev 指针和表尾 next 指针都指向 null, 对链表的访问 null 为终点。


  • 带表头指针和表尾指针:通过 list 结构的 head 指针和 tail 指针,程序获取链表的表头节点和表尾节点的复杂度为 O(1).


  • 带链表长度计数器:程序使用 list 结构的 len 属性来对 list 持有的链表节点说开那个进行计数,程序获取链表中节点数量的负载度为 O(1).


  • 多态:链表节点使用 void* 指针来保存节点值,并且可以使用 list 结构中的 dup、free、match 三个属性为节点值来设置类型特定函数。所以链表可以用于保存各种不同类型的值。


迭代器



这里链表的迭代和数据是分配开的,采用的是类似迭代器模式,这个思想就是很多场景用到的 leveldb 中,大家可以搜索一下迭代器模式。


typedef struct listIter {
    listNode *next;
    int direction;
} listIter;
listIter *listGetIterator(list *list, int direction)
{
    listIter *iter;
    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
    if (direction == AL_START_HEAD)
        iter->next = list->head;
    else
        iter->next = list->tail;
    iter->direction = direction;
    return iter;
}


运用场景


  • 链表广泛用韵用实现 Redis 的各种功能,比如列表键、发布订阅、满查询、监视器等。


  • 通过为链表设置不同的类型特定函数,Redis 链表可以用于保存各种不同类型的值。


参考资料




  • 《Redis 设计与实现》黄健宏


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
15天前
|
存储 C++
C++的list-map链表与映射表
这篇教程介绍了C++中`list`链表和`map`映射表的基本使用。`list`链表可通过`push_front()`、`push_back()`、`pop_front()`和`pop_back()`进行元素的添加和删除,使用迭代器遍历并支持在任意位置插入或删除元素。`map`是一个键值对的集合,元素自动按键值排序,可使用下标操作符或`insert()`函数插入元素,通过迭代器遍历并修改键值对,同时提供`count()`方法统计键值出现次数。教程中包含多个示例代码以帮助理解和学习。
15 2
|
21天前
|
存储 NoSQL 安全
Redis第六弹-List列表-(相当于数组/顺序表)Lpush key element-一次可以插入多个元素(假如key已经存在,并且key对应的value并非是list,则会报错)
Redis第六弹-List列表-(相当于数组/顺序表)Lpush key element-一次可以插入多个元素(假如key已经存在,并且key对应的value并非是list,则会报错)
|
1月前
|
Java Redis
redis-学习笔记(Jedis list简单命令)
redis-学习笔记(Jedis list简单命令)
26 1
|
12天前
|
C++ 容器
【C++进阶】深入STL之list:高效双向链表的使用技巧
【C++进阶】深入STL之list:高效双向链表的使用技巧
15 0
|
21天前
|
存储 NoSQL Redis
Redis第四弹,Redis实现list时候做出的优化ziplist(压缩链表,元素少的情况),可更好的节省空间list——(内部编码:quicklist)Object encoding
Redis第四弹,Redis实现list时候做出的优化ziplist(压缩链表,元素少的情况),可更好的节省空间list——(内部编码:quicklist)Object encoding
|
27天前
|
存储 Python
链表(Linked List)详解
链表(Linked List)详解
17 0
|
1月前
|
存储 消息中间件 NoSQL
redis-学习笔记(list)
redis-学习笔记(list)
13 0
|
1天前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
7 1
|
6天前
|
存储 安全 Java
Java List详解
Java List详解
|
7天前
|
Java API
使用 Java 来实现两个 List 的差集操作
使用 Java 来实现两个 List 的差集操作
12 3