美文网首页
Redis深度历险-集合

Redis深度历险-集合

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

Redis深度历险-集合

Redis中的set是一种无序集合,如果存储的全部都是数字则内部使用的是intset存储,否则使用的是hashtab存储

字符串集合

int setTypeAdd(robj *subject, sds value) {
    long long llval;
    if (subject->encoding == OBJ_ENCODING_HT) {
        dict *ht = subject->ptr;
        //使用的是字典存储,只不过value是NULL
        dictEntry *de = dictAddRaw(ht,value,NULL);
        if (de) {
            dictSetKey(ht,de,sdsdup(value));
            dictSetVal(ht,de,NULL);
            return 1;
        }
    } else if (subject->encoding == OBJ_ENCODING_INTSET) {
        ..........
    } else {
        serverPanic("Unknown set encoding");
    }
    return 0;
}

在编码是OBJ_ENCODING_HT时直接使用字典来存储,只不过所有的value是NULL

数字集合

int setTypeAdd(robj *subject, sds value) {
    long long llval;
    if (subject->encoding == OBJ_ENCODING_HT) {
        .........
    } else if (subject->encoding == OBJ_ENCODING_INTSET) {
        //判断能够转为long long类型的证书
        if (isSdsRepresentableAsLongLong(value,&llval) == C_OK) {
            uint8_t success = 0;
            //插入到intset数据结构中
            subject->ptr = intsetAdd(subject->ptr,llval,&success);
            if (success) {
                //如果intset中存储的数据超过set_max_intset_entries则转为字典存储,默认512个
                if (intsetLen(subject->ptr) > server.set_max_intset_entries)
                    setTypeConvert(subject,OBJ_ENCODING_HT);
                return 1;
            }
        } else {
            //不能转换成证书,则转为存储到字典中
            setTypeConvert(subject,OBJ_ENCODING_HT);
          
            serverAssert(dictAdd(subject->ptr,sdsdup(value),NULL) == DICT_OK);
            return 1;
        }
    } else {
        serverPanic("Unknown set encoding");
    }
    return 0;
}

编码类型转换

在插入字符串或者数据数量超过512个(配置文件中设置)时转为为OBJ_ENCODING_HT

void setTypeConvert(robj *setobj, int enc) {
    setTypeIterator *si;
    serverAssertWithInfo(NULL,setobj,setobj->type == OBJ_SET &&
                             setobj->encoding == OBJ_ENCODING_INTSET);
        
    //只支持转换为字典类型
    if (enc == OBJ_ENCODING_HT) {
        int64_t intele;
        dict *d = dictCreate(&setDictType,NULL);
        sds element;
                
        //按集合数据类型,初始化字典空间
        dictExpand(d,intsetLen(setobj->ptr));

        //将intset中的每一项数据逐个加入到集合中
        si = setTypeInitIterator(setobj);
        while (setTypeNext(si,&element,&intele) != -1) {
            element = sdsfromlonglong(intele);
            serverAssert(dictAdd(d,element,NULL) == DICT_OK);
        }
        setTypeReleaseIterator(si);
                
        //释放原油的空间
        setobj->encoding = OBJ_ENCODING_HT;
        zfree(setobj->ptr);
        setobj->ptr = d;
    } else {
        serverPanic("Unsupported set conversion");
    }
}

相关文章

  • Redis深度历险-整数集合(intset)

    Redis深度历险-整数集合(intset) Redis中的集合在只有数字的情况下使用的是intset存储,主要代...

  • Redis深度历险-集合

    Redis深度历险-集合 Redis中的set是一种无序集合,如果存储的全部都是数字则内部使用的是intset存储...

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

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

  • Redis深度历险-快速列表

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

  • 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/azravltx.html