redis 从0到1完整学习 (十二):RedisObject 之 List 类型

2024-01-01 10:42:29


1. 引言

前情提要:
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
《redis 从0到1完整学习 (七):ZipList 数据结构》
《redis 从0到1完整学习 (八):QuickList 数据结构》
《redis 从0到1完整学习 (九):SkipList 数据结构》
《redis 从0到1完整学习 (十):RedisObject 数据结构》
《redis 从0到1完整学习 (十一):RedisObject 之 String 类型》

上一节整体讲了 RedisObject 的数据结构,能灵活地处理不同类型和大小的数据,本文主要介绍 RedisObject 是如何管理 List 类型的数据结构的。

2. redis 源码下载

Redis 源码可以点击这里下载,方便查看其中定义的一些数据结构。
在这里插入图片描述

3. redisObject 管理 List 类型的数据结构

3.1 redisObject 管理 List 类型

在 redis 3.2版本之后,采用 QuickList 来实现 List 数据结构。参考 《redis 从0到1完整学习 (八):QuickList 数据结构》我们回顾下 QuickList 数据结构:
在这里插入图片描述
那么我们看下 RedisObject 是怎么管理 List 类型的数据结构:
在这里插入图片描述

ptr 指向的是 QuickList 结构体,QuickList 结合 ZipList 保存着正常的 List 数据,是不是很简单!

3.2 List PUSH 源码

还记得 redis 的 List 用法吗?参考这里 redis 从0到1完整学习 (三):redis 数据结构 的 List 用法,我们在 List 可以用 push、pop 命令,例如:

LPUSH myqueue item1  
RPOP myqueue

那么我们看下 LPUSH 这些命令在源码是怎么实现的:

void lpushCommand(client *c) {
    pushGenericCommand(c,LIST_HEAD);
}

void rpushCommand(client *c) {
    pushGenericCommand(c,LIST_TAIL);
}

这里都指向了pushGenericCommand 方法,所以我们来看下 pushGenericCommand 关键部分,我这里看的是 v6.0.0 的源码,不同版本可能稍微有差异,但是主体逻辑差异不大:

void pushGenericCommand(client *c, int where) {
    int j, pushed = 0;
    // 根据key来找缓存中的redisObject。
    // 例如 LPUSH key v1 v2:对应的argv从0开始,也就是LPUSH对应的是argv[0],key对应的是argv[1],v1对应的是argv[2],依次类推
    robj *lobj = lookupKeyWrite(c->db,c->argv[1]);
	// 判断redisObject的type是否为List,不是List需要报错!
    if (lobj && lobj->type != OBJ_LIST) {
        addReply(c,shared.wrongtypeerr);
        return;
    }
   	// 从argv[2]开始,表示开始遍历value
    for (j = 2; j < c->argc; j++) {
    	// List不存在,则需要创建List,创建的QuickList
        if (!lobj) {
            lobj = createQuicklistObject();
            quicklistSetOptions(lobj->ptr, server.list_max_ziplist_size,
                                server.list_compress_depth);
            dbAdd(c->db,c->argv[1],lobj);
        }
        // 将value push到List里
        listTypePush(lobj,c->argv[j],where);
        pushed++;
    }
	...
}

关键的部分的逻辑都在上面注解了,其实很好理解!

4. 参考

《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
《redis 从0到1完整学习 (七):ZipList 数据结构》
《redis 从0到1完整学习 (八):QuickList 数据结构》
《redis 从0到1完整学习 (九):SkipList 数据结构》
《redis 从0到1完整学习 (十):RedisObject 数据结构》
《redis 从0到1完整学习 (十一):RedisObject 之 String 类型》

文章来源:https://blog.csdn.net/qq_36803941/article/details/135319371
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。