Redis的数据类型

Redis 支持五种数据类型:

  • string
  • hash
  • list
  • set
  • zset

String

string 是最基本的类型。string 二进制安全,即可以包含任何数据。

string 一个键最大能存储512MB。

string 类型的数据结构存储方式有三种intrawembstr

int

Redis 中规定假如存储的是整数型值,比如set num 123这样的类型,就会使用int的存储方式进行存储,在redisObjectptr属性中就会保存该值。

SDS

假如存储的字符串是一个字符串值并且长度大于32个字节就会使用 SDS(simple dynamic string)方式进行存储,并且encoding设置为raw;若是字符串长度小于等于32个字节就会将encoding改为embstr来保存字符串。

SDS称为简单动态字符串,对于SDS中的定义在Redis的源码中有的三个属性int lenint freechar buf[]

len保存了字符串的长度,free表示buf数组中未使用的字节数量,buf数组则是保存字符串的每一个字符元素。

因此当你在Redis中存储一个字符串"Hello_World"时,SDS 的形式的redisObject结构图如下图所示:

Hash

Redis hash 是一个键值(key=>value)对集合

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

每个 hash 可以存储 23212^{32} -1 键值对。

Hash对象的实现方式有两种分别是ziplisthashtable,其中hashtable的存储方式key是 String 类型的,value也是以key value的形式进行存储。

ziplist

压缩列表(ziplist)是一组连续内存块组成的顺序的数据结构,压缩列表能够节省空间,压缩列表中使用多个节点来存储数据。

压缩列表是列表键和哈希键底层实现的原理之一,压缩列表并不是以某种压缩算法进行压缩存储数据,而是它表示一组连续的内存空间的使用,节省空间,压缩列表的内存结构图如下:

其中:

  1. zlbytes:4个字节的大小,记录压缩列表占用内存的字节数。
  2. zltail:4个字节大小,记录表尾节点距离起始地址的偏移量,用于快速定位到尾节点的地址。
  3. zllen:2个字节的大小,记录压缩列表中的节点数。
  4. entry:表示列表中的每一个节点。
  5. zlend:表示压缩列表的特殊结束符号'0xFF'

每一个entry节点又有三部分组成,分别是previous_entry_lengthencodingcontent

  1. previous_entry_length表示前一个节点entry的长度,可用于计算前一个节点的其实地址,因为他们的地址是连续的。
  2. encoding:这里保存的是content的内容类型和长度。
  3. contentcontent保存的是每一个节点的内容。

hashtable

hashtable 是一种字典类型的数据结构,用于存储键值对,其中键是字符串类型,值可以是字符串、列表、集合或有序集合。hashtable 的底层实现是一个数组,每个数组元素是一个链表,用于解决哈希冲突。当 hashtable 中的键值对数量变化时,会进行扩展或收缩操作,重新分配数组的大小和哈希值。hashtable 是哈希键和集合键的底层实现之一,当这些键的元素数量和长度较大时,Redis 会使用 hashtable 作为其存储方式。

List

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部。

列表最多可存储 23212^{32} - 1 元素。

Redis中的列表在3.2之前的版本是使用ziplistlinkedlist进行实现的。在3.2之后的版本就是引入了quicklist

linkedlist

linkedlist 是一个双向链表,他和普通的链表一样都是由指向前后节点的指针。插入、修改、更新的时间复杂度是 O(1),查询的时间复杂度是 O(n)。其特性为

  1. 每一个节点都有指向前一个节点和后一个节点的指针。
  2. 头节点和尾节点的prevnext指针指向为null,所以链表是无环的。
  3. 链表有自己长度的信息,获取长度的时间复杂度为 O(1)。

quicklist

quicklist 实际上是 zipList 和 linkedList 的混合体,它将 linkedList 按段切分,每一段使用 zipList 来紧凑存储,多个 zipList 之间使用双向指针串接起来。

  1. prevnext指向该节点的前后节点。
  2. zl指向该节点对应的 ziplist 结构。
  3. sz代表整个 ziplist 结构的大小。
  4. encoding代表采用的编码方式:1代表是原生的,2代表使用LZF进行压缩。
  5. container为 quickListNode 节点zl指向的容器类型:1代表none2代表使用ziplist存储数据。
  6. recompress代表这个节点之前是否是压缩节点,若是,则在使用压缩节点前先进行解压缩,使用后需要重新压缩,此外为1,代表是压缩节点。
  7. attempted_compress测试时使用。
  8. extra为预留。

Set

Redis 的 Set 是 string 类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

集合中最大的成员数为 23212^{32} - 1

Redis 中列表和集合都可以用来存储字符串,但是 Set 是不可重复的集合,而 List 列表可以存储相同的字符串

Set 的底层实现是hashtableintset

intset

inset 也叫做整数集合,用于保存整数值的数据结构类型,它可以保存int16_tint32_t 或者int64_t 的整数值。

在整数集合中,有三个属性值encoding、length、contents[],分别表示编码方式、整数集合的长度、以及元素内容,length就是记录contents里面的大小。

在整数集合新增元素的时候,若是超出了原集合的长度大小,就会对集合进行升级,具体的升级过程如下:

  1. 首先扩展底层数组的大小,并且数组的类型为新元素的类型。
  2. 然后将原来的数组中的元素转为新元素的类型,并放到扩展后数组对应的位置。
  3. 整数集合升级后就不会再降级,编码会一直保持升级后的状态。

Zset

Redis zset 和 set 一样也是 string 类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。

zset 的成员是唯一的,但分数(score)却可以重复。

zset 的底层实现是ziplistskiplist

skipset

skiplist 也叫做跳跃表,跳跃表是一种有序的数据结构,它通过每一个节点维持多个指向其它节点的指针,从而达到快速访问的目的。

skiplist 由如下几个特点:

  1. 有很多层组成,由上到下节点数逐渐密集,最上层的节点最稀疏,跨度也最大。
  2. 每一层都是一个有序链表,只扫包含两个节点,头节点和尾节点。
  3. 每一层的每一个每一个节点都含有指向同一层下一个节点和下一层同一个位置节点的指针。
  4. 如果一个节点在某一层出现,那么该以下的所有链表同一个位置都会出现该节点。

Redis的数据类型
https://ivansnow02.github.io/posts/14492/
作者
Ivan Snow
发布于
2023年4月24日
许可协议