Redis在实现键值对数据库时,并没有直接使用数据结构,而是基于已有的数据结构创建了一个对象系统,每种对象至少包含一种数据结构。
redis3.0 中对象结构:
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
int refcount;
void *ptr;
} robj;
这个系统包含字符串对象,列表对象,哈希对象,集合对象和有序集合对象5中类型的对象。
使用对象有什么好处?
1:根据对象的类型来判断一个对象是否可以执行给定的命令。
2:针对不同的数据场景,为对象设置多种不同的数据结构实现,从而优化在不同场景的使用效率。
3:对象系统还实现了基于应用计数的内存回收机制
4:Redis的对象带有访问时间记录的信息,如果该键的空转时长较大那么会优先删除掉
对象中的 type 类型:
/* Object types */
#define REDIS_STRING 0 /*字符串对象*/
#define REDIS_LIST 1 /*列表对象*/
#define REDIS_SET 2 /*集合对象*/
#define REDIS_ZSET 3 /*有序集合对象*/
#define REDIS_HASH 4 /*哈希对象*/
可以用 type 命令查看对象的类型
encoding 编码:
#define REDIS_ENCODING_RAW 0 /* Raw representation 简单动态字符串*/
#define REDIS_ENCODING_INT 1 /* Encoded as integer long 类型的整数*/
#define REDIS_ENCODING_HT 2 /* Encoded as hash table 字典*/
#define REDIS_ENCODING_ZIPMAP 3 /* Encoded as zipmap 压缩map*/
#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list 双端链表*/
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist 压缩列表*/
#define REDIS_ENCODING_INTSET 6 /* Encoded as intset 整数集合*/
#define REDIS_ENCODING_SKIPLIST 7 /* Encoded as skiplist 跳跃表*/
#define REDIS_ENCODING_EMBSTR 8 /* Embedded sds string encoding embstr编码的简单动态字符串*/
raw 编码 和 embstr编码的区别:
1:如果字符串对象保存都是一个字符串值,并且这个字符串值长度小于等于32字节,那么使用embstr编码方式保存值,也就是说 embstr是用来保存短字符串的值
这样做有什么好处呢?
1:raw编码会调用2次内存分配函数分别创建redisObject结构和sdshdr结构, 而embstr编码则通过调用 1 次内存分配函数分配一块连续的空间,空间会包含redisObject和sdshdr结构。
2:那么释放的时候raw要释放2次, 而embstr只释放一次内存空间。
refcount 属性:
Redis为对象系统构建了一个引用计数,就是这个字段,目的是来实现内存回收机制。
ptr 属性:
存储的值
lru 属性:
这个属性记录了对象最后一次呗命令程序访问的时间
我们可以用这个属性来计算给定键多长时间没有被访问了。
命令: object idletime 健名
还有一个用处:
如果服务器设置打开了maxmemory选项,并且服务器回收内存算法为volatile-lru或者allkeys-lru,那么当服务器的内存超过了maxmemory设置的上限时,没有被访问的时间越长的键就越有限被服务器释放,从而回收内存