概述:

    学习使用Redis,其实并不需要去研究其底层数据的实现。我们只需要了解他有哪些常用的数据类型,然后熟练使用,就可以很好的掌握Redis 这个工具了。但是这样的学习方法只适合Redis 的入门,“工欲善其事必先利其器”,我们想要用好Redis,则必须深入了解Redis 的底层到底是如何实现的,我们在选择数据结构的时候才能做出正确的选择。

    在上一篇博客《深入浅出Redis-redis底层数据结构(上)》中,我们已经讲解了Redis 中的 动态字符串,链表,字典

    在这里我们简单回顾一下他们的特点:

      1、动态字符串SDS:区别于C语言字符串,具有良好的伸缩性,在获取字符串长度,字符串修改,防止缓存区溢出等性能都比C语言字符串好

      2、链表:顺序存储对象信息,有用于缓存链表长度的属性,在插入删除对象功能中有良好性能,避免环的产生

      3、字典:key-value 存储方式,通过hash值计算,判断key的存储,当容量过大,会通过rehash重新分配字典大小

5、跳跃表


  5.1 概述

    跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳跃表是一种随机化的数据,跳跃表以有序的方式在层次化的链表中保存元素,效率和平衡树媲美 ——查找、删除、添加等操作都可以在对数期望时间下完成,并且比起平衡树来说,跳跃表的实现要简单直观得多。

    Redis 只在两个地方用到了跳跃表,一个是实现有序集合键,另外一个是在集群节点中用作内部数据结构

  

  5.2 跳跃表的定义

    我们先来看一下一整个跳跃表的完整结构:

     Redis 的跳跃表 主要由两部分组成:zskiplist(链表)和zskiplistNode (节点)

    

   5.2.1 zskiplistNode(节点) 数据结构:

typedef struct zskiplistNode{
   //层
struct zskiplistLevel{
     //前进指针
struct zskiplistNode *forward;
    //跨度
unsigned int span;
} level[];
  //后退指针
struct zskiplistNode *backward;
  //分值
double score;
  //成员对象
robj *obj;
}

    1、层:level 数组可以包含多个元素,每个元素都包含一个指向其他节点的指针。

    2、前进指针:用于指向表尾方向的前进指针

    3、跨度:用于记录两个节点之间的距离

    4、后退指针:用于从表尾向表头方向访问节点

    5、分值和成员:跳跃表中的所有节点都按分值从小到大排序。成员对象指向一个字符串,这个字符串对象保存着一个SDS值

   5.2. zskiplist 数据结构:

typedef struct zskiplist {
//表头节点和表尾节点
structz skiplistNode *header,*tail;
//表中节点数量
unsigned long length;
//表中层数最大的节点的层数
int level; }zskiplist;

    

     从结构图中我们可以清晰的看到,header,tail分别指向跳跃表的头结点和尾节点。level 用于记录最大的层数,length 用于记录我们的节点数量。

  5.3 总结

  •  跳跃表是有序集合的底层实现之一
  • 主要有zskiplist 和zskiplistNode两个结构组成
  • 每个跳跃表节点的层高都是1至32之间的随机数
  • 在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的对象必须是唯一的
  • 节点按照分值的大小从大到小排序,如果分值相同,则按成员对象大小排序

6、整数集合(Intset)


  6.1 概述

    《Redis 设计与实现》 中这样定义整数集合:“整数集合是集合建的底层实现之一,当一个集合中只包含整数,且这个集合中的元素数量不多时,redis就会使用整数集合intset作为集合的底层实现。”

    我们可以这样理解整数集合,他其实就是一个特殊的集合,里面存储的数据只能够是整数,并且数据量不能过大。

  6.2 整数集合的实现

    

typedef struct intset{
//编码方式
uint32_t enconding;
// 集合包含的元素数量
uint32_t length;
//保存元素的数组
int8_t contents[]; }

  我们观察一下一个完成的整数集合结构图:

  

    1、encoding:用于定义整数集合的编码方式

    2、length:用于记录整数集合中变量的数量

3、contents:用于保存元素的数组,虽然我们在数据结构图中看到,intset将数组定义为int8_t,但实际上数组保存的元素类型取决于encoding

  6.3 整数集合的升级

    在上述数据结构图中我们可以看到,intset 在默认情况下会帮我们设定整数集合中的编码方式,但是当我们存入的整数不符合整数集合中的编码格式时,就需要使用到Redis 中的升级策略来解决

    Intset 中升级整数集合并添加新元素共分为三步进行:

      1、根据新元素的类型,扩展整数集合底层数组的空间大小,并为新元素分配空间

        2、将底层数组现有的所有元素都转换成新的编码格式,重新分配空间

      3、将新元素加入到底层数组中

   比如,我们现在有如下的整数集合:

    我们现在需要插入一个32位的整数,这显然与整数集合不符合,我们将进行编码格式的转换,并为新元素分配空间:

    第二步,将原有数据他们的数据类型转换为与新数据相同的类型:(重新分配空间后的数据)

    

    第三部,将新数据添加到数组中:

  

  6.3.1 整数集合升级的好处

      1、提升灵活性

      2、节约内存

  6.4 总结

    整数集合是集合建的底层实现之一

    整数集合的底层实现为数组,这个数组以有序,无重复的范式保存集合元素,在有需要时,程序会根据新添加的元素类型改变这个数组的类型

    升级操作为整数集合带来了操作上的灵活性,并且尽可能地节约了内存

    整数集合只支持升级操作,不支持降级操作

