Redis数据类型底层数据结构

Redis目前基本的数据类型有String、List、Set、ZSet、Hash五种,首先Redis是C语言开发的,所以底层就是用C语言封装数据结构或者C语言本身提供的数据结构来存储。redis内部的主要数据结构主要有简单字符串(SDS)、双端链表、字典、压缩列表、跳跃表、整数集合。Redis内部并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个对象系统包含了我们所熟知的五种基本类型数据,也就是字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象。而它们每一种对象都使用到了至少一种前面所介绍的数据结构。下面介绍一下redis内部的主要几个数据结构简单字符串(SDS)、双端链表、压缩列表、跳跃表的定义。然后再介绍一下redis基本的五种数据类型,也就是五种类型的对象用到了上面的哪些数据结构。


redis的数据结构

SDS(Simple Dynamic String)简单字符串

1、redis定义:

2、使用范围:在redis里面,C本身的字符串只会作为字符串字面量(String literal)只用在一些不必对字符串值修改的地方,比如打印日志。

而redis需要使用字符串存储并且会修改的地方,都使用了SDS来存储。例如Key值。

3、优点:使用SDS来存储字符串的优点:

  • SDS的len属性直接记录了长度,获取字符串长度的复杂度为O(1)。
  • C字符串本身不记录长度容易产生缓存区溢出,而SDS杜绝了缓冲区的溢出。
  • C字符串本身不记录长度,每次修改都要重新分配内存,SDS减少了重新分配内存次数。
  • 优化了字符串缩短操作。并且可以保存任意格式的二进制数据,而C字符串必须含有编码。

链表(list)

1、链表:listNode结构来保存,多个listNode可以形成双向链表,redis定义了list表示头节点来持有链表,下图分别是节点listNode和链表list的定义。

1、redis定义:

  • 节点listNode

  • 链表list

2、使用范围:链表在redis中用作了列表键、发布与订阅、慢查询、监视器等


跳跃表(zskiplist)

1、跳跃表:是一种有序得数据结构,通过在每个节点上维持多个指向其他节点的指针,从而达到快速访问的目的,可以理解为改进版的双端链表,改进的手段是通过空间换取了时间。

2、复杂度:跳跃表支持平均O(logN)、最坏O(N)的查找复杂度,大部分条件下,跳跃表的效率可以和平衡树媲美,并且实现比平衡树简单。

  • 跳跃表节点zskiplistNode

  • 跳跃表zskiplist

2、跳跃表结构图:



仔细观察上图跳跃表的结构后,发现如果节点的层数越高,那么这个节点访问其他节点的速度就越快。换言之,level越高,代表了这个跳跃表的查找效率可能会比较高。当然并不是绝对的,因为redis每次创建跳跃表节点时,程序是根据幂次定律(越大的数出现概率越小), 生成层数高度。同时,节点的顺序是根据每个节点的分值排序的,如果分值相同,那么根据对象的大小排序。


压缩列表(ziplist)

1、压缩列表:是redis为了节省内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个压缩列表的可以包含多个节点,每个节点可以保存一个字节数组或者一个整数值。

2、压缩列表结构图:

3、压缩列表特点:

  • 是一种为节省内存开发的顺序性数据结构
  • 可以包含多个节点,每个节点保存一个字节数组或者整数值
  • 添加新节点到压缩列表,或者从压缩列表删除节点,可能会引发连锁更新操作,但是机率不高

Redis五种基本数据类型

上面提到过,redis并没有使用上面的数据结构直接用来实现键值对数据库,也就是常说的五种基本数据类型,而是创建了一个对象系统,这个系统包含了字符串对象,列表对象、哈希对象、集合对象、和有序集合对象这五种基本数据类型。这样做有一个好处是,我们可以针对不同的场景,对相同的数据类型对象使用不同的数据结构,来优化提高效率。

redisObject对象

1、对象:redis的键值对都是一个redisObject结构,该结构中有三个属性,type类型属性、encoding编码属性、ptr指向底层数据结构属性。

  • redisObject对象定义

  • 数据库的key值都是一个string字符串对象

2、编码常量:

String类型

字符串对象的编码是int、raw、embstr。参考上面的编码常量表,也就是说字符串类型的数据底层的数据结构使用的是整数、SDS、embstr编码的SDS。

1、编码转换

即上述几种编码会在何时转换,也就是redis底层决定用什么存储字符串数据?。

当int类型的编码通过操作存储的是字符串值,那么字符串对象的编码将从int变为raw。


List类型

列表对象的编码可以是zipList压缩列表linkedlist双端链表

1、编码转换

即上述两种编码会在何时转换,也就是redis底层什么时候会用压缩列表存储列表数据?什么时候会使用双端链表存储列表数据。

当列表同时满足以下两个条件时,列表对象会使用zipList编码,也就是压缩列表

  • 列表对象保存的所有字符串元素的长度都小于64字节
  • 列表保存的元素少于512个,

2、配置

上述两个条件是支持配置的,也就是说我们可以redis直接读取我们的配置,来决定列表list类型底层使用什么样的数据结构来存储数据

  • list-max-ziplist-value
  • list-max-ziplist-entries

Set类型

集合对象使用的是intset整数集合(intset底层使用的是整数集合数据结构)或者hashtable哈希表(hashtable底层使用的是字典数据结构,我们并没有在本文做详细介绍,有需要可以自己了解)

1、编码转换

当集合对象同时满足下面两个条件,会使用intset编码

  • 集合对象保存的所有对象都是整数值
  • 集合对象保存的元素数量小于512个;

2、配置

上述第二个条件是支持配置的。

  • set-max-intset-entries

ZSet类型

