美文网首页
Redis深度历险-快速列表

Redis深度历险-快速列表

作者: 突击手平头哥 | 来源:发表于2021-08-19 23:17 被阅读0次

Redis深度历险-快速列表

快速列表就是为了实现list的功能,是基于压缩列表和双向链表的集合实现,主要是规避普通双向链表的前后指针分配和内存碎片问题

列表

void listTypePush(robj *subject, robj *value, int where) {
    //list只有快速列表一种存储方式了
    if (subject->encoding == OBJ_ENCODING_QUICKLIST) {
        int pos = (where == LIST_HEAD) ? QUICKLIST_HEAD : QUICKLIST_TAIL;
        //将数据插入到快速列表中 
        if (value->encoding == OBJ_ENCODING_INT) {
            char buf[32];
            ll2string(buf, 32, (long)value->ptr);
            quicklistPush(subject->ptr, buf, strlen(buf), pos);
        } else {
            quicklistPush(subject->ptr, value->ptr, sdslen(value->ptr), pos);
        }
    } else {
        serverPanic("Unknown list encoding");
    }
}

列表只使用了快速列表存储数据

快速列表

快速列表的结构很简单,快速列表就是一个双向链表,只不过链表中每一个节点都是一个压缩列表

结构体

快速列表

typedef struct quicklist {
    quicklistNode *head;
    quicklistNode *tail;                //快速列表的头尾节点
    unsigned long count;        //所有元素的个数
    unsigned long len;          //快速列表节点个数
    int fill : QL_FILL_BITS;                        //和压缩有关的参数,不必关注
    unsigned int compress : QL_COMP_BITS;   
    unsigned int bookmark_count: QL_BM_BITS;
    quicklistBookmark bookmarks[];
} quicklist;

压缩列表可以进行压缩以节省空间,暂时不必关注

快速列表节点

typedef struct quicklistNode {
    struct quicklistNode *prev;             
    struct quicklistNode *next;             //双向链表前一个节点和后一个节点
    unsigned char *zl;                              //压缩列表
    unsigned int sz;                        //压缩列表字节长度
    unsigned int count : 16;                //压缩列表中元素个数? 压缩列表中不是有吗???
    unsigned int encoding : 2;              //编码方式,原生的还是压缩的
    unsigned int container : 2;             
    unsigned int recompress : 1;                
    unsigned int attempted_compress : 1; 
    unsigned int extra : 10;                            //为将来预留的标志位
} quicklistNode;

头部插入元素

int quicklistPushHead(quicklist *quicklist, void *value, size_t sz) {
    quicklistNode *orig_head = quicklist->head;
    //目前快速列表的头节点是否还允许插入元素
    if (likely(
            _quicklistNodeAllowInsert(quicklist->head, quicklist->fill, sz))) {
        //在快速列表头节点中插入元素
        quicklist->head->zl =
            ziplistPush(quicklist->head->zl, value, sz, ZIPLIST_HEAD);
        //更新头节点中压缩列表的字节长度
        quicklistNodeUpdateSz(quicklist->head);
    } else {
        //创建一个新的快速列表节点,并把元素插入到此节点中
        quicklistNode *node = quicklistCreateNode();
        node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_HEAD);
                
        //更新快速列表中压缩列表字节长度
        quicklistNodeUpdateSz(node);
        //将这个新创建的快速列表节点插入在快速列表头部
        _quicklistInsertNodeBefore(quicklist, quicklist->head, node);
    }
    //更新数量统计
    quicklist->count++;
    quicklist->head->count++;
    return (orig_head != quicklist->head);
}

因为列表只支持头部、尾部插入数据,所以整个代码还是比较清晰的

相关文章

  • Redis深度历险-快速列表

    Redis深度历险-快速列表 快速列表就是为了实现list的功能,是基于压缩列表和双向链表的集合实现,主要是规避普...

  • 分布式Redis深度历险-复制

    Redis深度历险分为两个部分,单机Redis和分布式Redis。 本文为分布式Redis深度历险系列的第一篇,主...

  • Redis深度历险-压缩列表

    Redis深度历险-压缩列表 在zset和hash在元素个数较少时会采用压缩列表来存储以节省空间,主要代码在zip...

  • Redis深度历险-紧凑列表

    紧凑列表 在Redis5.0又引入了新的数据结构listpack,是在压缩列表基础上的改进,整体有所类似,紧凑列表...

  • redis利用zset简单限流

    引用出处:老钱的 Redis 深度历险:核心原理与应用实践

  • 蜻蜓点水说说Redis的ziplist的奥秘

    本篇博客参考: Redis 深度历险:核心原理与应用实践 Redis内部数据结构详解(4)——ziplist Re...

  • Redis学习之旅~原理篇

    内容依旧来自 核心原理 线程IO模型 单线程非阻塞IO redis是单线程模型。redis的...

  • Redis深度历险笔记

    Redis深度历险笔记 基础与应用 Redis基础数据结构 5种基础数据结构:string、list、hash(字...

  • redis有序集合对象

    内容来自:《redis设计与实现》购买本书请访问: 京东商城《Redis 深度历险:核心原理与应用实践》购买本书请...

  • redis集合对象

    内容来自:《redis设计与实现》购买本书请访问: 京东商城《Redis 深度历险:核心原理与应用实践》购买本书请...

网友评论

      本文标题:Redis深度历险-快速列表

      本文链接:https://www.haomeiwen.com/subject/zxnnbltx.html