`

Redis代码阅读2--Redis数据结构之链表

 
阅读更多

     Redis 是一个开源的高性能key-value数据库,其很大程度上弥补了memeched这类key-value存储的不足(除了支持String外,还支持Hash,Set,sorted set, List),在部分场合对关系型数据库也起到了很好的补充作用。因为Redis的代码量并不多,因为我逐步阅读了其源代码,以期能对其有深入的理解。首先介绍Redis支持的各种数据结构。

     Redis中的链表是双向链表,这一点可以由 adlist.h 中代码得出:

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

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    unsigned int len;
} list;

 struct list通过head 和tail这两个指针维护了链表的头、尾节点。ListNode通过prev和next使得链表成为一个双向链表。Struct List里面的dup、free和match这三个函数指针用于配置复制、释放和匹配三个功能。比如listSetMatchMethod就是用来设置match方法的。

  Redis里的List这一数据结构和我们常说的数据结构里面的链表很相似,同样有在头、尾节点增加Node,删除Node,查找Node及Index等功能。

  Redis里面操作list的命令有RPUSH,LPUSH,LSET,LLEN等。Redis中负责实现这些命令的API就在t_list.c。下面就以RPUSH为例,来说明当客户端执行RPUSH命令时,Redis是如何通过list 的API去执行list的listAddNodeTail方法的。

   在Redis.c里面,有一个Struct里面叫readonlyCommandTable。这个struct将Redis的各种命令和Redis里面各种命令对应的函数关联起来。比如:{"rpush",rpushCommand,-3,REDIS_CMD_DENYOOM,NULL,1,1,1}。

   Redis Server接收各个Client传过来的各种命令是通过networking.c里面的代码来完成的。具体如何解析和执行各种Command以后会单独拎出来讲。这里主要简单介绍下其流程。

 processInputBuffer-->processCommand-->lookupCommand.这里的lookupCommand就是根据Command的名字从readonlyCommandTable找出该Command对应的方法。比如,Client执行RPUSH命令,则这里的lookupCommand找到的是rpushCommand。

 

void rpushCommand(redisClient *c) {
    pushGenericCommand(c,REDIS_TAIL);
}

void pushGenericCommand(redisClient *c, int where) {
    int j, addlen = 0, pushed = 0;
    robj *lobj = lookupKeyWrite(c->db,c->argv[1]);
    int may_have_waiting_clients = (lobj == NULL);

    if (lobj && lobj->type != REDIS_LIST) {
        addReply(c,shared.wrongtypeerr);
        return;
    }

    for (j = 2; j < c->argc; j++) {
        c->argv[j] = tryObjectEncoding(c->argv[j]);
        if (may_have_waiting_clients) {
            if (handleClientsWaitingListPush(c,c->argv[1],c->argv[j])) {
                addlen++;
                continue;
            } else {
                may_have_waiting_clients = 0;
            }
        }
        if (!lobj) {
            lobj = createZiplistObject();
            dbAdd(c->db,c->argv[1],lobj);
        }
        listTypePush(lobj,c->argv[j],where);
        pushed++;
    }
    addReplyLongLong(c,addlen + (lobj ? listTypeLength(lobj) : 0));
    if (pushed) signalModifiedKey(c->db,c->argv[1]);
    server.dirty += pushed;
}

void listTypePush(robj *subject, robj *value, int where) {
    /* Check if we need to convert the ziplist */
    listTypeTryConversion(subject,value);
    if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
        ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)
            listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);

    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
        int pos = (where == REDIS_HEAD) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
        value = getDecodedObject(value);
        subject->ptr = ziplistPush(subject->ptr,value->ptr,sdslen(value->ptr),pos);
        decrRefCount(value);
    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
        if (where == REDIS_HEAD) {
            listAddNodeHead(subject->ptr,value);
        } else {
            listAddNodeTail(subject->ptr,value);
        }
        incrRefCount(value);
    } else {
        redisPanic("Unknown list encoding");
    }
}

     在t_list.c里面,rpushCommand-->pushGenericCommand-->listTypePush。listTypePush里面通过方向变量where来判断是在head还是在tail插入新的Node。

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    Redis-x64-3.2.100.zip

    redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,...区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步

    Redis-x64-4.0.14

    redis安装版 直接可以运行在windows端。。redis是一个key-value...和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。

    Redis-x64-5.0.9.msi

    redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,...区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

    redis-x64-3.2.1

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    Redis-x64-2.8.2104.zip (windows下不需安装解压版)

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    Redis-x64-5.0.10

    windows下redis安装包。 redis是一个key-value存储系统。它支持存储的value类型很多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、...

    Redis-for-windows-x64-2.8.2400

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    Redis-x64-3.0.500-rc1

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    Redis-win64-5.0.14.1

    redis是一个以key-value存储的数据库结构型服务器,它支持的数据结构类型包括:字符串(String)、链表(lists)、哈希表(hash)、集合(set)、有序集合(Zset)等。为了保证读取的效率,redis把数据对象都存储在...

    Redis-x64-3.2.100 windows版.7z

    Redis 64位 3.2.100 windows版 便携版,可直接解压使用。 redis是一个key-value存储...区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

    windows下64位的Redis-x64-3.0.300-alpha3

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    linux下redis-4.0.14.zip下载

    这个特点主要是因为其有“持久化”功能 (2)存储的数据有“结构”,对于memcache来说,存储的数据,只有一种类型——“字符串”,而redis则可以存储字符串、链表、集合、有序集合、哈序结构3、持久化的两种方式:...

    redis-linux-7.2.1

    redis是一个以key-value存储的数据库结构型服务器,它支持的数据结构类型包括:字符串(String)、链表(lists)、哈希表(hash)、集合(set)、有序集合(Zset)等。为了保证读取的效率,redis把数据对象都存储在...

    Redis-deployment-on-windows.rar_MEMCACHED_Master/Slave_文件哈希存储

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、 list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    redis-core-java.zip

    区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类...

    redis 源代码

    redis源代码+注释 redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都...

    redis的双链表代码提取

    将redis中的双链表代码提取出来,已经在vs2015下编译通过。可直接使用在工程项目中。 如果直接将redis源码拉出来,编译不通过,本资源充分解决了此烦恼

    redis-2.2.2 (源码)

    区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 redis的几种使用方式 Strings、Hashs、Lists、Sets、Sorted Sets、Pub/Sub、...

    redisCluster.zip

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

Global site tag (gtag.js) - Google Analytics