Redis数据结构与对象

155 阅读4分钟

Redis数据结构与对象

当聊到redis的数据结构与对象时,不得不分清两个概念,一个是什么是redis对象,一个是redis底层存储的数据结构。正因为redis细致化的数据类型和巧妙组装的对象,使得redis可以基于内存进行交互。正因为很多文章将对象的概念和数据结构混淆,所以在开篇特意指出让大家在接下来的阅读中能更加通俗易懂地了解作者的阐述。

对象根据类型分(即常提及的):字符串对象(string),字典对象(hash),列表对象(list),集合对象(set)和有序集合对象(zset)。

底层存储数据结构:如简单动态字符串(SDS)、链表、字典、跳跃表、整数集合以及压缩列表。

本篇文章从全局讲述数据结构和对象的概念,在之后的文章会分别对数据结构和对象进行一个详细的阐述。

Redis对象

简介

首先先看一下什么是redis对象,即我们常说的:字符串对象,字典对象,列表对象,集合对象和有序集合对象。redis在根据类型区分不同对象之外,根据对象存储特性的不同还会做更细致的区分,比如列表对象会根据存储元素的数量和类型,选择用不同的数据结构进行存储-(链表存储还是压缩列表存储)。以下是redis对象结构:

结构

typedef struct redisObject {
    // 类型 -对象的类型,string、list、hash、set、zset
    unsigned type:4;
    
    // 编码 对象存储的底层数据结构的编码(类型)
    unsigned encoding:4;
    
    // 指向底层实现数据结构的指针
    void *ptr;
    
    // 计数器
    int refcount;
    
    // 记录对象最后一次被命令程序访问的时间
    unsigned lru:22;
}

类型

结构中的type记录了对象的类型

类型常量对象名称
REDIS_STRING字符串对象
REDIS_LIST列表对象
REDIS_HASH哈希对象
REDIS_SET集合对象
REDIS_ZSET有序集合对象

通过TYPE命令可以查看对象的类型,以下为例子

redis> SET msg "hello world"
OK
redis> TYPE msg
string

即msg这个key的值的对象类型为字符串对象(string)

编码

编码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编码的简单动态字符串*/

通过OBJECT ENCODING命令可以查看值对象的编码,以下为例子

redis> SET msg "hello world"
OK
redis> OBJECT ENCODING msg
"embstr"

计数器refcount

redis使用引用计数法(reference counting)进行内存回收,通过这个字段记录该对象被引用的次数。具体策略如下

  • 当创建对象时,refcount会被初始化为1
  • 当对象被一个新程序引用时,refcount会被加1
  • 当对象不再被一个程序引用时,refcount会被减1
  • 当对象引用计数值为0时,对象所占用的内存会在适当时机被释放

对象空转时长lru

记录对象最后一次被命令程序访问的时间,此外通过这个值那些空转时间较高的那部分键会优先被释放以达到释放内存的目的。这一过程在后续内存回收中详细介绍。

通过以上介绍,希望能够给读者对redis的对象有较为清楚的认识。

  • 平时常提的“字符串数据结构”、“列表类型数据结构”、“hash数据结构”并不是真的数据结构,指的是redis的对象类型。

  • redis定义的对象redisObject的主要参数的意义,通过这些参数了解对象所具备的能力。

  • 下面的文章会通过介绍redis对象,穿插着介绍讲解redis使用的数据结构。

本文的主要知识来源于书籍 《Redis设计与实现》,也希望大家能够通过书籍系统学习知识。