7、压缩列表


  7.1 概述

    压缩列表是列表键和哈希键的底层实现之一。当一个列表键只把汗少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,那么Redis 就会使用压缩列表来做列表键的底层实现。

  

  7.2 压缩列表的构成

    一个压缩列表的组成如下:

  

    1、zlbytes:用于记录整个压缩列表占用的内存字节数

    2、zltail:记录要列表尾节点距离压缩列表的起始地址有多少字节

    3、zllen:记录了压缩列表包含的节点数量。

    4、entryX:要说列表包含的各个节点

    5、zlend:用于标记压缩列表的末端

  7.3 总结

    压缩列表是一种为了节约内存而开发的顺序型数据结构

    压缩列表被用作列表键和哈希键的底层实现之一

    压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者整数值

    添加新节点到压缩列表,可能会引发连锁更新操作。

深入浅出Redis-redis底层数据结构(下)的更多相关文章

  1. Redis(二)--- Redis的底层数据结构

    1.Redis的数据结构 Redis 的底层数据结构包含简单的动态字符串(SDS).链表.字典.压缩列表.整数集合等等:五大数据类型(数据对象)都是由一种或几种数结构构成. 在命令行中可以使用 OBJ ...

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

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

  3. Redis详解(四)------ redis的底层数据结构

    上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redis 中,这几种数据类型底层是由什么数据结构构造的呢?本篇博客我们就来详细介绍Redis中五大数据类型的底层实现. 1.演示数据类 ...

  4. Redis 的底层数据结构(对象)

    目前为止,我们介绍了 redis 中非常典型的五种数据结构,从 SDS 到 压缩列表,这都是 redis 最底层.最常用的数据结构,相信你也掌握的不错. 但 redis 实际存储键值对的时候,是基于对 ...

  5. Redis 详解 (四) redis的底层数据结构

    目录 1.演示数据类型的实现 2.简单动态字符串 3.链表 4.字典 5.跳跃表 6.整数集合 7.压缩列表 8.总结 上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redis 中, ...

  6. redis string底层数据结构sds

    redis的string没有采用c语言的字符串数组而采用自定义的数据结构SDS(simple dynamic string)设计 len 为字符串的实际长度  在redis中获取字符串的key长度的时 ...

  7. Redis 的底层数据结构(SDS和链表)

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.可能几乎所有的线上项目都会使用到 Redis,无论你是做缓存.或是用作消息中间件,用起来很简单方便 ...

  8. Redis 的底层数据结构(字典)

    字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...

  9. Redis 的底层数据结构(跳跃表)

    字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...

  10. Redis 的底层数据结构(整数集合)

    当一个集合中只包含整数,并且元素的个数不是很多的话,redis 会用整数集合作为底层存储,它的一个优点就是可以节省很多内存,虽然字典结构的效率很高,但是它的实现结构相对复杂并且会分配较多的内存空间. ...

随机推荐

  1. Linux的文件夹配置

    学习linux我个人认为首先须要了解清楚在系统中没给目录的详细事干什么的才行,这样在以后的学习其中以及在使用linux系统的过程中才会事半功倍. /bin 主要内容是系统的运行文件,可是/bin中的运 ...

  2. Mvc 下载文件

    你如何将文件传送给用户取决于你最开始如何存储它,如果你将文件存入数据库,你会用流的方式将文件返还给用户,如果你将文件存在硬盘中,你只需要提供一个超链接即可,或者也可以以流的方式.每当你需要以流的方式将 ...

  3. poj3744高速功率矩阵+可能性DP

    Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4410   Accepted: 1151 Descr ...

  4. avalonjs 1.3.7发布

    avalonjs 1.3.7发布 又到每个月的15号了,现在avalon已经固定在每个月的15号发布新版本.这次发布又带来许多新特性,让大家写码更加轻松,借助于“操作数据即操作DOM”的核心理念与双向 ...

  5. zepto.js的基本介绍与使用

    最近看到了一篇文章,是介绍一种新的js框架,名为zepto.js,他适用于移动设备已经桌面浏览器除了ie系列的.. 他兼容jquery的API,所以学起来或用起来并不吃力.他比jquery的优势在于1 ...

  6. C# 通讯网关开发

    C# 通讯网关开发 楼主从12年毕业大部分时间一直从事于通讯网关的开发,刚刚学那会连C#是啥都不知道,就直接入手网关开发,前前后后到现在也算是弄了5.6个通讯协议,后来看到北风之神的socket框架和 ...

  7. SharePoint 2013常用开发工具

    SharePoint 2013常用开发工具分享 2014-04-01 00:59 by jv9, 589 阅读, 1 评论, 收藏, 编辑 众所周知,一款好的开发工具不仅能提高项目开发效率,而且能够协 ...

  8. 持续集成 windows下jenkins常见问题填坑

    [过程改进]持续集成 windows下jenkins常见问题填坑 没有什么高深的东西,1 2天的时间大多数人都能自己摸索出来,这里将自己遇到过的问题分享出来避免其他同学再一次挖坑. 目录 1. 主从节 ...

  9. let和const关键词

    ECMAScript 6中的let和const关键词 2013-11-28 21:46 by BarretLee, 21 阅读, 0 评论, 收藏, 编辑 ECMAScript 6中多了两个定义变量的 ...

  10. 生活沉思录 via 哲理小故事(四)

    1.围墙里的墓碑 第一次世界大战期间,驻守意大利某小镇的年轻军官结识了镇上的牧师.虽然军官信仰信教,而牧师是天主教牧师,但两人一见如故. 军官在一次执行任务中身负重伤,弥留之际嘱托牧师无论如何要把自己 ...