redis 从0到1完整学习 (七):ZipList 数据结构
文章目录
- 1. 引言
- 2. redis 源码下载
- 3. zipList 数据结构
- 3.1 整体
- 3.2 entry 数据结构分析
- 3.3 连锁更新
- 4. 参考
1. 引言
前情提要:
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
本文主要结合源码来介绍 ZipList 的数据结构
2. redis 源码下载
Redis 源码可以点击这里下载,方便查看其中定义的一些数据结构。

3. zipList 数据结构
3.1 整体
zipList 是为了提高存储效率而设计的一种特殊编码的双向链表,由一系列特殊编码的连续内存块组成。可以在任意一端进行 push 和 pop 操作,并且该操作的时间复杂度为 O(1)。它可以存储字符串或者整数,存储整数时是采用整数的二进制而不是字符串形式存储。
zipList 数据结构示意图:

| 名称 | 类型 | size | 用途 |
|---|---|---|---|
| zlbytes | uint32_t | 4 字节 | 记录整个 zipList 占用的字节总数,即图中 zlbytes 的起始 到 zlend 的末尾 |
| zltail | uint32_t | 4 字节 | 记录 zipList 尾节点距离起始地址有多少字节,即图中 zlbytes 起始 到 tail 起始的偏移量,通过这个偏移量,可以确定尾节点的地址 |
| zllen | uint16_t | 2 字节 | 记录了压缩列表包含的节点数量。 最大值为 UINT16_MAX (65534)。如果超过这个值,会记录为65535。 |
| entry | 不定 | 压缩列表包含的各个节点,节点的长度由节点保存的内容决定。 | |
| zlend | uint8_t | 1 字节 | 特殊值 0xFF (十进制 255 ),用于标记压缩列表的末端。 |
3.2 entry 数据结构分析
ziplist 中的每个 entry 都以包含两条信息的元数据作为前缀。首先,存储上一个 entry 的长度,以便能够从后向前遍历列表。其次,提供 entry encoding,表示 entry 类型,整数或字符串,如果是字符串,它还表示字符串有效负载的长度。因此,完整的 entry 存储如下:

