Redis设计与实现 - chapter8 对象

Chapter8 对象

前面介绍了Redis中基本的几种数据结构:sds、linkedlist、dict、ziplist、intset,Redis并没有直接使用这些基本数据结构实现key-value数据库,而是基于它们构建了一个对象系统,用对象来描述数据库中的数据元素。

1. 对象定义

五种对象

名称 type 简记
字符串对象 REDIS_STRING StringObject
列表对象 REDIS_LIST ListObject
哈希对象 REDIS_HASH HashObject
集合对象 REDIS_SET SetObject
有序集合对象 REDIS_ZSET ZSetObject

这五种对象分别对应了Redis应用过程中看到的五种数据类型。

数据库中的key和value都是对象,而且key被限定为StringObject,所以创建一个key-value就至少创建了两个对象:一个StringObject的key和一个与数据类型对应的value的对象。

使用对象的优点

  • 可以根据value的类型判断命令是否合法;

  • 同一种类型在不同场景下可以使用不同的底层数据结构实现,优化内存使用效率;

  • 基于引用计数的内存回收和对象共享,以节约内存;

  • 命令访问时间记录,计算数据的空转时间,以清理数据空间;

数据结构

typedef struct redisObject {
    unsigned type:4;    // 对象类型
    unsigned encoding:4;    // 编码,负责解释ptr指向的内存区域中的数据
    void *ptr;    // 指向底层实现数据结构的内存区域

    int refCount;    // 引用计数
    unsigned lru:22;    // 最后一次被命令程序(除了OBJECT IDLETIME)访问到的时间
    ...
} robj;

查看type:TYPE {key}

查看encoding:OBJECT ENCODING {key}

encoding取值:

encoding 含义(对应的底层数据结构) OBJECT ENCODING输出
REDIS_ENCODING_INT long类型整数 int
REDIS_ENCODING_EMBSTR embstr编码的sds embstr
REDIS_ENCODING_RAW sds raw
REDIS_ENCODING_HT dict hashtable
REDIS_ENCODING_LINKEDLIST 双向链表linkedlist linkedlist
REDIS_ENCODING_ZIPLIST ziplist ziplist
REDIS_ENCODING_INTSET 整数集合 intset
REDIS_ENCODING_SKIPLIST zskiplist和dict skiplist

每种类型都至少有两种底层实现,即至少有两种encoding取值:

String INT, EMBSTR, RAW
List ZIPLIST, LINKEDLIST
Hash ZIPLIST, HT
Set INTSET, HT
ZSet ZIPLIST, SKIPLIST

encoding属性的好处:

  • 解绑了底层实现的数据结构与应用层的对象类型之间的关系;

  • 提升了Redis的灵活性和效率,优化内存,并在空间和时间两者之间进行了有效的trade-off。

2. StringObject

编码:int,embstr,raw

embstr:

  • 短字符串的优化编码;

  • 将redisObject和ptr指向的sdshdr两块内存放在一个连续的内存空间中,

    • 节省了内存分配/释放次数;

    • 能更好地利用缓存(因为可以整个一块内存进行统一一次性处理);

  • 只读,任意一个修改操作都会将embstr变成raw;

编码转换:

  • int:能用long表示的整数,任何非整数命令操作或产生非整数结果的操作都会导致编码变成raw;

  • 浮点数都是字符串表示;

  • 对embstr进行修改都变成raw;

  • incrby/decrby命令只能对encoding=int的数据进行操作;

3. ListObject



你可能感兴趣的:(Redis设计与实现 - chapter8 对象)