1. 跳跃表(skiplist)

    跳跃表是一种有序数据结构。跳跃表支持平均O(logN),最坏O(N)复杂度的节点查找,大部分情况下,跳跃表的效率可以和平衡树相媲美,并且因为跳跃表的实现比平衡树简单,所有不少程序都用跳跃表代替平衡树。Redis使用跳跃表作为有序集合的底层实现,另一个是在集群节点中用作内部数据结构。

1.1 跳跃表的实现

typedef struct zskiplist {

struct zskiplistNode *header, *tail;

unsigned long length;

int level;

} zskiplist;

  • header:指向跳跃表的表头节点。
  • tail:指向跳跃表的表尾节点。
  • level:记录目前跳跃表内,层数最大的那个节点的层数(表头节点的层数不计算在内)
  • lenght:记录跳跃表的长度,即跳跃表目前包含节点的数量(表头节点的层数不计算在内)

typedef struct zskiplistNode {

robj *obj;

double score;

struct zskiplistNode *backward;

struct zskiplistLevel {

struct zskiplistNode *forward;

unsigned int span;

} level[];

} zskiplistNode;

  • 层(level):节点中用L1, L2, L3等字样标记节点的各个层,L1代表第一层,L2代表第二层,依次类推。每个层都带有两个属性:前进指针和跨度。
  • 前进(level[i].forward)属性:用于从表头向表尾方向的访问节点。遍历跳跃表中所有节点的路径。
  • 跨度(level[i].span)属性:用于记录两个节点之间的距离。两个节点直接的跨度越大,他们相距的就越远。指向NULL的所有指针的跨度都为0,因为他们没有连向任何节点。
  • 后退(backward)指针:节点中用BW字样标记节点的后退指针,他指向位于当前节点的前一个节点。后退指针在程序从表尾向表头遍历使用。
  • 分值(score):各个节点中的1.0,2.0和3.0是节点所保存的分值。在跳跃表中节点按各自所保存的分值从小到大排列。
  • 成员对象(obj): 各个节点中o1、o2、o3是节点所保存的成员对象。
  1. 整数集合(intset)

整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。

typedef struct intset {

uint32_t encoding;

uint32_t length;

int8_t contents[];

} intset;

  • contents数组时整数集合的底层实现:各个元素在数组中按值大小从小到大有序地排列,并且数组中不包含任何重复项。
  • length属性记录了整数集合包含的元素数量,即contents数组数组的长度。

    虽然intset结构将contents属性声明为int8_t类型的数组,但实际上contents数组并不保存任何int8_t类型的值,contents数组的真正类型取决于encoding属性值。
  • 如果encoding属性的值为INTSET_ENC_INT16,那么contents就是一个int16_t类型的数组。数组长度sizeof(int16_t)*length
  • 如果encoding属性的值为INTSET_ENC_INT32,那么contents就是一个int32_t类型的数组。数组长度sizeof(int32_t)*length
  • 如果encoding属性的值为INTSET_ENC_INT64,那么contents就是一个int64_t类型的数组。数组长度sizeof(int64_t)*length

整数集合升级,不支持降级。

每当将一个元素添加到整数集合里面,并且新元素的类型比整数集合现有所有元素的类型都要长时,整数集合需要先进行升级,然后才能添加到整数集合里面。升级分三步进行:

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

2)将底层数组现有的所有元素都转换成与新元素相同的元素类型,并将类型转换后的元素放置到正确的位置。

3)将新元素添加到底层数组里面。

升级的好处

1)提升灵活性。因为语言时静态类型语言,不能将两种不同类型的值放在同一个数据结构里面。因为整数集合可以自动升级底层数组来适应新元素。

2)节约内存。 要让一个数组同时可以保存int16_t,int32_t, int64_t三种类型通常做法直接使用int64_t类型作为数组,这样出现浪费内存。

升级例子:将一个类型int32_t的数值65535添加到int16_t类型集合里面:





  1. 压缩列表(ziplist)

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

3.1 压缩列表的构成

压缩列表时Redis为了节约内存而开发,是由一系列特殊编码的连续内存块组成的顺序型的数据结构。一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。

3.1 压缩列表节点的构成

每个压缩列表节点可以保存一个字节数组或者一个整数值。其中,字节数组可以是以下三种长度中的一种:

长度小于等于63(2^6-1)字节的字节数组;

长度小于等于16383(2^14-1)字节的字节数组

长度小于等于4294967295(2^32-1)字节的字节数组

整数值可以是以下6种长度中的一种:

4位长,介于0至12之间的无符号整数

1字节长的有符号整数

3字节长的有符号整数

int16_t类型整数

int32_t类型整数

int64_t类型整数

节点的 previous_entry_length属性以字节为单位,记录了压缩列表中前一个节点的长度。

如果前一节点的长度小于254字节,那么 previous_entry_length属性的长度为1字节,

如果前一节点的长度大于等于254字节,那么 previous_entry_length属性的长度为5字节:其中属性的第一字节会被设置为0xFE(十进制值254),而之后的四个字节则用于保存前一节点的长度。

节点的encoding属性记录了节点的content属性所保存数据的类型以及长度。