- prevlen:前一个 entry 的长度,占1个或5个字节。
- 如果前一个 entry 的长度 < 254字节,则采用1个字节来保存这个长度值
- 如果前一个 entry 的长度 > 254字节,则采用5个字节来保存这个长度值,第一个字节为 0xfe,后四个字节才是真实长度数据
- encoding:编码属性,记录数据类型(字符串还是整数)以及长度,占用1个、2个或5个字节
- entry-data:负责保存 entry 数据,可以是字符串或整数
根据 redis 源码的注解来看,encoding 的编码如下:
(1)字符串编码
| encoding 格式 | 编码长度 | 字符串大小 |
|---|---|---|
| |00pppppp| | 1 bytes | <= 63 bytes |
| |01pppppp|qqqqqqqq| | 2 bytes | <= 16383 bytes |
| |10000000|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| | 5 bytes | <= 4294967295 bytes |
例如,下面保存 ab、bc 字符串示例:
* [13 00 00 00] [0e 00 00 00] [02 00] [00 02 61 62] [04 02 62 63] [ff]* | | | | | |* zlbytes zltail zllen "ab" "bc" end*
a 的 ASCII 码是97,对应的16进制是61;
b 的 ASCII 码是98,对应的16进制是62;
c 的 ASCII 码是99,对应的16进制是63;
ab 的编码是 6162,长度是2字节,所以 encoding 是 00000010 即 16进制02,而前一个 entry 不存在,因而 prevlen 为 0,所以 ab 编码为 00026162;同样的 bc 前一个 entry 为 ab,字节一共为4,所以 bc 编码为 04026263。
(2)数字编码
| encoding 格式 | 编码长度 | 整数类型 |
|---|---|---|
| 11000000 | 1 | int16_t(2 bytes) |
| 11010000 | 1 | int32_t(4 bytes) |
| 11100000 | 1 | int64_t(8 bytes) |
| 11110000 | 1 | 24位有符整数(3 bytes) |
| 11111110 | 1 | 8位有符整数(1 bytes) |
| 1111xxxx | 1 | 在xxxx位置保存数值,范围从0001~1101,减1后结果为实际值 |
例如,下面是 redis 源码给出的保存 2、5 整数示例:
* [0f 00 00 00] [0c 00 00 00] [02 00] [00 f3] [02 f6] [ff]* | | | | | |* zlbytes zltail zllen "2" "5" end*
2 的长度在 0001~1101,对应上面表格的最后一种,所以 encoding 为 11110011,即16进制的 f3 (这里的3,实际为2+1);同样 5 encoding 为 11110110,即 f6
3.3 连锁更新
zipList 的每个 entry 都包含 prevlen 来记录上一个节点的大小,长度是1个或5个字节:
- 如果前一节点的长度 < 254字节,则采用1个字节来保存这个长度值
- 如果前一节点的长度 >= 254字节,则采用5个字节来保存这个长度值,第一个字节为0xfe,后四个字节才是真实长度数据
当一种边界场景下,插入了一个 entry,entry 的大小超过了 254 字节,导致后续大范围的 entry 的 prevlen 由1字节转为用5个字节来保存,触发了连锁更新,同时删除也可能触发连锁更新。
4. 参考
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
相关文章:
redis 从0到1完整学习 (七):ZipList 数据结构
文章目录 1. 引言2. redis 源码下载3. zipList 数据结构3.1 整体3.2 entry 数据结构分析3.3 连锁更新 4. 参考 1. 引言 前情提要: 《redis 从0到1完整学习 (一):安装&初识 redis》 《redis 从0到1完整学习 (二&am…...
2015年第四届数学建模国际赛小美赛C题科学能解决恐怖主义吗解题全过程文档及程序
2015年第四届数学建模国际赛小美赛 C题 科学能解决恐怖主义吗 原题再现: 为什么人们转向恐怖主义,特别是自杀性恐怖主义?主要原因是什么?这通常是大问题和小问题的结合,或者是一些人所说的“推拉”因素。更大的问题包…...
基于Java开发的微信约拍小程序
一、系统架构 前端:vue | element-ui 后端:springboot | mybatis 环境:jdk8 | mysql8 | maven | mysql 二、代码及数据库 三、功能说明 01. 首页 02. 授权登录 03. 我的 04. 我的-编辑个人资料 05. 我的-我的联系方式 06. …...
蓝桥杯的学习规划
c语言基础: Python语言基础 学习路径:画框的要着重学习...
EMC噪声的本质
01 频谱的含义 频谱是将电磁波分解为正弦波分量,并按波长顺序排列的波谱,就是将具有复杂组成的东西分解(频谱分析仪)为单纯成分,并把这些成分按其特征量的大小依序排列(部分不计),…...
Redis遇到过的问题 (Could not get a resource from the pool )
生产上通过scan命令,查询一个大key耗时40s后,报 Could not get a resource from the pool,初步报错是连接池的连接数不够,从网上搜了一些解决方案。 排查过程: 一、首先需要先尝试连接redis,如果连接不上那…...
Spring Boot 3.2 新特性之 HTTP Interface
SpringBoot 3.2引入了新的 HTTP interface 用于http接口调用,采用了类似 openfeign 的风格。 具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-http-interface 一、概述 HTTP Interface 是一个类似于 openfeign 的同步接口调…...
Flask+Mysql项目docker-compose部署(Pythondocker-compose详细步骤)
一、前言 环境: Linux、docker、docker-compose、python(Flask)、Mysql 简介: 简单使用Flask框架写的查询Mysql数据接口,使用docker部署,shell脚本启动 优势: 采用docker方式部署更加便于维护,更加简单快…...
DDOS攻击简介——什么是DDOS
DDoS是什么? DDoS是分布式拒绝服务攻击(Distributed denial of service attack)的简称。 分布式拒绝服务器攻击(以下均称作DDoS)是一种可以使很多计算机(或服务器)在同一时间遭受攻击,使被攻击的目标无法正常使用的一种网络攻击方式。DDoS攻击在互联网上已经出现过…...
龙蜥开源操作系统能解决CentOS 停服造成的空缺吗?
龙蜥开源操作系统能解决CentOS 停服造成的空缺吗? 本文图片来源于龙蜥,仅做介绍时引用用途,版权归属龙蜥和相关设计人员。 一、《国产服务器操作系统发展报告(2023)》称操作系统已步入 2.0 时代,服务器操作…...
『Linux升级路』基础开发工具——gdb篇
🔥博客主页:小王又困了 📚系列专栏:Linux 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、背景知识介绍 二、gdb指令介绍 一、背景知识介绍 在软件开发中,…...
边缘计算云边端全览—边缘计算系统设计与实践【文末送书-10】
文章目录 一.边缘计算1.1边缘计算的典型应用 二.边缘计算 VS 云计算三.边缘计算系统设计与实践【文末送书-10】3.1 粉丝福利:文末推荐与福利免费包邮送书! 一.边缘计算 边缘计算是指在靠近物或数据源头的一侧,采用网络、计算、存储、应用核心…...
使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错的问题
目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序,查看库与库的依赖关系,找出出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总(专栏文章列表&…...
Servlet技术之Cookie对象与HttpSession对象
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 Servlet技术之Cookie对象与HttpSession对象 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前…...
winlogbeat收集Windows事件日志传给ELK
服务器部署winlogbeat后,修改winlogbeat.yml: ###################### Winlogbeat Configuration Example ######################### This file is an example configuration file highlighting only the most common # options. The winlogbeat.reference.yml fi…...
Gin框架之使用 go-ini 加载.ini 配置文件
首先,联想一个问题,我们在部署服务时,通常为了方便,对于需要迭代更新的代码进行修改,但是比对shell,可以搞一个变量将需要修改的,以及修改起来变动处多的,写在变量内,到时候如果需要变更,可以直接变更变量即可; 那么,golang有没有什么方式可以将需要变的东西保存起…...
SpringMVC:整合 SSM 上篇
文章目录 SpringMVC - 03整合 SSM 上篇一、准备工作二、MyBatis 层1. dao 层2. service 层 三、Spring 层四、SpringMVC 层五、执行六、说明 SpringMVC - 03 整合 SSM 上篇 用到的环境: IDEA 2019(JDK 1.8)MySQL 8.0.31Tomcat 8.5.85Maven…...
BFS解决多源最短路相关leetcode算法题
文章目录 1.01矩阵2.飞地的数量3.地图中的最高点4.地图分析 1.01矩阵 01矩阵 class Solution {int dx[4] {0,0,1,-1};int dy[4] {1,-1,0,0}; public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {//正难则反,找0…...
ARM GIC(四) gicv3架构基础
GICv3架构是GICv2架构的升级版,增加了很多东西。变化在于以下: 使用属性层次(affinity hierarchies),来对core进行标识,使gic支持更多的core 将cpu interface独立出来,用户可以将其设计在core…...
Kafka日志
位置 server.properties配置文件中通过log.dir指定日志存储目录 log.dir/{topic}-{partition} 核心文件 .log 存储消息的日志文件,固定大小为1G,写满后会新增一个文件,文件名表示当前日志文件记录的第一条消息的偏移量。 .index 以偏移…...
[认知计算] 神经网络架构:从生物启发的神经元到现代激活函数演进
1. 从生物神经元到人工神经元的数学抽象 1943年,麦卡洛克和皮茨在论文《神经活动中内在思想的逻辑演算》中首次提出用数学模型模拟生物神经元。这个看似简单的想法,彻底改变了人类对智能的认知方式。生物神经元由树突、细胞体和轴突三部分组成࿱…...
LumiPixel优化升级:如何利用Z-Image模型生成更细腻的像素人像
LumiPixel优化升级:如何利用Z-Image模型生成更细腻的像素人像 1. 引言:像素艺术的复兴与挑战 像素艺术作为一种独特的数字艺术形式,近年来在游戏、NFT和数字设计领域迎来复兴。然而传统像素创作面临两大核心挑战: 细节表现力不…...
LiuJuan Z-Image Generator参数详解:CFG Scale=2.0与12步生成高质量人像
LiuJuan Z-Image Generator参数详解:CFG Scale2.0与12步生成高质量人像 想用AI生成一张惊艳的人像照片,却发现要么细节模糊,要么风格怪异,怎么调参数都达不到理想效果?如果你也遇到过类似问题,那今天这篇文…...
Crawl4AI浏览器配置文件创建与键盘交互处理终极指南:打造个性化爬虫身份
Crawl4AI浏览器配置文件创建与键盘交互处理终极指南:打造个性化爬虫身份 【免费下载链接】crawl4ai 🔥🕷️ Crawl4AI: Open-source LLM Friendly Web Crawler & Scrapper 项目地址: https://gitcode.com/GitHub_Trending/craw/crawl4ai…...
c++ 字符大小写转化
#include <iostream> using namespace std;int main() {char a;cin >> a;//a-z-97-122//A-Z-65-90//差32//小写转大写 if(97<(int)a && (int)a<122){a(int)a-32;cout << a; return 0; }//大写转小写 if(65<(int)a && (int)a<90)…...
COMSOL数值模拟:N2和CO2混合气体在THM热流固三场耦合下增强瓦斯抽采
COMSOL数值模拟,实现N2和CO2混合气体在THM热流固三场耦合情况下增强瓦斯(煤层气抽采)煤层气抽采效率提升这事儿,最近在实验室搞了个骚操作——往煤层里怼氮气和二氧化碳的混合气。说人话就是拿这俩气体当开塞露,把卡在…...
OpenClaw对接GLM-4.7-Flash:模型版本管理指南
OpenClaw对接GLM-4.7-Flash:模型版本管理指南 1. 为什么需要关注模型版本管理 上周我在调试一个自动化文档处理流程时,遇到了一个奇怪的现象:同样的OpenClaw脚本,前一天还能完美运行的文档摘要功能,第二天突然开始输…...
OpenClaw+GLM-4.7-Flash:自动化电子书生成与排版工具
OpenClawGLM-4.7-Flash:自动化电子书生成与排版工具 1. 为什么需要自动化电子书制作 作为一个经常需要整理技术文档的开发者,我过去制作电子书的流程堪称"手工活地狱":先在多个网页间复制粘贴内容,用Word调整格式&…...
使用现代 Java 技术栈构建企业级 AI 应用
使用现代 Java 技术栈构建企业级 AI 应用 引言 随着人工智能技术的快速发展,企业级 AI 应用的需求也迅速增长。Java 作为一门成熟的企业级编程语言,其生态系统在 AI 应用开发中扮演着重要角色。本文将探讨如何利用 Java 技术栈构建生产级 AI 应用&#x…...
PostgreSQL 冻结(Freeze)机制深度解析
PostgreSQL 冻结(Freeze)机制深度解析一、为什么需要冻结 1.1 事务 ID 的本质 PostgreSQL 用 32 位无符号整数表示事务 ID(XID),范围 0 ~ 2^32-1(约 42 亿)。 其中有三个特殊 XID:XI…...
