| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 【Redis】五种存储类型及其底层数据结构 -> 正文阅读 |
|
[数据结构与算法]【Redis】五种存储类型及其底层数据结构 |
目录1. Redis的五种存储类型1.1 String字符串字符串是redis中最简单的数据结构,其内部表示就是一个字符数组。 SDS动态字符串(simple dynamic string) Redis中所有场景中出现的字符串,基本都是由SDS来实现的:包括字符串类型的key、字符串类型的值。 在C语言中,字符串可以用’\0’结尾的char数组标示。这种简单的字符串表示,在大多数情况下都能满足要求,但是不能高效的计算length和append数据。所以Redis自己实现了SDS(简单动态字符串)的抽象类型。
空间预分配 字符串类型的内部结构采用 预分配冗余空间 的方式来减少内存的频繁分配。内部为当前字符串分配的实际空间capacity一般要高于实际字符串长度。 当字符串长度小于1MB时,扩容都是加倍;长度超出1MB,一次只会多扩1MB的空间。 1.2 List列表Redis的列表相当于Java语言中的LinkedList,它是一个 双向链表 而不是数组。这意味着list的插入和删除操作非常快,但索引定位很慢。 数据结构:由List和ListNode两个数据结构构成 List部分
ListNode部分
使用场景 Redis的列表结构常用来做异步队列使用:将需要延后处理的任务结构体序列化成字符串,塞进Redis列表,另一个线程从这个列表中轮询数据进行处理。 1.2.1 ZipList压缩列表使用LinkedList结构链表的附加空间太高,prex和next指针就要占去16个字节,另外每个节点的内存单独分配,会加剧内存的碎片化。 为了节约内存,使用一种ZipList压缩列表的存储方式。 在列表元素较少的情况下,会使用一块连续的内存存储,这个结构是 压缩列表ZipList。它将所有的元素紧挨着存储,分配的是一块连续的内存。当数据量比较多的时候使用LinkedList。 ZipList结构
其中每一个Entry结构
ZipList增加元素 因为ZipList是紧凑存储没有冗余空间,意味着插入一个元素就要调用realloc扩展内存,可能会分配新的内存空间,并将之前的内容一次性拷贝到新的地址,也可能在原有地址上进行扩展。 所以其不适合存储大型字符串、存储的元素也不宜过多。 1.2.1 QuickList快速链表Redis的早期版本使用的是LinkedList和ZipList两种结构相结合的方式,在新版本中对列表的数据结构进行了改造,使用QuickList代替了LinkedList和ZipList。 QuickList将LinkedList按段切分,每一段使用ZipList让存储紧凑,多个ZipList之间使用双向指针串接起来。
每一个ZipList长度为8KB,超出这个字节数就会灵气一个ZipList,这个长度是可配置的。 压缩深度 为了支持快速的push/pop操作,QuickList的首尾两个ZipList不压缩,此时压缩深度为1。 如果压缩深度为2,表示QuickList的收尾两个ZipList不压缩。QuickList的默认压缩深度为0。这个深度也是可配置的。 1.3 Hash字典Redis的哈希对象的底层存储可以使用ZipList和HashTable。当hash对象可以同时满足一下两个条件时,哈希对象使用ziplist编码。当前超出以下条件,也会由ZipList结构转换为HashTable结构。
1.3.1 ZipList字典结构与上述List结构中ZipList存储的结构是相同的,在存储内容上,每个Entry依次存储Key、Value。 1.3.2 HashTable字典结构Redis中的字典相当于Java中的HashMap,是无序字典,内部存储了很多键值对。实现结构上和HashMap也是类似的,都是 “数组+链表” 结构,当hash数组位置碰撞时,就会将碰撞的元素使用链表串接起来。不同的是,Redis中的Hash字典的值只能是字符串。
渐进式reHash
在字典扩容缩容时,需要分配新的HashTable,然后进行渐进式搬迁。这时两个HashTable存储的分别是旧的HashTable和新的HashTable,待搬迁结束后,旧的HashTable被删除,新的HashTable取而代之。 1.4 Set集合Redis的集合相当于Java中的HashSet,它内部的键值对是无序的、唯一的。 其内部实现相当于一个特殊的Hash字典,字典中所有的Value都是NULL。 1.5 ZSet有序列表ZSet可能是Redis提供的最有特色的数据结构,它2类似于Java的SortedSet和HashMap的结合体。一方面它是一个Set,保证了内部value的唯一性;另一方面它可以给每个value赋予一个score,代表这个value的排序权重。 其内部实现是一种叫做 “跳跃列表” 的数据结构。 SlipList跳跃列表跳表结构比较复杂,先简单介绍其原理 想象你是一家创业公司的老板,刚开始只有几个人,大家都平起平坐。后来随着公司的发展,人数越来越多,团队沟通成本逐渐增加,渐渐地引入了组长制,对团队进行划分,于是有一些人又是员工又有组长的身份。 再后来,公司规模进一步扩大,公司需要再进入一个层级:部门。于是每个部门又会从组长中推举一位选出部长。 跳跃表就类似于这样的机制,最下面一层所有的元素都会串起来,都是员工,然后每隔几个元素就会挑选出一个代表,再把这几个代表使用另外一级指针串起来。然后再在这些代表里面挑出二级代表,再串起来。最终形成了一个金字塔的结构。 跳跃表以有序的方式在层次化的链表中保存元素, 效率和平衡树媲美 —— 查找、删除、添加等操作都可以在对数期望时间下完成, 并且比起平衡树来说, 跳跃表的实现要简单直观得多。 从图中可以看到, 跳跃表主要由以下部分构成:
跳表工作流程 跳表之所以跳跃,是因为其内部元素可能"身兼数职",一个元素可以同时处于不同的层级,可以快速在不同层次之间进行"跳跃"。 元素定位 定位元素时,先在顶层进行定位,然后下潜到下一级定位,直到找到目标位置。
新元素的层级 跳跃列表采取一个随机策略来决定新元素可以兼职到第几层。 首先其位于第0层的概率肯定是100%,而兼职到L1层只有50%的概率,到L2层有25%的概率,以此类推,一直到最顶层。列表中元素越多,能够深入的层次就越深,元素能进入到顶层的可能性就越大。 跳表层数上限是32,最大的元素容量(即Level0层)有2的64次方个。根据这个随机算法,当level[0]有2的64次方个节点时能达到32层。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 19:22:00- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |