对象系统
  1. Redis使用对象来表示数据库中的键和值
  2. 每种对象都用到了至少一种数据结构:动态字符串、链表、字典、跳跃表、整数集合、压缩列表
  3. 针对不同的使用场景,为对象设置多种不同的数据结构实现,优化对象在不同场景下的使用效率
  4. 基于引用计数技术的 内存回收机制对象共享机制
  5. 对象带有访问时间记录信息,
定义
// 对象类型
// 字符串对象
#define OBJ_STRING 0    
// 列表对象
#define OBJ_LIST 1      
// 集合对象
#define OBJ_SET 2       
// 有序集合对象
#define OBJ_ZSET 3      
// 哈希对象
#define OBJ_HASH 4      

// 对象编码类型
// 简单动态字符串
#define OBJ_ENCODING_RAW 0     
// long类型的整数
#define OBJ_ENCODING_INT 1     
// 字典
#define OBJ_ENCODING_HT 2      
#define OBJ_ENCODING_ZIPMAP 3  
// 双端链表
#define OBJ_ENCODING_LINKEDLIST 4 
// 压缩列表
#define OBJ_ENCODING_ZIPLIST 5 
// 整数
#define OBJ_ENCODING_INTSET 6  
// 跳跃表
#define OBJ_ENCODING_SKIPLIST 7  
// embstr编码的简单动态字符串
#define OBJ_ENCODING_EMBSTR 8  
// 压缩链表
#define OBJ_ENCODING_QUICKLIST 9 
// 流
#define OBJ_ENCODING_STREAM 10 

/**
 * 对象redisObject数据结构
 * Redis 存储的 value 数据都是用 redisObject 来封装的
 * 包括 string,hash,list,set,zset  在内的所有数据类型
 */
typedef struct redisObject {
    /**
     * 对象类型:表示当前对象使用的数据类型,
     * Redis主要支持5种数据类型:string,hash,list,set,zset。
     * 可以使用type {key}命令查看对象所属类型,
     * type命令返回的是值对象类型,键都是string类型。
     */
    unsigned type:4;

    // 
    /**
     * 编码类型:ptr指针所指向对象的底层实现数据结构类型,即当前对象使用了什么数据结构作为对象的底层实现
     * 表示Redis内部编码类型,encoding在Redis内部使用,
     * 代表当前对象内部采用哪种数据结构实现。
     * 理解Redis内部编码方式对于优化内存非常重要 ,
     * 同一个对象采用不同的编码实现内存占用存在明显差异,
     */
    unsigned encoding:4;
    
    // 缓存策略数据
    // 空转时长(idletime) = 当前时间 - lru属性时间
    // LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰
    // 该算法赋予每个页面一个访问时间字段,用来记录一个页面自上次被访问以来所经历的时间 idletime,当须淘汰一个页面时,选择现有页面中其 idletime 值最大的

    /**
     * 记录对象最后一次被访问的时间,
     * 当配置了maxmemory 和 maxmemory-policy=volatile-lru | allkeys-lru 时,辅助LRU算法释放高空转时长键,回收内存
     */
    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). */
    
    // LFU是Least Frequently Used的缩写,即最近最不经常使用,是一种常用的页面置换算法,选择引用计数最小的页面予以淘汰
    // 该算法赋予每个页面一个引用计数字段,用来记录一个页面使用次数 refcount,当须淘汰一个页面时,选择现有页面中其 refcount 值最小的
    
    /**
     * 引用计数:记录当前对象被引用的次数,用于通过引用次数回收内存,
     * 当refcount=0时,可以安全回收当前对象空间。
     * 使用 object refcount {key} 获取当前对象引用。
     */
    int refcount;

    /**
     * 指底层实现数据结构的指针:保存实际的数据
     * 与对象的数据内容相关,如果是整数直接存储数据,否则表示指向数据的指针。
     * Redis在3.0 之后对值对象是字符串且长度 <=39 字节的数据,
     * 内部编码为 embstr 类型,字符串 sds 和 redisObject 一起分配,从而只要一次内存操作。
     * 因此在高并发的场景尽量是我们的字符串保持 39 字节内,
     * 减少创建redisObject内存分配次数从而提高性能。
     */
    void *ptr;
} robj;

TYPE 命令

查看数据库键【对应的值对象】的类型

OBJECT ENCODING 命令

查看数据库键的【值对象】的编码

OBJECT REFCOUNT 命令

查看数据库键的【值对象】的引用计数

OBJECT IDLETIME 命令

查看数据库键的空转时长,不会修改值对象的lru属性

源码阅读
  1. 文件:src/server.h
只言片语任我说,提笔句句无需忖。落笔不知寄何人,唯有邀友共斟酌。对象系统 - 《Redis设计与实现》读书笔记_数据结构