侧边栏壁纸
博主头像
Terry

『LESSON 5』

  • 累计撰写 90 篇文章
  • 累计创建 21 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Redis中RedisObject分析

Terry
2021-01-01 / 0 评论 / 0 点赞 / 407 阅读 / 2,990 字 / 正在检测是否收录...

简述

大家都知道,使用object encoding key就能看出redis value的数据结构,比如raw、int、hash、ziplist等,我一开始也以为redis key-value结构,value直接使用数据结构,但是如果是这样object encoding key命令就说不通了。所以我再次看redis源码分析下😊。

redisObject

首先看redisObject,它在server.h下。

typedef struct redisObject {
    /*类型*/
    unsigned type:4;
    /*编码*/
    unsigned encoding:4;
    /*对象最后一次被访问的时间*/
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    /*引用计数*/
    int refcount;
    /*指向底层实现数据结构的指针*/
    void *ptr;
} robj;

可以看到,其实在Redis中创建一个key-value时,我们会至少创建两个对象,key和value。key和value其实都是redisObject类型,key的话,最终会存的是SDS类型,这里我们先看redisObject中的参数。

type

/* The actual Redis Object */
#define OBJ_STRING 0    /* String object. */
#define OBJ_LIST 1      /* List object. */
#define OBJ_SET 2       /* Set object. */
#define OBJ_ZSET 3      /* Sorted set object. */
#define OBJ_HASH 4      /* Hash object. */
#define OBJ_MODULE 5    /* Module object. */
#define OBJ_STREAM 6    /* Stream object. */

含义:

类型名称
OBJ_STRING0字符串对象
OBJ_LIST1列表对象
OBJ_SET2集合对象
OBJ_ZSET3有序集合对象
OBJ_HASH4hash对象
OBJ_MODULE5RDB文件中用到的模块对象,不太了解
OBJ_STREAM6流对象,不太了解

encoding

#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */

含义:

类型名称
OBJ_ENCODING_RAW0简单动态字符串
OBJ_ENCODING_INT1最大值为2的63次方-1
OBJ_ENCODING_HT2字典
OBJ_ENCODING_ZIPMAP3压缩字典
OBJ_ENCODING_LINKEDLIST4双端链表,注释写着不再使用
OBJ_ENCODING_ZIPLIST5压缩列表
OBJ_ENCODING_INTSET6整数集合
OBJ_ENCODING_SKIPLIST7跳跃表,不过也包含字典
OBJ_ENCODING_EMBSTR8短的简单动态字符串
OBJ_ENCODING_QUICKLIST9快速列表,是ziplist和linkedList的混合体
OBJ_ENCODING_STREAM10流,不太了解

lru

Least Recently Used,对象最后一次被访问的时间。

refcount

refcount表示引用计数,由于C语言没有自动内存回收功能,所以Redis在对象中添加这个属性,如果refcount为0的时候,可以进行垃圾回收。

ptr

指向对象的底层实现数据结构指针。

使用RedisObject的好处

  1. 能直接知道对象类型,在执行命令之前可以根据对象的类型来执行给定的命令。我们可以通过type key获取到数据结构类型;通过object encoding key可以获取到存储的数据结构。
  2. 可以针对不同的使用场景,为不同的对象设置不同的实现,大大优化了内存和查询速度。比方说hash,数据量比较少,数据都比较小的时候会使用ziplist数据结构,大大减少内存占用,因为数据量小,zip查询速度也不会很慢;当数据量比较多,数据比较大的时候,会使用hashTable数据结构,虽然内存没ziplist占用少,但是查询时间复杂度为O(1)。

key对象类型

我上面也说了,key和value都使用了redisObject,那么key具体的数据结构是什么?带着疑问,我看了添加键值对的方法,具体在db.c下:

/* Add the key to the DB. It's up to the caller to increment the reference
 * counter of the value if needed.
 *
 * The program is aborted if the key already exists. */
void dbAdd(redisDb *db, robj *key, robj *val) {
    /*使用sds,简单动态字符串*/
    sds copy = sdsdup(key->ptr);
    int retval = dictAdd(db->dict, copy, val);

    serverAssertWithInfo(NULL,key,retval == DICT_OK);
    signalKeyAsReady(db, key, val->type);
    if (server.cluster_enabled) slotToKeyAdd(key->ptr);
}

以上代码可以看出,每次存储key-value的时候,key都会使用sds(简单动态字符串)来存。所以key是string类型,是固定的。

总结

今天介绍了redisObject,自己看了源码,和结合《redis设计与实现》对redisObject介绍总结的。网上的大部分文档没有对源码的解析,自己去看了遍,印象更加深刻。只要存疑,自己亲自去查看,而不是只关注别人发的文章,才更有收获!下次我会继续介绍type和encoding的几种类型。

0

评论区