一字节、两字节或者五字节长,值的最高位为00、01或者10的是字节数组编码:这种编码表示节点的 content属性保存着字节数组,数组的长度由编码除去最高两位之后的其他位记录。

一字节长,值的最高位以11开头的是整数编码:这种编码表示节点的content属性保存着整数值,整数值的类型和长度由编码除去最高两位之后的其他位记录。

节点的content属性负责保存节点的值,节点值可以是一个字节数组或者整数,值的类型和长度由节点的encoding属性决定。

节点的content属性负责保存节点的值,节点值可以是一个字节数组或者整数,值的类型和长度由节点的encoding属性决定

redis数据结构和对象二的更多相关文章

  1. Redis数据结构和对象三

    1.Redis 对象系统 Redis用到的所有主要数据结构,简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合.跳跃表. Redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这些 ...

  2. redis数据结构整理(二)

    摘要: 1.各个数据结构的应用举例 1.1 String类型应用举例 1.2List类型应用举例 1.3Set类型应用举例 1.4Sorted Set类型应用举例 1.5Hash类型应用举例 内容: ...

  3. redis数据结构和对象一

    1. SDS:简单动态字符串(simple dynamic string) Redis没有直接使用C语言的字符串,而是自己构建了一种名为简单动态字符串类型,并将SDS用作Redis的默认字符串. SD ...

  4. redis 系列9 对象类型(字符串,哈希,列表,集合,有序集合)与数据结构关系

    一.概述 在前面章节中,主要了解了 Redis用到的主要数据结构,包括:简单动态字符串.链表(双端链表).字典.跳跃表. 整数集合.压缩列表(后面再了解).Redis没有直接使用这些数据结构来实现键值 ...

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

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

  6. [redis读书笔记] 第一部分 数据结构与对象 对象类型

    - 从前面redis的基本数据结构来看,可以看出,redis都是在基本结构(string)的基础上,封装了一层统计的结构(SDS),这样让对基本结构的访问能够更快更准确,提高可控制度. - redis ...

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

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

  8. Redis学习笔记一:数据结构与对象

    1. String(SDS) Redis使用自定义的一种字符串结构SDS来作为字符串的表示. 127.0.0.1:6379> set name liushijie OK 在如上操作中,name( ...

  9. Redis 基础数据结构与对象

    Redis用到的底层数据结构有:简单动态字符串.双端链表.字典.压缩列表.整数集合.跳跃表等,Redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包 ...

随机推荐

  1. 最短路径问题---Floyed(弗洛伊德算法),dijkstra算法,SPFA算法

    在NOIP比赛中,如果出图论题最短路径应该是个常考点. 求解最短路径常用的算法有:Floyed算法(O(n^3)的暴力算法,在比赛中大概能过三十分) dijkstra算法 (堆优化之后是O(MlogE ...

  2. Codeforces Round #644 (Div. 3)

    比赛链接:https://codeforces.com/contest/1360 A - Minimal Square 题意 计算能包含两个 $a \times b$ 矩形的最小正方形的面积. 题解 ...

  3. 【noi 2.6_1481】Maximum sum(DP)

    题意:求不重叠的2段连续和的最大值. 状态定义f[i]为必选a[i]的最大连续和,mxu[i],mxv[i]分别为前缀和后缀的最大连续和. 注意:初始化f[]为0,而max值为-INF.要看好数据范围 ...

  4. 【noi 2.2_8758】2的幂次方表示(递归)

    题意:将正整数N用2的幂次方表示(彻底分解至2(0),2). 解法:将层次间和每层的操作理清楚,母问题分成子问题就简单了.但说得容易,操作没那么容易,我就打得挺纠结的......下面附上2个代码,都借 ...

  5. Happy 2006 POJ - 2773 容斥原理+二分

    题意: 找到第k个与m互质的数 题解: 容斥原理求区间(1到r)里面跟n互质的个数时间复杂度O(sqrt(n))- 二分复杂度也是O(log(n)) 容斥原理+二分这个r 代码: 1 #include ...

  6. Redis全面解析

    1.什么是Redis? Redis是BSD协议,是一个高性能的key-value非关系型数据库. 2.redis单线程问题 所谓的单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一 ...

  7. Yocto项目介绍及入门 -- 嵌入师工程师必备利器

    目录 写在前面 1. Yocto项目是什么 2. Yocto项目有什么用 3. 如何快速上手Yocto项目 4. 带你通过Yocto项目编译一个自定义镜像文件 写在前面 博主目前从事BMC工作,由于公 ...

  8. volatile的内存屏障的坑

    请看下面的代码并尝试猜测输出: 可能一看下面的代码你可能会放弃继续看了,但如果你想要彻底弄明白volatile,你需要耐心,下面的代码很简单! 在下面的代码中,我们定义了4个字段x,y,a和b,它们被 ...

  9. PPT online viewer

    PPT online viewer PPT 在线查看器 SpeakerDeck https://speakerdeck.com/xgqfrms/python?slide=3 SlideShare ht ...

  10. 十大排序算法时间复杂度 All In One

    十大排序算法时间复杂度 All In One 排序算法时间复杂度 排序算法对比 Big O O(n) O(n*log(n)) O(n^2) 冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 ...