• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Redis数据类型与指令详解之集合(t_set)

mysql 搞代码 4年前 (2022-01-09) 18次浏览 已收录 0个评论
文章目录[隐藏]

集合编码方式 Redis 集合(set)使用REDIS_ENCONDING_INT与REDIS_ENCONDING_HT两种编码方式 1、REDIS_ENCONDING_INT: intset.c/intset.h 2、REDIS_ENCONDING_HT: dict.c/dict.h 第一个添加到集合的元素,决定了创建集合时所使用的编码:如果第一个元素可以表示

集合编码方式

Redis 集合(set)使用REDIS_ENCONDING_INT与REDIS_ENCONDING_HT两种编码方式
1、REDIS_ENCONDING_INT: intset.c/intset.h
2、REDIS_ENCONDING_HT: dict.c/dict.h
第一个添加到集合的元素,决定了创建集合时所使用的编码:如果第一个元素可以表示为 long long 类型值(也即是,它是一个整数),那么集合的初始编码为 REDIS_ENCODING_INTSET ;否则,集合的初始编码为 REDIS_ENCODING_HT 。
编码切换:如果一个集合使用 REDIS_ENCODING_INTSET 编码,那么当以下任何一个条件被满足时,这个集合会被转换成 REDIS_ENCODING_HT 编码:
1、 intset 保存的整数值个数超过 server.set_max_intset_entries (默认值为 512 )
2、试图往集合里添加一个新元素,并且这个元素不能被表示为 long long 类型

集合指令实现

SADD

指令格式: SADD key member [member…]
将一个或多个member元素加入到集合key当中,由于集合成员不能重复,已经存在于集合key中的member元素将被忽略。
如果key不存在,则创建一个包含被添加的member元素的新集合。
如果key不是集合类型(REDIS_SET)时,则操作出错,redis返回一个错误。
时间复杂度:O(N)

void saddCommand(redisClient *c) {    robj *set;    int j, added = 0;    set = lookupKeyWrite(c->db,c->argv[1]);//写查找数据库中名为c->argv[1]的集合    if (set == NULL) {//集合不存在        set = setTypeCreate(c->argv[2]);//创建一个新的集合        dbAdd(c->db,c->argv[1],set);//将该集合添加到数据库中,dict中的key就是集合的名称,value就是集合元素    } else {        if (set->type != REDIS_SET) {//判断是否是集合类型            addReply(c,shared.wrongtypeerr);            return;        }    }    for (j = 2; j argc; j++) {//添加集合元素        c->argv[j] = tryObjectEncoding(c->argv[j]);//尝试使用整型存储数据        if (setTypeAdd(set,c->argv[j])) added++;    }    if (added) {        signalModifiedKey(c->db,c->argv[1]);//通知数据库哪些键key变化了,把变化的key存储到watched_keys中,只在事务操作时才用的着        notifyKeyspaceEvent(<mark style="color:transparent">本文来源gaodaimacom搞#^代%!码网@</mark>REDIS_NOTIFY_SET,"sadd",c->argv[1],c->db->id);//暂不知道啥用途    }    server.dirty += added;//数据库中数据变化的数目    addReplyLongLong(c,added);}

lookupKeyWrite函数在object.c文件中,用来在数据库中查找指定key的value值。
setTypeCreate函数在创建一个新的Redis_Set时,根据添加的元素类型为整型还是字符串会创建不同的存储数据结构

//创建一个集合对象,如果value是整型,那么使用intset,否则使用dictrobj *setTypeCreate(robj *value) {    if (isObjectRepresentableAsLongLong(value,NULL) == REDIS_OK)        return createIntsetObject();//intset    return createSetObject();//dict}robj *createSetObject(void) {    dict *d = dictCreate(&setDictType,NULL);    robj *o = createObject(REDIS_SET,d);    o->encoding = REDIS_ENCODING_HT;    return o;}robj *createIntsetObject(void) {    intset *is = intsetNew();    robj *o = createObject(REDIS_SET,is);    o->encoding = REDIS_ENCODING_INTSET;    return o;}robj *createObject(int type, void *ptr) {    robj *o = zmalloc(sizeof(*o));    o->type = type;    o->encoding = REDIS_ENCODING_RAW;    o->ptr = ptr;    o->refcount = 1;    /* Set the LRU to the current lruclock (minutes resolution). */    o->lru = server.lruclock;    return o;}

SCARD

SCARD key
返回集合key中元素的个数
时间复杂度:O(1)
简单根据集合的编码类型:如果是HT编码,那么直接通过dictSize函数得到字典中元素的个数;如果是intset编码,那么直接通过intsetLen函数得到结果.

SISMEMBER


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Redis数据类型与指令详解之集合(t_set)
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址