blogposts

(Redis系列第二篇)Redis数据结构一览

yirufeng

1072字约4分钟

RedisRedis系列

2024-05-12

背景

很多人了解Redis主要从数据结构着手,其实日常工作中我们使用的都是Redis对象的操作命令,包括字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象。每一种对象底层对应了多种不同数据结构

  • Redis并没有直接使用数据结构来实现键值对数据库,而是基于数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象,每种对象都用到了多种数据结构。通过这五种不同类型的对象,Redis可以在执行命令之前,根据对象的类型来判断一个对象是否可以执行给定的命令。使用对象的另一个好处是,可以针对不同的使用场景,为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率。
  • Redis的对象系统还实现了基于引用计数技术的内存回收机制,当程序不再使用某个对象的时候,这个对象所占用的内存就会被自动释放;
  • Redis还通过引用计数技术实现了对象共享机制,这一机制可以在适当的条件下,通过让多个数据库键共享同一个对象来节约内存。
  • Redis的对象带有访问时间记录信息,该信息可以用于计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的那些键可能会优先被服务器删除。

Redis对象系统介绍

对于Redis数据库保存的键值对来说,键总是一个字符串对象,而值则可以是字符串对象、列表对象、哈希对象、集合对象或者有序集合对象的其中一种。 Redis使用对象来表示数据库中的键和值,每次当我们在Redis的数据库中新创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(值对象)。

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

对象详解

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

  • type属性记录了对象的类型,可以是如下类型(REDIS_STRINGREDIS_LISTREDIS_HASHREDIS_SETREDIS_ZSET)中的一种。TYPE命令返回数据库键对应的值对象的类型
  • ptr指针指向对象的底层实现数据结构,而这些数据结构由对象的encoding属性决定。
  • encoding属性记录了对象所使用的编码,也即是说这个对象使用了什么数据结构作为对象的底层实现,这个属性的值可以是REDIS_ENCODING_INTREDIS_ENCODING_EMBSTRREDIS_ENCODING_RAWREDIS_ENCODING_HTREDIS_ENCODING_LINKEDLISTREDIS_ENCODING_ZIPLISTREDIS_ENCODING_INTSETREDIS_ENCODING_SKIPLIST的其中一个
SyntaxDescription
HeaderTitle
ParagraphText

123 每一个Redis数据结构都是有雨

● 当我们称呼一个数据库键为“字符串键”时,我们指的是“这个数据库键所对应的值为字符串对象”; ● 当我们称呼一个键为“列表键”时,我们指的是“这个数据库键所对应的值为列表对象” ● TYPE命令的实现方式也与此类似,当我们对一个数据库键执行TYPE命令时,命令返回的结果为数据库键对应的值对象的类型,而不是键对象的类型:

对象类型有5种,但是底层数据结构(内部编码)对应8种 。


Redis主要数据结构一览

  • 简单动态字符串(SDS)
  • 双端链表
  • 字典
  • 压缩列表
  • 数据集合

数据结构具体实现

No Pains, No Gains