redis的数据结构及算法实现

717 阅读3分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

redis的数据结构及算法实现

整体redis介绍

redis是简单的键值数据库,也就是使用键去获取值的过程.而不是像关系型数据库那样复杂的数据结构

redis是在内存中进行操作的,所以操作数据的时候需要考虑主机的内存使用情况

常见的数据类型包括:字符串(string)、列表(List)、集合(set)、有序集合(zset)、字典(hash对象)

除此之外还有类似geospatial(存储地理经纬度)、hyperloglog(集合的个数)、bitmap(位图),不做赘述,百度一大堆(其实也有自己的实际使用场景,可以了解下面试和面试官吹一下)

List(列表)

redis中使用的list包括两部分

  • 压缩列表(列表中存储的数据量较小时使用)
  • 双向循环列表()

压缩列表 需要满足一下两个条件

  1. 单个数据小于64字节
  2. 列表中数据小于512个

一片连续的空间存储数据,每个节点的大小可能不同(相对于数组唯一不同就是数组的每个节点都是一样大小的,这样会因为有些数据大小小于节点大小,从而造成了内存浪费.所以这个地方也就体现了压缩的概念)

特点:

  1. 内存占用较小
  2. 支持多种类型的数据存储

双向循环列表

// 以下是C语言代码,因为Redis是用C语言实现的。
typedef struct listnode {
  struct listNode *prev;
  struct listNode *next;
  void *value;
} listNode;


typedef struct list {
  listNode *head;
  listNode *tail;
  unsigned long len;
  // ....省略其他定义
} list;

另外有一个list字段来表示头指针、尾指针和列表的长度

hash

是压缩列表和散列表两种方式实现

使用压缩列表实现与上述条件一致

散列表 使用MurmurHash2作为散列算法,特点是运行速度快、随机性好.同时redis还支持散列表的动态扩容、缩容

当数据动态增加之后,散列表的装载因子会不停地变大。为了避免散列表性能的下降,当装载因子大于 1 的时候,Redis 会触发扩容,将散列表扩大为原来大小的 2 倍左右.当装载因子小于 0.1 的时候,Redis 就会触发缩容

扩容和缩容会涉及数据的搬移和hash值的重新计算,很消耗资源

set

实现包括以下两种

  • 有序数组
  • 散列表

set集合主要是不重复的数据

有序数组的条件是

  • 存储的数据都是整数;
  • 存储的数据元素个数不超过 512 个。

zset

有序集合

实现方式

  • 压缩列表
  • 跳表

压缩列表的条件是

  • 所有数据的大小都要小于 64 字节;
  • 元素个数要小于 128 个。

那么redis这种数据类型如何进行持久化操作呢

键值对的值会支持多种数据类型.这样的话存储的时候还需要将其对应的结构存储在磁盘中吗

  1. 只存储数据,数据结构只是一个标识,当需要还原的时候再还原成对应的数据类型,这样的话还原会很消耗资源来进行这个操作
  2. 数据结构与数据都存储