有序集合的编码使用的是ziplist压缩列表skiplist跳跃表

注意:上面介绍skiplist的时候我们可以从结构图中明显看到存储集合元素的时候,score在每个节点中式如何存储的。那么如果ZSet使用的式ziplist压缩列表,redis怎么存储score和value值呢?其实很简单,每个集合的元素都使用两个节点来存储,第一个节点保存的是成员(member),第二个元素保存的是元素的分值(score)

1、编码转换

当有序集合对象可以同时满足以下两个条件时,使用ziplist编码

  • 有序集合的所有元素长度都小于64字节
  • 有序集合的元素数量小于128个;

2、配置

上述两个条件是支持配置的。

  • zset-max-ziplist-value
  • zset-max-ziplist-entries

Hash类型

哈希对象使用的是ziplist压缩列表hashtable哈希表。(hashtable底层使用的是字典数据结构,我们并没有在本文做详细介绍,有需要可以自己了解)

1、编码转换

当哈希对象同时满足下面两个条件,使用ziplist压缩列表

  • 哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
  • 哈希对象保存的键值对的数量小于512个;

2、配置

上述两个条件是支持配置的。

  • hash-max-ziplist-value
  • hash-max-ziplist-entries


Redis基本数据类型底层数据结构的更多相关文章

  1. Redis 概念以及底层数据结构

    Redis 简介 REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C ...

  2. redis 列表的底层数据结构链表

    当一个列表键包含了数量比较多的元素,又或者列表中包含的的元素都是比较长的字符串,Redis就会使用链表作为列表键的底层实现 每个列表节点的数据结构为 列表数据接口中保存了 该节点前置节点的指针.后置节 ...

  3. Redis常用数据类型底层数据结构分析

    Redis是一种键值(key-Value)数据库,相对于关系型数据库,它也被叫作非关系型数据库 Redis中,键的数据类型是字符串,但是为了非富数据存储方式,方便开发者使用,值的数据类型有很多 字符串 ...

  4. Redis学习笔记(二)redis 底层数据结构

    在上一节提到的图中,我们知道,可以通过 redisObject 对象的 type 和 encoding 属性.可以决定Redis 主要的底层数据结构:SDS.QuickList.ZipList.Has ...

  5. redis基本数据类型和对应的底层数据结构

    Redis的数据类型包含string,list,hash,set,sorted set. Redis中定义了一个对象的结构体: /* * Redis 对象 */ typedef struct redi ...

  6. 说一下redis中5种数据类型的底层数据结构

      前言: 阅读 redis设计与实现 一书的记录.未完待续... redis我们都知道有5种数据类型,分别是string,list,hash,set,zset,那么你知道它们的底层数据结构实现吗? ...

  7. Redis不同数据类型的的数据结构实现

    我们知道Redis支持五种数据类型, 分别是字符串.哈希表(map).列表(list).集合(set)和有序集合,和Java的集合框架类似,不同数据类型的数据结构实也是不一样的. >>Re ...

  8. 深入理解Redis:底层数据结构

    简介 redis[1]是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...

  9. Redis 的几种数据结构&五种数据类型对象

    先看几种数据结构 通过分析底层的数据结构,学习如何根据场景选型和设计 1,简单动态字符串 redis使用的字符串SDS有别于C语言中的字符串 a, 结构 free字段为已分配但未使用的空间 len为已 ...

随机推荐

  1. Python 实现断网自动重连

    为了实现 断网了,自动连接网络原理:每隔一段时间ping一下百度,判断网络状态,没有联网的话,就模仿浏览器发一条Post给服务器import urllibimport hashlibimport su ...

  2. JavaScript常用的Hook脚本

    JavaScript常用的Hook脚本 本文Hook脚本 来自 包子 页面最早加载代码Hook时机 在source里 用dom事件断点的script断点 然后刷新网页,就会断在第一个js标签,这时候就 ...

  3. Visual Studio 重置窗口布局

    Visual Studio 重置窗口布局

  4. springboot整合rabbitmq实现生产者消息确认、死信交换器、未路由到队列的消息

    在上篇文章  springboot 整合 rabbitmq 中,我们实现了springboot 和rabbitmq的简单整合,这篇文章主要是对上篇文章功能的增强,主要完成如下功能. 需求: 生产者在启 ...

  5. Noip模拟57 2021.9.20

    规律总结:联考必爆炸 T1 2A 没$A$掉的大水题,但是是真的不知道$000$前面的$00$也算先导$0$,以后要长记性,这种东西不能再错了 再打三遍: $000$前面的$00$也算先导$0$ $0 ...

  6. Noip模拟22 2021.7.21

    T1 d 简化题意就是找到相对平均长宽的偏移量较大的矩形给他删掉 可以说是个贪心,按照a,b分别为第一关键字排序 然后假装删去要求的那么多个按a排序的较小的,然后再去b中, 找到 删去的a中的那几个矩 ...

  7. stm32看门狗详细解答,看了觉得一下子明白了很多

    一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...

  8. Beam Search快速理解及代码解析

    目录 Beam Search快速理解及代码解析(上) Beam Search 贪心搜索 Beam Search Beam Search代码解析 准备初始输入 序列扩展 准备输出 总结 Beam Sea ...

  9. Unmount and run xfs_repair

    参考连接:https://blog.csdn.net/qq_35022803/article/details/109287086 如故障图所示,sda3出现问题, 下面的解决办法: 解决办法: 原因: ...

  10. SpringBoot 整合 Mybatis-Plus + Mysql

    mybatis-plus是mybatis的一款插件,它的主要作用是快速开发,省略mybatis的配置,具体的功能请参照官网. 开发环境: springboot,maven,mybatis-plus,m ...