概述:

    学习使用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. 个人学习JQ插件编写成果:little酷炫的图片滑动切换效果

    工作一个多月了,好久没来冒冒泡了,看了@wayong的JQ插件教程,自己编写了一个模仿拉勾网首页广告栏滑动特效的JQ插件,现在跟朋友们分享分享! 先上demo链接:http://runjs.cn/de ...

  2. leetcode 第42题 Multiply Strings

    题目:Given two numbers represented as strings, return multiplication of the numbers as a string. Note: ...

  3. 【UNIX网络编程(一)】套接字地址结构、网络字节顺序和地址转换功能

    介绍:应该用在网络编程实现每个套接字地址结构.所以主套接字地址结构后前提网络计划编制,地址结构可以在两个方向上发送:从工艺到内核和内核处理.构中的二进制值之间进行转换. 大多数套接字函数都须要一个指向 ...

  4. 01.由浅入深学习.NET CLR 基础系列之CLR 的执行模型

    .Net 从代码生成到执行,这中间的一些列过程是一个有别于其他的新技术新概念,那么这是一个什么样的过程呢,有什么样的机制呢,清楚了这些基本的东西我们做.Net的东西方可心中有数.那么,CLR的执行模型 ...

  5. 12个很少被人知道的CSS事实

    之前没有认真的研究过,padding-bottom的值如果是百分比,那么它的实际值是根据父类的宽度来调整的.我还以为是根据这个元素的本身的宽度来定义呢?汗..padding-top/padding-l ...

  6. ASP.NET WebApi 入门

    今天参照微软官方(http://www.asp.net)学习了WebApi,在这里摘录如下: 前言 HTTP 不只是为了生成 web 页面.它也是一个强大的平台,可以建设公开服务和数据的 Api.HT ...

  7. C# 求精简用一行代码完成的多项判断 重复赋值

    C# 求精简用一行代码完成的多项判断 重复赋值 哈哈,说实话,个人看着这么长的三元操作也麻烦,但是我也只想到了这样三元判断句中执行方法体能够写到一行,追求的终极目的是,用一行实现这个过程,而且简单,由 ...

  8. C++拷贝构造函数总结

    C++拷贝构造函数总结 目录: 拷贝构造函数的基础知识 拷贝构造函数的使用 拷贝构造函数的行为 1.拷贝构造函数的基础知识 拷贝构造函数(copy constructor)是构造函数,是拷贝已经存在的 ...

  9. [译]反-反汇编 & 混淆 #1: 苹果没有遵循自己制定的Mach-O规范?

    原文地址:http://reverse.put.as/2012/02/02/anti-disassembly-obfuscation-1-apple-doesnt-follow-their-own-m ...

  10. dyld binding test

    ========================================================================= a.c ---------------------- ...