Redis数据结构三之压缩列表
本文首发于公众号:Hunter后端
原文链接:Redis数据结构三之压缩列表
本篇笔记介绍压缩列表。
在 Redis 3.2 版本之前,压缩列表是列表对象、哈希对象、有序集合对象的的底层实现之一。
因为压缩列表本身结构上的一些缺陷,压缩列表这个结构被替换了,但是压缩列表结构本身有一些可取之处,并且替换它的新结构 listpack 与之很相似,所以我们这里还是介绍一下压缩列表的结构和存储
1、压缩列表的结构
压缩列表是 Redis 为了节约内存而开发的,由一个连续内存块组成的顺序型数据结构。
它的组成结构如下:
| zlbytes | zltail | zllen | entry1 | entry2 | ... | entryN | zlend |
压缩列表的英文名是 ziplist,所以它的属性都是 zl 开头。
1. 列表属性介绍
zlbytes
zlbytes 长度为 4 字节,记录整个压缩列表占用的内存字节数
zltail
zltail 长度为 4 字节,记录压缩列表最后一个节点,也就是我们结构示例中的 entryN 到 zlbytes 的地址之间的偏移量。
zllen
zllen 长度为 2 字节,记录的是压缩列表包含的节点数量,也就是结构中的 N。
zlend
zlend 长度为 1 字节,它的值为 0xFF(十进制 255),用于标记压缩列表的末端。
2. 压缩列表节点属性介绍
对于每一个 entry 节点,也就是压缩列表中的元素节点,它的结构示意如下:
| previous_entry_length | encoding | content |
previous_entry_length
previous_entry_length 属性记录的是压缩列表中前一个节点的长度
previous_entry_length 属性本身的长度可以是 1 字节或者 5 字节
如果前一节点的长度小于 254 字节,那么 previous_entry_length 属性的长度为 1 字节,前一个节点的长度保存在这个字节里
如果前一节点的长度大于等于 254 字节,那么 previous_entry_length 属性的长度为 5 字节,第一个字节被设置成 0xFE(也就是 254),之后的四个字节用于前一节点的长度。
通过 previous_entry_length 属性,我们可以通过当前节点的地址和 previous_entry_length 属性,计算出前一个节点的起始地址,压缩列表的从表尾到表头的遍历操作就是使用这个原理一个节点一个节点往前回溯实现的。
encoding
encoding 属性记录了节点的 content 属性所保存数据的类型以及长度。
encoding 的值如果是一字节长,且值的最高位以 11 开头,那么表示是整数编码,表示 content 属性保存着整数值。
encoding 的值为 一字节、两字节、五字节长,且值的最高位为 00、01、10 则表示是字节数组编码
content
content 属性保存的是节点的值,可以是一个字节数组或者整数,值的类型和长度由节点的 encoding 属性决定。
2、 连锁更新
在压缩列表的节点属性中,previous_entry_length 属性的长度是根据前一节点的长度来进行赋值的,如果前一节点的长度小于 254 字节,那么下一节点的 previous_entry_length 属性长度为 1 字节,如果前一节点的长度大于等于 254 字节,那么下一节点的 previous_entry_length 属性为 5 字节。
那么在这种情况下,就存在一种较为极端的情况,那就是压缩列表中每个节点的长度都在 250 - 253 字节之间,这时候,如果在表头插入一个长度大于等于 254 字节的节点,那么相对应的第二个节点的 previous_entry_length 的长度就要从 1 字节变为 4 字节,那么该节点的整体长度就大于等于 254 字节。
依此类推,压缩列表的每一个节点的长度都会产生连锁反应,长度都会逐个变成大于等于 254 字节长度,程序就需要不断地对压缩列表执行空间重分配的操作。
Redis 将这种在特殊情况下产生的连续多次空间扩展操作称为连锁更新。
除了新增节点这种情况,还有一种删除节点也可能造成连锁更新的情况,比如有这么几个节点,big 节点的长度大于等于 254 字节,small 节点长度小于254 字节,e1 到 eN 的节点长度都在 250-253 字节之间。
| zlbytes | zltail | zllen | big | small | entry1 | entry2 | ... | entryN | zlend |
这时候,删除 small 节点,entry1 节点的前节点的长度就会从 250-253 变成大于等于 254,因此 entry1 节点的 previous_entry_length 长度就会变成 5 字节,entry1 整体长度就会大于等于 254 字节,依次之后每个节点都会这样产生连锁更新。
尽管连锁更新的复杂度较高,但它真正造成性能问题的几率是很低的:
首先,压缩列表里要恰好有多个连续的、长度介于 250-253 字节之间的节点,连锁反应才有可能被引发
其次,即使出现连锁更新,但只要被更新的节点数量不多,就不会对性能造成任何影响,比如对只拥有三五个节点的压缩列表进行连锁更新。
3、压缩列表缺点
压缩列表虽然能节约内存,但仍然存在一些缺点:
- 需要通过遍历操作来查找节点,元素过多时会造成查询效率低下
- 对压缩列表节点进行新增或者修改时,可能会造成连锁更新的问题
如果想获取更多后端相关文章,可扫码关注阅读:

