【redis系列】数据类型的根源-redisObject

前言

redis相信每一个java伙伴都知道,但是我相信有一部分大佬已经对redis的使用以及底层实现已经烂熟于心,但是有些java伙伴可能还是停留在使用阶段,至于redis那么多数据类型,底层是怎么样的数据结构,以及实现方式还不是很了解,恰好,笔者最近正在研究这方便,希望精通的大佬,看看我阐述的有没有错误,不明白的小伙伴一起坐下来一起讨论,欢迎大家评论区留言。

因为redis是用c语言写的,笔者的c是个二把刀,所以很多地方如有错误,欢迎指正。

版本

本文采用的redis6.2的版本,如果没有特殊声明,则一直使用该版本。

redis类型的根源

问:什么是redis类型的根源?
答:临近中秋节,大家都要吃月饼了,制作月饼的时候,是需要将原料放到月饼的模具里面;redis也是一样,所有的数据类型都应该有一个东西去存储它,只不过redis的这个模具叫redisObject

redisObject对象

在这里插入图片描述

如下代码块来自于server.h中673行~681行

typedef struct redisObject {
	//下面语法的含义是:创建一个int类型的,占4位
	//unsigned int:4;
	
	//表示类型
    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). */

    //当前对象的引用次数,0时即释放
    int refcount;
    //存储数据的位置
    void *ptr;
} robj;

type属性

type字段主要表示的redis的类型(确切的说是redis中每个k-v对象的v类型,因为key的类型永远都是String),例如String、List等等。
如下代码块来自于server.h的506行~511行


/*-----------------------------------------------------------------------------
 * Data types
 *----------------------------------------------------------------------------*/

/* A redis object, that is a type able to hold a string / list / set */

/* 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. */

encoding属性

encoding字段代表了redisObject底层使用什么数据结构实现的。

例如:set底层使用的intset和hashtable(intset和hashtable底层是两种数据结构,笔者会在后续的日志中分享出来)。

如下代码块来自于server.h的651行~664行

/* Objects encoding. Some kind of objects like Strings and Hashes can be
 * internally represented in multiple ways. The 'encoding' field of the object
 * is set to one of this fields for this object. */
 /**
  * 对象编码。某些类型的对象,如string和hash,可以在内部以多种方式表示。
  * 对象的'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 */

例:set的encoding

为了方便大家理解,笔者特意找了set中添加元素的源码来给大家确认一下。
这里主要看的是set的编码,所以具体添加的代码,笔者省略了,后期笔者也会更新。
如下代码块来自于t_set.h的48行~86行

int setTypeAdd(robj *subject, sds value) {
    long long llval;
    //判断robj类型的形参*subject的encoding属性是否等于OBJ_ENCODING_HT
    if (subject->encoding == OBJ_ENCODING_HT) {
		//略
	//判断robj类型的形参*subject的encoding属性是否等于OBJ_ENCODING_HT
    } else if (subject->encoding == OBJ_ENCODING_INTSET) {
    	//略
    } else {
        serverPanic("Unknown set encoding");
    }
    return 0;
}

结论:通过上面的源码,可以非常明确的知道encoding的确存储的是编码类型

lru属性

lru是淘汰策略,redis启动时会读取配置文件中的redis的内存大小,如果redis的内存满了,就是根据不同的策略来进行释放。

refcount属性

refcount存储当前对象的引用次数,用于实际对象的共享,存储对象时,refcount就会增加1,删除对象的时候,refcount就会减少1,如果是0的时候,就会删除。

*ptr属性

*ptr属性存储的是实际存储数据的位置,仍然使用上面提到的set类型为例,*ptr实际指向的就是set底层数据数显对应的intset结构或者是hashtable结构。

总结

看到这里,相信大家对redis有了更加深入的了解,笔者也会在后续的日子中持续更新redis的源码分析,也希望大家耐心等待,一起成长,如果有问题或者有建议,欢迎大家评论区见。。

参考资料:

《Redis5设计与源码分析》 作者陈雷
《Redis设计与实现》 作者黄健宏

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值