redis对象

2019-07-26  本文已影响0人  ysdyyy

一 redis是怎样实现键值对数据库的
redis使用对象系统来实现键值对数据库,这个系统包括:字符串对象、列表对象、哈希对象、集合对象、有序集合对象。

二 redis对象定义(来自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;

2.1 变量解释
2.1.1 type: redis对象的类型,是一个常量,表示以上五种对象的任何一种。

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

2.1.2 ptr: 指向底层实现数据结构的指针

2.1.3 encodiing: 底层实现数据结构的类型,是一个常量,是某redis对象底层实现的一种。如字符串对象有三种实现(int、embstr、raw),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 */
#

2.1.4 lru:记录该对象最后一次被访问的时间,与内存回收有关。
若服务器内存回收算法与lru有关,且打开了maxmemory选项,当服务器占用的内存数大于maxmemory时,空转时长(now-lru)比较高的部分键会被优先释放。

2.1.5 refcount: 引用计数,用于自动内存回收。
由于c语言没有自动内存回收功能,所以redis在对象系统中增加refcount来实现内存回收机制:
当创建redis对象时,引用计数为1;
当对象被新程序引用时,引用计数增1;
当不在被一个程序使用时,引用计数减1;
当引用计数变为0时,释放该对象内存。

ps: 由于键值对中,键的类型固定为字符串对象,所以通常我们说的字符串键,列表键、哈希键、均指的是值对象的类型。

2.2 在redis中创建一个键值对的过程。
2.2.1 执行命令:

set str1 "hello"

2.2.2 redis创建一个字符串对象,保存键的值:‘str1’,然后根据值本身的特征,根据某规则,选择encoding=‘embstr’,创建如下object(为表示清楚,采用js对象表示法):

{
    type: 0,
    encoding: 8,
    lru: 1564126860413,
    refcount: 1,
    ptr: xxxxx// 指向embstr数据结构,该数据结构中保存着“hello”
}

2.2.3 redis判断值“hello”的类型,结合值的类型和特征,创建一个字符串对象。

三: 各redis对象的编码和使用情景。
3.1 字符串对象
字符串对象可使用的编码:

#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */

3.1.1 如果字符串对象保存的是一个整数值,且可以用long类型来表示,字符串对象会将整数值保存在ptr属性里面,并将对象的编码置为int;


image.png

3.1.2 如果字符串对象保存的是一个字符串值,并且字符串长度大于32字节,则使用sds来保存这个字符串值,并将对象的编码设置为raw;


image.png

3.1.3 如果字符串对象保存的是一个字符串值,并且字符串长度小于等于32字节;或者一个可以用long double类型表示的浮点数;则使用embstr方式保存这个字符串值,该编码调用一次内存分配函数来分配一块连续空间,空间中依次包含redisobject和sdshdr两个结构。


image.png

3.2 列表对象
列表对象可使用的编码:

#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */

3.2.1 当列表对象保存的所有字符串元素的长度都小于64字节;且保存的元素数量小于512个,使用ziplist编码


image.png

3.2.2 不满足3.2.1条件的,使用linkedlist编码


image.png

以上限制可以通过配置修改

3.3 哈希对象
哈希对象可以使用的编码

#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */

3.3.1 当哈希对象保存的所有键和值的长度都小于64字节,且键值对数量小于512个,使用ziplist编码

image.png
image.png

3.3.2 不满足3.2.1条件的,使用hashtable编码


image.png

以上限制可以通过配置修改

3.4 集合对象
集合对象可以使用的编码

#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */

3.4.1 当集合对象所有元素都是整数值,且元素数量不超过512个,使用intset编码


image.png

3.4.2 不满足3.4.1条件的,使用hashtable编码


image.png

元素数量512可以通过配置修改

3.5 有序集合对象
有序集合对象可以使用的编码

#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */

3.5.1 当有序集合保存的元素数量小于128个,且所有元素成员的长度都小于64字节,使用ziplist编码


image.png
image.png

3.5.2 不满足3.5.1的,使用skiplist编码。同时保存在字典和跳跃表中。保存在字典中是为了满足按键查找分数。


image.png

以上限制可以通过配置修改

四:redis内存回收
redis对象的refcount和lru与内存回收有关。

参考:《redis设计与实现》

上一篇 下一篇

猜你喜欢

热点阅读