redis · 1 4 月, 2021 0

redis面向对象基本概念

在redis中主要用到的数据结构包括了简单动态字符串(SDS),双端链表,字典,压缩列表,整数集合等。

在redis中没有直接使用这些数据结构来实现键值对数据库, 而是基于这些数据结构创建一个对象系统. 这个系统包含了字符串对象,列表对象,哈希对象,集合对象有序集合对象五中类型。每种对象都用到了至少一种数据结构。

对象优点

  • 通过这五中不同类型的对象, Redis可以在执行命令之前, 根据对象的类型来判断一个对象是否可以执行给定的领命。

  • 可以针对不同的使用场景, 为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率。

内存回收机制

  • Redis对象系统基于引用计数法对内存进行回收。 当程序不在使用某个对象的时候, 这个对象所占用的内存就会被自动释放;

  • Redis还通过引用计数实现对象共享机制, 可以在适当条件下, 通过让多个数据库共享同一个对象来节约内存。

对象抛弃策略

Redis对象带有访问时间记录信息, 该信息可以用于计算数据库键的空转时长, 在服务器启用了maxmemory功能情况下, 空转时长较大的那些键可能会优先被服务器删除。

对象类型要编码策略

对象的创建

当我们在想Redis中创建一个键值对时, 我们至少会创建两个对象

  • 键对象: 用于存储键值对中的键信息

  • 值对象: 用于存储键值对中的值信息

对象的定义

typedef struct redisObject {
 // 类型
 unsigned type:4;
 // 编码
 unsigned encoding:4;
 // 指向底层实现数据结构的指针
 void *ptr;
}

 

Redis中每个对象由一个redisObject结构表示, 该结构中和保存数据有关的三个属性分别是type,encodingptr属性。

类型

对象的type属性记录了对象的类型。

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

对于Redis数据库保存的键值对来说, 键总是一个字符串对象, 而值则可以是字符串对象,列表对象,哈希对象,集合对象,有序集合对象中的一种。

type命令可以查看Redis中值对象的类型:

> RPUSH numbers 1 3 5

> TYPE msg
list

对象 对象type属性的值 TYPE命令的输出
字符串对象 REDIS_STRING “string”
列表对象 REDIS_LIST “list”
哈希对象 REDIS_HASH “hash”
集合对象 REDIS_SET “set”
有序集合对象 REDIS_ZSET “zset”

编码与底层实现

对象ptr指针指向对象的底层实现数据结构, 而这些数据结构由对象的encoding属性决定.

编码常量 编码所对应的底层数据结构
REDIS_ENCODING_INT long类型的整数
REDIS_ENCODING_EMBSTR embtr编码的简单动态字符串
REDIS_ENCODING_RAW 简单动态字符串
REDIS_ENCODING_HT 字典
REDIS_ENCODING_LINKEDLIST 双端链表
REDIS_ENCODING_ZIPLIST 压缩列表
REDIS_ENCODING_INTSET 整数集合
REDIS_ENCODING_SKIPLIST 跳跃表和字典

每种类型至少使用两种中不同的编码:

类型 编码 对象
REDIS_STRING REDIS_ENCODING_INT 使用整数值实现的字符串对象
REDIS_STRING REDIS_ENCODING_EMBSTR 使用embstr编码的简单动态字符串实现的字符串对象
REDIS_STRING REDIS_ENCODING_RAW 简单动态字符串实现的字符串对象
REDIS_LIST REDIS_ENCODING_ZIPLIST 使用压缩列表实现的列表对象
REDIS_LIST REDIS_ENCODING_LINKEDLIST 使用双端链表实现的列表对象
REDIS_HASH REDIS_ENCODING_ZIPLIST 使用压缩列表实现的哈希对象
REDIS_HASH REDIS_ENCODING_HT 使用字典实现的hash对象
REDIS_SET REDIS_ENCODING_INTSET 使用整数集合实现的集合对象
REDIS_SET REDIS_ENCODING_HT 使用字典实现的集合对象
REDIS_ZSET REDIS_ENCODING_ZIPLIST 使用压缩列表实现的有序集合对象
REDIS_ZSET REDIS_ENCODING_SKIPLIST 使用跳跃表和字典实现的有序集合对象

NOTE: 可以通过OBJECT ENCODING查看键值对象中的值对象的编码。

通过encoding属性来设定对象所使用的编码, 而不是为特定类型的对象关联一种固定的编码, 极大地提升了Redis的灵活性和效率, 因为Redis可以根据不同的使用场景来为一个对象设置不同的编码.

压缩列表和双端队列比较

  • 压缩列表比双端队列更节约内存, 并且在元素数量较少时, 在内存中以连续块方式保存的压缩列表比起双端链表可以更快被载入到缓存中.

  • 随着列表对象包含的元素越来越多, 使用压缩列表来保存元素的优势组件消失时, 对象就汇将底层实现从压缩列表向功能更强, 也适合保存大量元素的双端链表上面。