目录

  • SDS 的设计到底有多牛逼。
  • List、Set、Sorted Set、Hash 底层实现原理

SDS 的设计到底有多牛逼

Redis 使用 C 语言编写,但是并没有直接使用 C 语言自带的字符串,而是使用了 SDS 来管理字符串。接下来就来探讨下为什么 Redis 使用了 SDS 来管理字符串。

SDS 全称 Simple Dynamic String,即简单动态字符串。SDS 组成部分如下:

  • free:表示 buf 中的空闲的空间大小,图左空闲空间为 0,图右空闲空间为 3
  • len:表示 buf 中的内容长度,注意 len 的长度不包括 ' 0 '(字符串以0 结尾是为了使用 C 语言中现成的库函数,而不需要重新造轮子)
  • buf:一个 char 类型的数组,用于存储实际字符串的内容。

SDS 的优势

  1. 获取字符串长度的复杂度为 O(1);直接可通过 len 属性获得字符串的长度。
  2. 防止 buf 存储内容溢出的问题;每次增加字符串的长度的时候先检查 free 属性是否能存下要增加的字符串的长度,如果不够,则先对 buf 数组扩容,然后在将内容存入 buf 数组中。
  3. 空间预分配&空间惰性释放;SDS 会预先分配一部分空闲空间,当字符串内容添加时不需要做空间申请的工作,当字符串从 buf 数组中移除时,空闲出来的空间不会立马被内存回收,防止新增字符串的内容写入时空间不够而临时申请空间。
  1. 二级制安全性;由于字符串是存储在 char 类型的数组中,即内容是以二进制的形式存储的,所以 SDS 可以存储任何类型的二进制数据,同时也不需要担心数据格式转换的问题。

List 的实现原理

在 Redis3.2 之前,List 底层采用了 ZipList 和 LinkedList 实现的,在 3.2 之后,List 底层采用了 QuickList。

Redis3.2 之前,初始化的 List 使用的 ZipList,List 满足以下两个条件时则一直使用 ZipList 作为底层实现,当以下两个条件任一一个不满足时,则会被转换成 LinkedList。

  • List 中存储的每个元素的长度小于 64byte
  • 元素个数小于 512

ZipList方式 的实现原理

ZipList 是由一块连续的存储空间组成,从图中可以看出 ZipList 没有前后指针。

各部分作用说明:

  • zlbytes:表示当前 list 的存储元素的总长度。
  • zllen:表示当前 list 存储的元素的个数。
  • zltail:表示当前 list 的头结点的地址,通过 zltail 就是可以实现 list 的遍历。
  • zlend:表示当前 list 的结束标识。
  • entry:表示存储实际数据的节点,每个 entry 代表一个元素。
  • previours_entry_length: 表示当前节点元素的长度,通过其长度可以计算出下一个元素的位置。
  • encoding:表示元素的编码格式。
  • content:表示实际存储的元素内容。

ZipList 的优缺点比较

  • 优点:内存地址连续,省去了每个元素的头尾节点指针占用的内存。
  • 缺点:对于删除和插入操作比较可能会触发连锁更新反应,比如在 list 中间插入删除一个元素时,在插入或删除位置后面的元素可能都需要发生相应的移动操作。

LinkedList方式 的实现原理

LinkedList 都比较熟悉了,是由一系列不连续的内存块通过指针连接起来的双向链表。

各部分作用说明:

  • head:表示 List 的头结点;通过其可以找到 List 的头节点。
  • tail:表示 List 的尾节点;通过其可以找到 List 的尾节点。
  • len:表示 List 存储的元素个数。
  • dup:表示用于复制元素的函数。
  • free:表示用于释放元素的函数。
  • match:表示用于对比元素的函数。

QuickList方式 的实现原理

在 Redis3.2 版本之后,Redis 集合采用了 QuickList 作为 List 的底层实现,QuickList 其实就是结合了 ZipList 和 LinkedList 的优点设计出来的。

