Redis学习——2. 对象类型(一):字符串对象

2、对象类型

第一部分的6节简单介绍了Redis的基础数据结构,接下来要开始学习Redis的对象系统。下面(2-1)是redis中对象的实现:

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;

 其中 type共有5中:

对象 属性 type 指令输出
字符串对象 REDIS_STRING string
列表对象 REIDS_LIST list
哈希对象 REDIS_HASH hash
集合对象 REDIS_SET set
有序集合对象 REDIS_ZSET zset

encoding共8中,指明了*ptr的具体的数据结构,*ptr则是存储具体数据的指针。

2.1  字符串对象(string)

Redis中字符串对象针对不同的数据可能有三种编码方式。

2.1.1 REDIS_ENCODING_INT

整数型的字符串会使用这种编码进行存储,其取值范围为 -9223372036854775808~9223372036854775807(long)

127.0.0.1:6379> SET val1 1
OK
127.0.0.1:6379> type val1
string
127.0.0.1:6379> object encoding val1
"int"

2.1.2 REDIS_ENCODING_EMBSTR

对于长度小于等于39的字符串(3.0之后长度小于等于44),采用embstr编码方式存储。

127.0.0.1:6379> SET val1 abcd
OK
127.0.0.1:6379> SET val2 abcd
OK
127.0.0.1:6379> type val2
string
127.0.0.1:6379> object encoding val2
"embstr"

为什么是39和44这样的数呢?

对于字符串的存储,Redis使用robj+sdshdr实现;每次创建字符串对象程序必须进行两次内存申请,为了提升程序的性能,对于短字符串会一次申请64byte的内存大小(Redis使用jemalloc内存分配器,可以分配8,16,32,64字节等大小的内存),通过1-1、2-1我们可以算出robj需要的内存大小为4x4=16,sdshdr需要的内存大小为4x2=8,那buf的可用大小就是64-16-8=40,再出去'\0'占用的一个空间,则还剩39。

而44则是由于3.2之后redis对于sdshdr实现的修改,因为对于短字符串来说,int型的len和free有点过于浪费了,所以redis分别实现了sdshdr5,sdshdr8,sdshdr16,sdshdr32,sdshdr64。具体的长度大家可以自己自行计算,我在下面贴上这种类型的实现。

typedef unsigned char     uint8_t;

struct sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

值得注意的是,Redis并没有为embstr编写任何的修改程序,所以embstr对象实际上是只读的,当我们执行修改命令是,embstr对象会被转为raw对象,修改完成之后不会转换回去。

127.0.0.1:6379> set val4 hello
OK
127.0.0.1:6379> object encoding val4
"embstr"
127.0.0.1:6379> append val4 ' world'
(integer) 11
127.0.0.1:6379> object encoding val4
"raw"
127.0.0.1:6379> set val4 'hello world'
OK
127.0.0.1:6379> object encoding val4
"embstr"

2.1.3 REDIS_ENCODING_RAW

127.0.0.1:6379> SET val3 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678
OK
127.0.0.1:6379> object encoding val3
"embstr"
127.0.0.1:6379> type val3
string
127.0.0.1:6379> SET val3 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789
OK
127.0.0.1:6379> object encoding val3
"raw"
127.0.0.1:6379> type val3
string

出了上述两种情况外,字符串都会是raw编码。

猜你喜欢

转载自blog.csdn.net/Finalowee/article/details/81129882