第八课——跳跃表、对象

第八课时作业

静哥

by 2016.4.11~2016.4.17

 

【作业描述】

1.总结redis在节省内存开销方面做过哪些设计

2.总结概括五种对象的关键点

【作业-1:总结redis在节省内存开销方面做过哪些设计】

  1. 关于跳跃表

(1)跳跃表是一种有序数据结构,查询效率和平衡树媲美,实现上比平衡树简单,可以用跳跃表代替平衡树;查找复杂度平均是O(logN)z,最坏是O(N);

(2)跳跃表在redis里只有2个地方使用:一个是实现有序集合键(sorted set)、一个是集群节点中用作内部数据结构;也就是说,跳跃表是sorted set类型的底层实现之一;

(3)每个节点都有层高,层高越高,查找效率越高;存储节点的时候,随机生成1-32之间的随机数,假设生成的层高随机数为N,则,该节点数值在第一层~第N层都会被插入,且每层的数据都是有序的,这样在查找该节点时从最高层依次查找,最高层查不到,接着查次高层;

(4)同节点的层次直接通过数组实现,不是通过链表

  1. 关于整数集合

整数集合(intset)就是将所有整数类型封装到intset这个结构体里,根据实际存储的数据长度来动态选择使用哪种数据类型;

(1)整数类型有int16_t   int32_t   int64_t等;分别表示的整数范围如下:

(2)整数集合(intset)将所有整数类型封装的目的是:减少内存使用。可以根据存入的整数数值大小,动态选择用int16_t类型的还是int32_t类型的等;

当设置一个集合后,会判断集合里元素的整数值大小,最大的元素是什么类型的整数,就会将intset设置为该类型;例如一个集合里最大的元素是50000,那么这个集合的数据类型就是int32_t类型的,其他元素值也将被设置为int32_t类型;一个集合里最大的元素是30000,那么这个结婚的数据类型就是in16_t类型的;

例如:新增一个元素,该元素长度超过原来的类型范围,就需要类型升级,例如从int16_t升级到int32_t;

  1. 关于对象

(1)Redis里说的SDS字符串、链表、字典。压缩列表、整数集合等都是数据结构,redis并没有直接使用数据结构来实现键值对数据库,而是创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象、有序集合对象这5种类型的对象;通过不同类型的对象来判断一个对象是否可以执行给定的命令。

(2)redis的对象系统还实现基于引用计数技术的内存回收机制:有个引用计数参数,通过识别这个参数判断对象是否被使用,没有被引用则是否该对象的内存;此外,还实现了对象共享机制,一定条件下,可以多个数据库共享一个对象来节约内存;

(3)redis的5种数据类型,都是通过redisObject结构体来实现的,通过对该结构体的引用,根据实际使用生成5种数据类型的对象;结构体如下:

(3.1)Type属性表示类型,type:4的意思是定义属性type,占4个比特,unsigned等同于unsigned int;

(3.2)Encoding属性也占4个比特位;lru属性占24个比特位;

也就是type属性、encoding属性、lru属性合在一起,占用32个比特,也就是4个字节;

(3.3)Refcount属性,是int类型,占4个字节;ptr属性也占用4个字节;

综上,redisObject结构体一共占用12个字节,也就是redisObject结构体,巧妙运用位字段,节省内存,同时相对直接操纵位来编程也更容易。

(3.4)Type属性对应的值有5种,也就是5种对象类型:REDIS_STRING/REDSI_LIST/REDIS_HASH/REDIS_SET/REDIS_ZSET

(3.5)Encoding属性表示编码类型:5种对象类型,对应不同的编码类型,会有不同的底层实现;即,编码不同,底层支撑的数据结构不同;

Redis在减少内存开销方面做的设计:(1)整数集合;(2)定义redisObject一个结构体,来实现5种数据类型的引用,也即是5种对象;redisObject结构体里,定义type属性区分5种数据类型,多种底层存储结构支撑;而且,redisObject结构体里的type属性、encoding属性、lru属性是用位字段定义的,巧妙运用位字段,节省内存;

【作业-2:总结概括五种对象的关键点】

  1. 字符串对象
  2. 字符串对象有3种类型实现:int类型、raw类型、embstr类型;
  3. Int,如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型表示;
  4. raw,如果保存的是字符串,且长度大于39字节;
  5. embstr,如果保存的是字符串,且长度小于等于39字节;(embstr与raw一样,使用sds简单动态字符串结构;和redisObject结构一起分片和回收,因此只需要分配或回收一次;embstr的内存回收更快,因为redisObject和sdshdr内存是连续的;)

RawL类型的字符串长度大于39字节,不利于连续内存的分配,因此Raw类型的内存分片不是连续的;

可以用object encoding命令来查看数据的底层存储结构;

(2)

 

 

  1. 列表对象
  2. 列表对象有2种类型实现:ziplist类型、linkedlist类型

--- ziplist类型的使用要满足如下2个条件:所有节点长度都小于64字节+元素个数小于512;

列表对象使用ziplist类型的2个条件,是默认在redis.conf配置文件里的:

--- linkedlist类型:不能满足ziplist类型的条件的,都会采用linkedlist

  1. Ziplist      VS  linkedlist

--- Linkedlist是链表,扩展性好;且不需要连续的内存空间,内存利用率高;但是查找性能相对差;

--- ziplist类似数组,有高效的访问,查找性能更高;但是因为ziplist需要连续内存空间,对内存的利用率较低;

(3)

 

  1. 哈希对象
  2. 哈希对象有2种类型实现:ziplist类型、字典类型

--- ziplist类型:同事满足2个条件:所有节点长度都小于64字节 + 列表元素个数小于512   (注意:键值对挨在一起,先添加的键值对会被放在表头方向,后添加的放在表尾方向)

