【redis前传】集思广益之quicklist,取其精华去其糟粕
前言
- 在之前我们已经学习了redis五大数据结构中的list结构。其内部是linkedList和zipList两种结构。这是我们已经学习的内容。之前我没有结合操作具体查看。事实上在两者中还存在一种结合体quickList

结构演变
- 在上面我们添加了一个key为zlist的数据。通过object encoding zlist查看底层就是通过quicklist来构建的。之前在ziplist章节汇总我们了解到在redis中hash和list基本数据结构都使用了ziplist存储数据的。在list中我们确实quicklist。这里我们提前说明下quicklist内部就是基于ziplist来实现的。
linkedList
- 在开场quicklist之前我们简单梳理下之前学过的linkedList ,他是一种常见的双线链表。通过两个指针完成我们链表的构建。

C++指针
- redis是基于内存运行的,而内存有十分的宝贵所以redis在设计了双线链表后觉得有点耗内存。因为指针本身也是需要开辟空间的。根据系统的不同指针占位不同。这里我总结了一下一个指针占位就是一个系统操作的基本位
- 这里基本位是什么意思呢?加入你是64位系统那么一个指针就是64位即8个字节。如果你是32位系统那么一个指针就是32位即4个字节
- 也就是说如果我在redis中向双向链表中存储N个英文字母,我们又知道一个应为字母占1个字节。那么这N个元素就是N的listNode . 那么维持着N个listNode中间就需要2*(N-1)个指针。在64位系统中也就是我们需要开辟将近129倍的空间来存储内容。上述情况我们只有N个字节的内容,却需要
2*(N-1)*8+N个字节来构建listNode。 - 随着节点的递增我们浪费程度越离谱。所以redis在双向链表的基础上结合了ziplist进行改良。
过渡原因

ziplist
- 在ziplist章节中我们知道ziplist是一块连续内存,是redis对内存的一种改良结构。ziplist实现了内存的高使用率!

linkedlist+ziplist好处

quicklist引入
- quicklist是在redis3.2之后引入的,笔者这里使用的是redis6.4方便源码好像并没有quicklist源码。
- 后来翻阅了之后redis6.4好像取消了quicklist . 结构。所以我又特别下了一个3.2的版本。这里具体的是redis3.2.4版本!!!
庐山真面目
quicklist

- 通过他的源码我们很清晰的看出他的内部数据结构!这个大家应该很熟悉了。quicklist可以说就是我们之前的linkedList 结构。内部就是双向链表只不过里面的属性稍微多了点

- 通过图示是不是感觉和linkedList一样。

- 接下来我们看看quicklist中各个属性的含义吧

quicklistNode
- quicklist只是一个抽象的概念,真正负责数据的存储的是组成quicklist的成员quicklistNode 。

- 各个属性的作用

通过上面的属性介绍,我们也可以了解了解到node节点中的数据结构就是ziplist 。在ziplist基础上会在进行压缩达到内存更高的使用效率!
关于压缩这里我们不用太去了解!主要目的就是一种编码,这种编码是无法真正使用的在使用期间redis会进行解码操作。在解码操作期间就是通过recompress属性来标记的。

insert
- 在了解quicklist基本结构之后我们在看看insert时结构会发生哪些变化!上面我们也提到了在redis.conf配置文件中
list-max-ziplist-size属性是用来设置quicklist中每个节点中的ziplist存储的大小设置的。
| 属性值 | 作用 |
|---|---|
| -1 | 每个quicklistNode节点的ziplist所占字节数不能超过4kb |
| -2 | 每个quicklistNode节点的ziplist所占字节数不能超过8kb |
| -3 | 每个quicklistNode节点的ziplist所占字节数不能超过16kb |
| -4 | 每个quicklistNode节点的ziplist所占字节数不能超过32kb |
| -5 | 每个quicklistNode节点的ziplist所占字节数不能超过64kb |
| int | ziplist包含的entry上限 |
两端插入

- 第一种情况就是我们需要插入的数据是在两端的。如上图所示我们在redis.conf配置文件中设置的
list-max-ziplist-size: 2。表示内部节点ziplist中entry个数最大为2 。此时我们head头部节点中已经存储了两个内容,tail尾部节点存储的是1个节点! - 这个时候如果我们想头部添加一个元素是obj1 。 可想而知我们是无法加入的,这个时候redis会重新创建一个ziplist结构并包含obj1 ,将新创建的ziplist加入到链表的头部之后

- 而obj2加入尾结点时,因为尾结点的节点数是1还未达到峰值2,所以直接就加入了。最终的效果图如下

中间插入
st=>start: Insert
ziplistInsert=>operation: 向ziplist中插入
subziplistInsert=>operation: 将该ziplist拆分两个ziplist, 在对应位置加入
insertNear=>operation: 插入相邻的ziplist中
newZipInsert=>operation: 新建ziplist插入
cond=>condition: ziplist是否可以容纳
headtailCond=>condition: 插入位置在ziplist两端
nearheadtailCond=>condition: 相邻ziplist是否可以容纳
e=>end: 快乐的一天
st->cond
cond(yes)->ziplistInsert
cond(no)->headtailCond(yes)->nearheadtailCond
headtailCond(no)->subziplistInsert
nearheadtailCond(yes)->insertNear
nearheadtailCond(no)->newZipInsert
总结

