深入浅出Redis-redis底层数据结构(下)
概述:
学习使用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底层数据结构(下)的更多相关文章
- Redis(二)--- Redis的底层数据结构
1.Redis的数据结构 Redis 的底层数据结构包含简单的动态字符串(SDS).链表.字典.压缩列表.整数集合等等:五大数据类型(数据对象)都是由一种或几种数结构构成. 在命令行中可以使用 OBJ ...
- 深入理解Redis:底层数据结构
简介 redis[1]是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...
- Redis详解(四)------ redis的底层数据结构
上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redis 中,这几种数据类型底层是由什么数据结构构造的呢?本篇博客我们就来详细介绍Redis中五大数据类型的底层实现. 1.演示数据类 ...
- Redis 的底层数据结构(对象)
目前为止,我们介绍了 redis 中非常典型的五种数据结构,从 SDS 到 压缩列表,这都是 redis 最底层.最常用的数据结构,相信你也掌握的不错. 但 redis 实际存储键值对的时候,是基于对 ...
- Redis 详解 (四) redis的底层数据结构
目录 1.演示数据类型的实现 2.简单动态字符串 3.链表 4.字典 5.跳跃表 6.整数集合 7.压缩列表 8.总结 上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redis 中, ...
- redis string底层数据结构sds
redis的string没有采用c语言的字符串数组而采用自定义的数据结构SDS(simple dynamic string)设计 len 为字符串的实际长度 在redis中获取字符串的key长度的时 ...
- Redis 的底层数据结构(SDS和链表)
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.可能几乎所有的线上项目都会使用到 Redis,无论你是做缓存.或是用作消息中间件,用起来很简单方便 ...
- Redis 的底层数据结构(字典)
字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...
- Redis 的底层数据结构(跳跃表)
字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...
- Redis 的底层数据结构(整数集合)
当一个集合中只包含整数,并且元素的个数不是很多的话,redis 会用整数集合作为底层存储,它的一个优点就是可以节省很多内存,虽然字典结构的效率很高,但是它的实现结构相对复杂并且会分配较多的内存空间. ...
随机推荐
- OCP-1Z0-051-题目解析-第9题
9. Which statement is true regarding the INTERSECT operator? A. It ignores NULL values. B. Reversing ...
- hdu - 4979 - A simple math problem.(可反复覆盖DLX + 打表)
题意:一种彩票共同拥有 N 个号码,每注包括 M 个号码,假设开出来的 M 个号码中与自己买的注有 R 个以上的同样号码,则中二等奖,问要保证中二等奖至少要买多少注(1<=R<=M< ...
- iSwifting社区【www.iSwifting.com】招聘版主
iSwifting社区[www.iSwifting.com]昨天找来几个主持人.我已经被任命为他们的任务领域. 他们有百度的project噢,还有cocoaChina问答区的活跃人物! 欢迎大家一起学 ...
- webapp 开发调试测试方法总结
好久都没有发表过日志了,反正近期项目也已经接近尾声了,那么是时候该总结一下在项目中用到的技术了,请看:这里先废话几句,我们现在的开发模式是这样子的:先把本地的网页上传到远程服务器(因为好多设备都要去访 ...
- 点击表格的单元格时实现变颜色,通过for循环为每个单元格添加一个onclick事件
<title>无标题文档</title> <script type="text/javascript" language="javascri ...
- 13个不可不知的ASP.NET MVC扩展点
13个不可不知的ASP.NET MVC扩展点 ASP.NET MVC设计的主要原则之一是可扩展性.处理管线(processing pipeline)上的所有(或大多数)东西都是可替换的.因此,如果您不 ...
- JS列表的下拉菜单组件(仿美化控件select)
JS列表的下拉菜单组件(仿美化控件select) 2014-01-23 23:51 by 龙恩0707, 1101 阅读, 6 评论, 收藏, 编辑 今天是农历23 也是小年,在这祝福大家新年快乐!今 ...
- Web Components
Web Components是不是Web的未来 今天 ,Web 组件已经从本质上改变了HTML.初次接触时,它看起来像一个全新的技术.Web组件最初的目的是使开发人员拥有扩展浏览器标签的能力,可以 ...
- C++虚函数表调用学习
知识点是看 陈皓大哥的博客,代码也参考了他的,不过做了很小的改动. 原文链接:http://blog.csdn.net/haoel/article/details/1948051 #include & ...
- C#算两个时间段相差的时间
在数据中经常算两个时间差或者在某个时间段的内容 在数据库中设计表字段类型的时候设计为varchar类型,然后进行可以再Sql语句中书写>=或者<=这样的进行比较就可以查询出某个时间段的内容 ...