哈希对象使用ziplist类型的这2个限制条件是默认在redis.conf配置文件里的:

--- 字典类型:不能满足使用ziplist类型的2个条件,则采用字典类型

(2)

  1. 集合对象
  2. 集合对象有2种类型实现:intset类型、字典类型

--- intset类型:整数集合,满足2个条件才行:所有元素都是整数值 + 列表元素个数小于512

--- 字典类型:不满足上述2个条件,则采用字典;

(2)集合对象使用intset类型的限制条件是默认在redis.conf配置文件里的:

  1. 有序集合

1)有序集合对象有2种类型实现:ziplist类型、字典+跳跃表

--- ziplist类型:需要满足2个条件:所有节点长度都小于64字节 + 列表元素的个数小于128;(注意:元素和分支紧挨一起;先添加的键值对会被放在表头方向,后添加的放在表尾方向)

在redis.conf配置文件里的默认参数如下:

--- 字典和跳跃表:不能满足用ziplist类型的,就用字典+跳跃表实现

2)用字典+跳跃表组合实现,而不是只用字典的原因如下:

跳跃表保存分值和元素,字典也保存分值和元素;之所以用字典+跳跃表的组合,总体是为了在不同场景下的高性能;

zrank zrange等命令是通过跳跃表api实现;zscore命令通过字典实现;

字典和跳跃表都通过指针共享内存的方式避免重复存储;

来自为知笔记(Wiz)

时间: 2024-10-17 03:37:47

第八课——跳跃表、对象的相关文章

【算法导论】 第十二课 跳跃表

本节课介绍了一种全新的数据结构--跳跃表 跳跃表是一种简单又有趣的动态搜索数据结构,其主要优点在于其易于实现,而且很好的保证了其具有高效的性能,即2*O(lgn)的搜索性能 在此之前我想首先谈谈链表,链表的优点在于其插入和删除只需要常数项的时间(加上查找该元素需要额外的O(n)时间),但是其查找效率只有O(n),这里顺带补充一下链表类的问题,以下先给出两个BAT公司面试时热衷于考的两个链表经典问题: 1.如何快速查找单向链表倒数第m个元素 2.如何快速判断一个单向链表是否存在环 对于链表类问题,

JAVA学习第二十八课(常用对象API)- String类

多线程告一段落,开始常用对象API的涉及,背也要背下来!!! 日后开发,遇见最多的对象是文字,也就是字符串 String类 字符串是一个特殊对象 字符串一旦初始化就不可以被改变 一.特点 public class Main { public static void main(String[] args) { Demo1(); System.out.println("--------------"); Demo2(); } /*演示字符串的第一种定义方式,并明确字符串常量池的特点*/ p

JAVA学习第三十八课(常用对象API)- 集合框架(六)— Map集合及其常用方法

一.Map集合特点 Map集合(双列集合)一次添加一对元素,Collection集合(单列集合)一次添加一个元素 接口 Map<K,V>,实际上存储的是键值对 特点: 将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. 也就是说Map中必须保证键的唯一性 二.常用方法 1.添加:value = put(key,value);返回前一个和key相关联的值,如果没有返回null 2.删除:void clear();把Map中的所有映射关系清除 value remove(ke

【原创】bootstrap框架的学习 第八课 -[bootstrap表单]

Bootstrap 提供了下列类型的表单布局: 垂直表单(默认) 内联表单 水平表单 吹着表单或基本表单 向父 <form> 元素添加 role="form". 把标签和控件放在一个带有 class .form-group 的 <div> 中.这是获取最佳间距所必需的. 向所有的文本元素 <input>.<textarea> 和 <select> 添加 class .form-control. 例子: <!DOCTYPE

跳跃表 C#

           虽然avl树和红黑树在数据搜索和排序方面都是有效的数据结构,但是都显得特别麻烦,跳跃表就显得特别简单,虽然简单 不影响他性能,在平均情况下,其插入.删除.查找数据时间复杂度都是O(log(N)),其最坏情况下都为O(N).                                                                                                                                

第一部分 数据结构与对象 跳跃表

下面是跳跃表的基本原理,REDIS的实现大致相同 跳跃表的一个特点是,插入NODE是通过随机的方式来决定level的,比较奇特 下面是skipList的一个介绍,转载来的,源地址:http://kenby.iteye.com/blog/1187303,为防止源地址丢失,故拷贝一份放在这里,望作者原谅. ---------------转载开始----------------- 为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等. 想象一下,给

斯坦福第十八课:应用实例:图片文字识别(Application Example: Photo OCR)

18.1  问题描述和流程图 18.2  滑动窗口 18.3  获取大量数据和人工数据 18.4  上限分析:哪部分管道的接下去做 18.1  问题描述和流程图 图像文字识别应用所作的事是,从一张给定的图片中识别文字.这比从一份扫描文档中 识别文字要复杂的多. 为了完成这样的工作,需要采取如下步骤: 为了完成这样的工作,需要采取如下步骤: 1. 文字侦测(Text detection)——将图片上的文字与其他环境对象分离开来 2. 字符切分(Character segmentation)——将文

[译文]JOAL教程 第八课 OggVorbis格式流

[译文]JOAL教程 原文地址:http://jogamp.org/joal-demos/www/devmaster/lesson8.html 原文作者:Athomas Goldberg 译文:三向板砖 转载请保留以上信息. 这是JOAL教程系列的最后一节,学习笔记:http://blog.csdn.net/shuzhe66/article/details/40583771 我十分建议您在阅读完本文后参考学习笔记内容,这节的问题非常多. 第八课OggVorbis格式流 本文是DevMaster.

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类