参考文献
【redis前传】集思广益之quicklist,取其精华去其糟粕的更多相关文章
- 【redis前传】redis整数集为什么不能降级
前言 整数集合相信有的同学没有听说过,因为redis对外提供的只有封装的五大对象!而我们本系列主旨是学习redis内部结构.内部结构是redis五大结构重要支撑! 前面我们分别从redis内部结构分析 ...
- 【redis前传】自己手写一个LRU策略 | redis淘汰策略
title: 自己手写一个LRU策略 date: 2021-06-18 12:00:30 tags: - [redis] - [lru] categories: - [redis] permalink ...
- Vue.js 入门指南之“前传”(含sublime text 3 配置)
题记:关注Vue.js 很久了,但就是没有动手写过一行代码,今天准备入手,却发现自己比菜鸟还菜,于是四方寻找大牛指点,才终于找到了入门的“入门”,就算是“入门指南”的“前传”吧.此文献给跟我一样“白痴 ...
- 博弈论(Game Theory) - 01 - 前传之占优战略均衡
博弈论(Game Theory) - 01 - 前传之占优战略均衡 开始 我们现在准备攀爬博弈论的几座高峰. 我们先看看在纳什均衡产生之前,博弈论的发展情况. 我们的第一座高峰是占优战略均衡. 囚徒困 ...
- 博弈论(Game Theory) - 02 - 前传之重复剔除严格劣战略的占优战略均衡
博弈论(Game Theory) - 02 - 前传之重复剔除严格劣战略的占优战略均衡 开始 "重复剔除劣战略的严格占优战略均衡"(iterated dominance equil ...
- 博弈论(Game Theory) - 03 - 前传之最大最小均衡
博弈论(Game Theory) - 03 - 前传之最大最小均衡 开始 最大最小均衡是由人冯·诺依曼和摩根斯坦提出.冯·诺依曼和摩根斯坦也被认为是博弈论的创始人. 冯·诺依曼提出的"最大最 ...
- 《java入门第一季》之Arrays类前传(排序案例以二分查找注意的问题)
根据排序算法,可以解决一些小案例.举例如下: /* * 把字符串中的字符进行排序. * 举例:"dacgebf" * 结果:"abcdefg" * * 分析: ...
- Android-自定义View前传-View的三大流程-Layout
Android-自定义View前传-View的三大流程-Layout 参考 <Android开发艺术探索> https://github.com/hongyangAndroid/FlowL ...
- Android自定义View前传-View的三大流程-Measure
Android自定义View前传-View的三大流程-Measure 参考 <Android开发艺术探索> https://developer.android.google.cn/refe ...
随机推荐
- Setup a Simple HTTP Proxy Server
The host 10.21.3.69 has no H3C client, so it can't access the internet. With Tinyproxy, we can setuu ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...
- 【XSS-labs】Level 11-15
Level 11 和level 10 差不多的页面,传参后查看页面源代码:依旧是第3个可以正常传参. 尝试level 10 的payload 发现 " 被实体化 可以打开控制台将第三个inp ...
- CVE-2021-1732 Windows 本地权限提升漏洞 EXP 下载
漏洞简介 2021年2月10日,微软修复了一个Windows本地权限提升漏洞,漏洞编号为 CVE-2021-1732 ,本地攻击者可以利用该漏洞将权限提升为 System ,目前EXP已公开. 影响范 ...
- 常见的六种容错机制:Fail-Over、Fail-Fast、Fail-Back、Fail-Safe,Forking 和 Broadcast
目录 1.Fail-Over:故障转移 2.Fail-Fast:快速失败 3.Fail-Back:失效自动恢复 4.Fail-Safe:失效安全 5.Forking:并行调用多个服务 6.Broadc ...
- 10BASE—T的主要技术特性
1)数据传输速率10Mbps基带传输 2)每段双绞线最大长度100m 3)一条通路允许连接HUB数4个,最多5段传输介质 4)拓扑结构星型 5)访问控制方式CSMA/CD 6)帧长度可变,最大1518 ...
- S3C2440—5.UART的使用
文章目录 一.S3C2440中的UART介绍 1.1 电平匹配 1.2 UART数据帧与波特率 1.3UART框图 二.UART的配置 2.1 UART引脚的配置 2.2 波特率的配置 2.3 数据帧 ...
- 一文搞懂Java/Spring/Dubbo框架中的SPI机制
几天前和一位前辈聊起了Spring技术,大佬突然说了SPI,作为一个熟练使用Spring的民工,心中一紧,咱也不敢说不懂,而是在聊完之后赶紧打开了浏览器,开始的学习之路,所以也就有了这篇文章.废话不多 ...
- Set重写hashCode和equals方法实现引用对象去重
运作原理: 首先判断hashCode是否相同,如果不同,直接判定为两个不同的对象.如果hashCode相同,再去比较equals是否一样,如果一样,则为同一个对象.如果不一样,则是两个不同对象. 那么 ...
- ReentrantLock可重入锁lock,tryLock的区别
void lock(); Acquires the lock. Acquires the lock if it is not held by another thread and returns im ...