各部分作用说明:

  • 每个 listNode 存储一个指向 ZipList 的指针,ZipList 用来真正存储元素的数据。
  • ZipList 中存储的元素数据总大小超过 8kb(默认大小,通过 list-max-ziplist-size 参数可以进行配置)的时候,就会重新创建出来一个 ListNode 和 ZipList,然后将其通过指针关联起来。

Set 的实现原理

Set 集合采用了整数集合和字典两种方式来实现的,当满足如下两个条件的时候,采用整数集合实现;一旦有一个条件不满足时则采用字典来实现。

  • Set 集合中的所有元素都为整数
  • Set 集合中的元素个数不大于 512(默认 512,可以通过修改 set-max-intset-entries 配置调整集合大小)

整数集合实现原理图

字段实现原理图

Zset 的实现原理

Zset 底层同样采用了两种方式来实现,分别是 ZipList 和 SkipList。当同时满足以下两个条件时,采用 ZipList 实现;反之采用 SkipList 实现。

  • Zset 中保存的元素个数小于 128。(通过修改 zset-max-ziplist-entries 配置来修改)
  • Zset 中保存的所有元素长度小于 64byte。(通过修改 zset-max-ziplist-values 配置来修改)

采用 ZipList 的实现原理

和 List 的底层实现有些相似,对于 Zset 不同的是,其存储是以键值对的方式依次排列,键存储的是实际 value,值存储的是 value 对应的分值。

采用 SkipList 的实现原理

SkipList 分为两部分,dict 部分是由字典实现,Zset 部分使用跳跃表实现,从图中可以看出,dict 和跳跃表都存储的数据,实际上 dict 和跳跃表最终使用指针都指向了同一份数据,即数据是被两部分共享的,为了方便表达将同一份数据展示在两个地方。

关于跳跃表和字典的具体实现,此处不详细介绍,想深入了解的朋友自行上网查阅。

Hash 的实现原理。

Hash 底层实现采用了 ZipList 和 HashTable 两种实现方式,相信看到这里大家都比较轻车熟路了,下面来看看。Hash 结构当同时满足如下两个条件时底层采用了 ZipList 实现,一旦有一个条件不满足时,就会被转码为 HashTable 进行存储。

  • Hash 中存储的所有元素的 key 和 value 的长度都小于 64byte。(通过修改 hash-max-ziplist-value 配置调节大小)
  • Hash 中存储的元素个数小于 512。(通过修改 hash-max-ziplist-entries 配置调节大小)

ZipList方式 的实现原理

从图上看是不是很熟悉,其实和 Zset 的 ZipList 的实现逻辑几乎相同,就不多介绍了。

HashTable方式 的实现原理

HashTable 实现底层采用了字段的方式实现,其中键存储的内容为 field,值存储的是 value 值。

总结

本文主要介绍了 5 种基础常用集合的底层实现原理,相信大家看完之后,在业务开发时对集合选用,同时结合业务使用的命令更加有自己的理解。

下篇文章我们来介绍 Redis 数据过期策略、AOF 及 RDB 文件等内容,尽情期待。

