每日一博 | Redis 压缩列表原理与应用分析
摘要
Redis是一款著名的key-value内存数据库软件,同时也是一款卓越的数据结构服务软件。它支持字符串、列表、哈希表、集合、有序集合五种数据结构类型,同时每种数据结构类型针对不同的应用场景又支持不同的编码方式。这篇文章主要介绍压缩列表编码,在理解压缩列表编码原理的基础上介绍Redis对压缩列表的应用,最后再对Redis压缩列表应用进行分析。
Redis压缩列表原理与应用
压缩列表是一种数据结构,这种数据结构的功能是将一系列数据与其编码信息存储在一块连续的内存区域,这块内存物理上是连续的,逻辑上被分为多个组成部分,其目的是在一定可控的时间复杂读条件下尽可能的减少不必要的内存开销,从而达到节省内存的效果,这么介绍有点玄乎,我们先一起看看它的实现原理吧,Redis3.2版本中,作者对压缩列表的实现在ziplist.h和ziplist.c中。
压缩列表原理
我认为将数据按照一定规则存储在内存中可以用“编码”这个词描述,因此下面会常用“编码”这个词。
总体编码
上面说到压缩列表是一块连续的内存区域,这块内存区域布编码示意图大致如下:
Redis压缩列表内存编码示意图
常态的压缩列表内存编码如上图所示,整个内存块区域内分为五个部分,下面分别介绍着五个部分:
zlbytes:存储一个无符号整数,固定四个字节长度,用于存储压缩列表所占用的字节,当重新分配内存的时候使用,不需要遍历整个列表来计算内存大小。
zltail:存储一个无符号整数,固定四个字节长度,代表指向列表尾部的偏移量,偏移量是指压缩列表的起始位置到指定列表节点的起始位置的距离。
zllen:压缩列表包含的节点个数,固定两个字节长度,源码中指出当节点个数大于2^16-2个数的时候,该值将无效,此时需要遍历列表来计算列表节点的个数。
entryX:列表节点区域,长度不定,由列表节点紧挨着组成。
zlend:一字节长度固定值为255,用于表示列表结束。
列表元素编码
上面介绍了压缩列表的总体内存布局,对于初entryX区域以外的四个区域的长度都是固定的,下面再看看entryX区域的编码情况。
每个列表节点由三部分组成:
压缩列表节点编码示意图
每个压缩列表节点区域头部包含两部分,一部分叫做previous length,另一部分叫encoding,最后是主体内容,叫做content,下面分别介绍他们:
previous length
用于存储上一个节点的长度,因此压缩列表可以从尾部向头部遍历,即当前节点位置减去上一个节点的长度即得到上一个节点的起始位置。previous length的长度可能是1个字节或者是5个字节,如果上一个节点的长度小于254,则该节点只需要一个字节就可以表示前一个节点的长度了,如果前一个节点的长度大于等于254,则previous length的第一个字节为254,后面用四个字节表示当前节点前一个节点的长度。这么做很有效地减少了内存的浪费。
encoding
节点的encoding保存的是节点的content的内容类型以及长度,encoding类型一共有两种,一种字节数组一种是整数,encoding区域长度为1字节、2字节或者5字节长。Redis作者巧妙的利用了前两个字节来表示content存储的内容类型和encoding区域的长度,我们先看看字节数组类型的encoding内容:
content为字节数组的encoding内容
再看看整数编码类型的encoding内容:
content为整数的encoding内容
content
content区域用于保存节点的内容,节点内容类型和长度由encoding决定,上面可以看出目前content的内容类型有整数类型和字节数组类型,且某些条件下content的长度可能为0。
相信到这里,我们都明白了压缩列表的原理,压缩列表并不是对数据利用某种算法进行压缩,而是将数据按照一定规则编码在一块连续的内存区域,目的是节省内存。下面我们看看压缩列表在Redis中的应用领域。
Java架构/分布式:705127209(大牛交流群)没有开发经验勿加!
Redis中压缩列表的应用
Redis中,不同的数据类型广泛地应用了压缩列表编码,整理如下表:
Redis中数据结构类型与压缩列表的应用
上表总结了压缩列表编码在Redis不同的数据类型中的应用,Redis一共支持五种数据结构类型,其中有三种数据结构在一定条件下会应用压缩列表,至于什么条件后面会分析,值得一提的是Redis当前支持的GEO(地理位置)对压缩列表也有应用,具体此处不做讨论。
Redis压缩列表应用分析
上面部分介绍了Redis压缩列表的原理与应用,下面简单分析一下,主要从通过试图回答一些问题来分析:Redis为什么使用压缩列表?使用压缩列表的好处是什么?使用压缩列表的好处还有什么?压缩列表的应用对与我们使用内存有没有什么启发?
Redis对于每种数据结构、无论是列表、哈希表还是有序集合,在决定是否应用压缩列表作为当前数据结构类型的底层编码的时候都会依赖一个开关和一个阈值,开关用来决定我们是否要启用压缩列表编码,阈值总的来说通常指当前结构存储的key数量有没有达到一个数值(条件),或者是value值长度有没有达到一定的长度(条件)。任何策略都有其应用场景,不同场景应用不同策略。为什么当前结构存储的数据条目达到一定数值使用压缩列表就不好?压缩列表的新增、删除的操作平均时间复杂度为O(N),随着N的增大,时间必然会增加,他不像哈希表可以以O(1)的时间复杂度找到存取位置,然而在一定N内的时间复杂度我们可以容忍。然而压缩列表利用巧妙的编码技术除了存储内容尽可能的减少不必要的内存开销,将数据存储于连续的内存区域,这对于Redis本身来说是有意义的,因为Redis是一款内存数据库软件,想办法尽可能减少内存的开销是Redis设计者一定要考虑的事情。
另外,经过仔细琢磨,我认为使用压缩列表的好处除了节约内存之外,还有减少内存碎片的作用,我把这种行为叫做"合并存储",也就是将很多小的数据块存储在一个比较大的内存区域,试想想,如果我们将要存储的数据都是很小的条目,我们为每一个数据条目都单独的申请内存,结果是这些条目将有可能分散在内存的每一个角落,最终导致碎片增加,这是一件令人头疼的事情。
总结
这篇文章在介绍Redis压缩列表原理与应用的基础之上对Redis压缩列表的应用进行分析,分析部分主要掺杂着个人的理解与认知,如果有不同观点或者补充观点,欢迎留言讨论。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
开源头条公测版上线 —— 开发者专属的头条
一直以来都有不少用户表示,开源中国每天产出的资讯数量太少,哪怕是攒了一周的资讯,不一会儿也就看完了,意犹未尽而心难平,如同进入贤者时刻一般。 本着“为开发者服务”的使命,既然开发者的阅读需求如此强盛,我们就要努力让各位看得爽,看得过瘾。 于是我们在近日上线了一个新频道 —— 开源头条。 >>>https://www.oschina.net/feed 虽然开源头条目前尚处于 Beta 阶段,但还是忍不住拿出来给各位尝尝鲜。所以大家尽情使用吧,欢迎提出宝贵意见和专业看法,如果实在忍不住要开喷的话,麻烦走一下流程,用了再喷。 开源头条基于推荐算法,会根据你的阅读喜好不断调整,只为让你看到感兴趣的内容。 FAQ 开源头条的内容来自哪里? 1.开源中国全站内容,包括资讯、软件、问答、博客和翻译等版块由用户生产的内容,以及码云精品项目。 2.外网的优质网站,其中包含 300+ 英文网站。 如何调校开源头条,以使推荐的内容更符合自己的口味和需求? 简单来说就是多用多阅读。 多阅读自己感兴趣的文章,用得越多推荐系统越懂你。后续还会推出「我不喜欢」或者「不感兴趣」之类的反馈操作,以保证...
- 下一篇
微软开发者透露 Linux 在 Azure 上的使用量比 Windows Server 更多
三年半前,微软云公司 Azure CTO 的 Mark Russinovich 说:“四分之一的 Azure 实例是 Linux。”接下来,在 2017 年,微软披露了 40% 的 Azure 虚拟机是基于 Linux 的。然后在 2018 年秋季,微软云与企业集团执行副总裁 Scott Guthrie 在一次独家采访中说,“大约一半的 Azure 虚拟机是 Linux 的”。 现在,微软 Linux 内核开发人员 Sasha Levin 在请求允许微软加入 Linux 安全列表时透露,“我们云上的 Linux 使用量已经超过了 Windows”。 其实也并非完全如此。 很大程度上,Linux 是在内部服务器和云上运行企业计算的,而多年以来 Windows Server 的市场份额也一直在下降。在最新的 IDC 全球操作系统和子系统市场份额报告中,Linux 占据了 68% 的市场份额,从这开始,Linux 在 Azure 上的使用才持续增长。 Guthrie 说过的,“每个月,Linux 都会上升”,所以 Linux 统治Azure 也只是时间问题。 选择 Linux 的不仅仅是微软...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker安装Oracle12C,快速搭建Oracle学习环境
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7,CentOS8安装Elasticsearch6.8.6