Redis数据结构三之压缩列表的更多相关文章
- Redis学习之ziplist压缩列表源码分析
一.压缩列表ziplist在redis中的应用 1.做列表键 当一个列表键只包含少量列表项,并且每个列表项要么是小整数,要么是短字符串,那么redis会使用压缩列表作为列表键的底层实现 2.哈希键 当 ...
- 图解Redis之数据结构篇——压缩列表
前言 同整数集合一样压缩列表也不是基础数据结构,而是 Redis 自己设计的一种数据存储结构.它有点儿类似数组,通过一片连续的内存空间,来存储数据.不过,它跟数组不同的一点是,它允许存储的数据 ...
- [redis读书笔记] 第一部分 数据结构与对象 压缩列表
压缩列表是为了节省内存而设计的,是列表键和哈希键的底层实现之一. 压缩列表的逻辑如下,
- redis源码之压缩列表ziplist
压缩列表ziplist1.简介连续,无序的数据结构.压缩列表是 Redis 为了节约内存而开发的, 由一系列特殊编码的连续内存块组成的顺序型(sequential)数据结构. 2.组成 属性 类型 长 ...
- redis 底层数据结构 压缩列表 ziplist
压缩列表是列表键和哈希键的底层实现之一.当一个列表键只包含少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,redis就会使用压缩列表来做列表键的底层实现 当一个哈希键只包含少量键 ...
- Redis数据结构之压缩列表
压缩列表是Redis为了节约内存而开发的,由一系列特殊编码的连续内存块组成的顺序型数据结构.一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或者一个整数值. 一.压缩列表结构1. 压缩列 ...
- Redis 底层数据结构之压缩列表
文章参考:<Redis 设计与实现>黄建宏 压缩列表 压缩列表 ziplist 是列表键和哈希键的底层实现之一.当一个列表键只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比 ...
- Redis压缩列表原理与应用分析
摘要 Redis是一款著名的key-value内存数据库软件,同时也是一款卓越的数据结构服务软件.它支持字符串.列表.哈希表.集合.有序集合五种数据结构类型,同时每种数据结构类型针对不同的应用场景又支 ...
- Redis压缩列表
此篇文章是主要介绍Redis在数据存储方面的其中一种方式,压缩列表.本文会介绍1. 压缩列表(ziplist)的使用场景 2.如何达到节约内存的效果?3.压缩列表的存储格式 4. 连锁更新的问题 5 ...
- redis 笔记01 简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表
文中内容摘自<redis设计与实现> 简单动态字符串 1. Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simple Dynamic String,简单动态 ...
随机推荐
- 【AI 全栈 SOTA 综述 】这些你都不知道,怎么敢说会 AI?【语音识别原理 + 实战】
章目录 前言语音识别原理 信号处理,声学特征提取 识别字符,组成文本 声学模型 语言模型 词汇模型语音声学特征提取:MFCC和LogFBank算法的原理实战一 ASR语音识别模型 ...
- urllib.request发送get请求
发送请求 urllib.request库 模拟浏览器发起一个HTTP请求,并获取请求响应结果 urllib.request.urlopen的语法格式 urllib(url.data = None,[t ...
- [C++STL教程]1.vector容器是什么?实用教程来啦!超简单易懂,拿来就用
C++与传统的C语言有一个很大的区别,就是新增了标准模板库 STL(Standard Template Library),它是 C++ 标准库的一部分,不需要单独安装,只需要 #include 对应的 ...
- 在windows系统中设置MySQL数据库
MySQL搭建 效果图 step1:下载安装包 https://downloads.mysql.com/archives/community/ step2:解压后即完成安装 step3:创建 my.i ...
- 【实战】SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
JavaDog Chat v1.0.0 基于SpringBoot+uniapp简单通讯聊天软件 项目介绍 JavaDog Chat 简单通讯聊天软件是基于SpringBoot+MybatisPlus+ ...
- window的子对象
在控制台输入 history history.length 历史记录个数history.back() 后退history.forward() 前进history.go(n) 跳到某一页,可正可负,当n ...
- react中登录注册 使用验证码验证
后端接口 var express = require('express'); var router = express.Router(); var User = require('./../sql/c ...
- VBA GET POST HTTP VBA网络爬虫 最新Excel自动获取股票信息源码 EXCEL自动获取网络数据 最新VBA自动抓取股票数据源码
最新Excel自动获取股票信息源码 EXCEL自动获取网络数据 最新VBA自动抓取股票数据源码 通过接口获取股票数据内容的主要优点包括以下几点: 实时性高:通过访问股票数据接口,可以实时获取到股票的实 ...
- 记某gov门户网站渗透测试(已修复)
前言: 免责声明:涉及到的所有技术仅用来学习交流,严禁用于非法用途,未经授权请勿非法渗透.否则产生的一切后果自行承担! 该渗透测试项目为已授权项目,本文已对敏感部分做了相关处理. 正文: SQL注入( ...
- 随机服务系统模拟—R实现(三)
M/M/c随机服务系统的模拟 M/M/1服务系统:(1)队列长度没有限制:(2)顾客到达的时间间隔和服务时间均服从指数分布:(3)服务台数量为c. 一.M/M/c随机服务系统的模拟 在M/M/c排队系 ...