不要给我说什么底层原理_连集合底层实现原理都不知道,你敢说 Redis 用的很溜?...相关推荐

  1. aop实现原理_从宏观的实现原理和设计本质入手,带你理解 AOP 框架的原理

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 作者:FeelsChaotic juejin.im/post/5c57b2d5e51d45 ...

  2. dry的原理_速干面料的原理

    速干衣一般来说都是100%聚酯纤维的.采用了特殊的编制工艺 使其干的较快的哦. 速干的由来:所谓速干实际上是由英文QUICK-DRY或DRY-EASY等类似单词直译过来的,而速干是指该面料的衣物与毛质 ...

  3. 三线压力传感器原理_电喷摩托车进气压力传感器原理与检测

    功能:检测发动机的进气压力,判断进气行程和负荷状况,用于ECU决定喷油时间和点火正时. 原理:利用膜片弯曲,造成电阻变化,检测压力. 故障现象:低速不良:动力不足,耗油,冒黑烟:容易熄火. 故障原因: ...

  4. 分类计数原理与分步计数原理_《分类加法计数原理与分步乘法计数原理》教学设计...

    一.本节课教学内容的本质.地位.作用分析 分类加法计数原理与分步乘法计数原理是人类在大量的实践经验的基础上归纳出的基本规律,它们不仅是推导排列数.组合数计算公式的依据,而且其基本思想方法也贯穿在解决本 ...

  5. 高频开关电源原理_程控开关电源的工作原理

    本文介绍了开关电源的工作原理以及它的特点. 程控开关电源要要比线性电源复杂得多. 下图是典型的开关电源工作原理图. 首先对 220 V/50Hz 的 AC 输入,通过桥式整流器进行整流 储能电容对整流 ...

  6. 转子接地保护原理_罗茨鼓风机(压缩机)原理和操作规程

    罗茨鼓风机(罗茨风机),利用两个或者三个叶形转子在气缸内作相对运动来压缩和输送气体的回转压缩机.这种鼓风机结构简单,制造方便,适用于低压力场合的气体输送和加压,也可用作真空泵. 1.设备基础知识 1. ...

  7. ld3320语音识别模块工作原理_变频空调功率模块工作原理与故障检测

    一.功率模块原理与外形 功率模块是变频空调器电控系统中较重要的器件之一,也是故障率较高的一个器件.功率模块将IGBT连同驱动电路和多种保护电路封装在同一模块内,从而简化了设计,提高了稳定性.功率模块只 ...

  8. 简述ospf的工作原理_简述洛氏硬度计的工作原理及应用领域

    简述洛氏硬度计的工作原理及应用领域,其采用金刚石锥体或钢球作为压头.它应用一个次要负载,接着是一个主要负载,然后将负载减少到 初的次要负载.材料的硬度通过使用线性测量仪或其他工具从次要负载的第二次穿透 ...

  9. 双时隙的工作原理_双联开关的工作原理

    台灯的开关工作原理是什么 利用的是人体的静电.在按的过程中输入了脉冲.经芯片处理,改变亮度 采用触摸按键在结构方面非常简单方便,设计好的触摸按键电路板,直接贴在面板外壳上,然后用后盖压紧(或者其他方式 ...

最新文章

  1. Yolo(2)Yolo v2
  2. 华为S5700交换机开启telnet登录
  3. VS_自动添加头文件
  4. 【转】关于Ubuntu的sources.list 的总结
  5. 【转载】SAP参数文件简介
  6. wifi卡慢延迟高_健康生活好助手:华为智能体脂秤 WiFi 版 体验评测
  7. HDOJ 1247 HDU 1247 Hat’s Words ACM 1247 IN HDU
  8. 8.Azure文件(文件共享)-NAS(中)
  9. 单例模式几种不同实现方式?
  10. 学堂在线笔记——前端与后台的故事——SQL语言及其编程
  11. 特朗普对五角大楼云计算合同表示担忧
  12. 论文阅读笔记《Principal characteristic networks for few-shot learning》
  13. setopaque java_setOpaque(真/假); Java的
  14. TYVJ P1061 [Mobile Service]
  15. 付永刚计算机信息安全技术课后答案
  16. android手机赚钱软件排行
  17. 线性回归统计指标 SSE、MSE、RMSE、MAE、R-square
  18. Pr:抠像与视频合成
  19. 谷歌三大核心技术:from--http://blog.csdn.net/together_cz/article/details/66969003
  20. 微信小程序云开发教程-小程序端调用云函数

热门文章

  1. 《C语言程序设计》王希杰 课后答案
  2. Q#–一个新年愿望清单
  3. C#LeetCode刷题之#48-旋转图像(Rotate Image)
  4. 如何使用Docker Volumes在基于Docker的应用程序上启用实时重新加载
  5. vulcan 编程_如何用Next代替流星— Vulcan Next Starter简介
  6. mongoose-iot_如何使用带有ESP32和Mongoose OS的GCP-Cloud IoT核心版查看天气
  7. 现实世界的数据结构:JavaScript中的表格和图形
  8. 苹果x和xsmax有什么区别_苹果手机不卡的真相是什么,安卓和iOS有本质区别
  9. 代码生成插件Easy Code 使用
  10. XPath与lxml类库