当前位置: 首页 > news >正文

Redis数据结构之quicklist

前言

为了节省内存,Redis 推出了 ziplist 数据类型,采用一种更加紧凑的方式来存储 hash、zset 元素。因为查找的时间复杂度是 O(N),且写入需要重新分配内存,所以它仅适用于小数据量的存储,而且它还存在 连锁更新 的风险。
为了降低 ziplist 内存分配和连锁更新带来的影响,Redis 又推出了 quicklist 数据结构,我们来一睹它的风采。

注意:quicklist只是降低了 ziplist 内存分配和连锁更新带来的影响,没有从根本上解决这些问题。

quicklist

image.png
quicklist 是由若干个 ziplist 节点组成的一条双向链表,quicklist 的核心在于控制好每个 ziplist 的大小,因为 ziplist 越大,内存分配的开销越大,连锁更新带来的影响也就越大。
Redis 提供了list-max-ziplist-size参数来限制 ziplist 大小,值为负数时,限制的是 ziplist 的内存空间;值为正数时,限制的是 ziplist 元素数量。默认值是 -2,代表每个 ziplist 不超过 8KB。

  • -1:最大 4KB
  • -2:最大 8KB,默认值
  • -3:最大 16KB
  • -4:最大 32KB
  • -5:最大 64KB,不推荐
  • 0:限制元素数量

另外 Redis 还支持对 quicklist 中的 ziplist 节点做压缩,节点一旦压缩,就意味着每次访问都必须先解压缩,这势必会带来额外的开销。又因为两端的节点是访问频率较高的,特别是头尾节点是最常访问的节点。因此,为了兼顾访问性能和内存占用,Redis 提供了list-compress-depth参数配置 quicklist 两端不压缩的节点数,默认不压缩。

源码

  • quicklist

quicklist 是一条由若干个 ziplist 组成的双向链表,为了快速访问两端节点,quicklist 用两个指针分别指向了首尾节点,同时记录下链表里的节点数,以及所有的总元素数量,这样就不必每次都再统计一遍。
fill限制单个 ziplsit 长度,可以是内存空间也可以是元素数量;compress限制了两端不被压缩的节点数量。

typedef struct quicklist {quicklistNode *head; // 头节点quicklistNode *tail; // 尾节点unsigned long count; // 总元素数量unsigned long len; // 节点数int fill : QL_FILL_BITS; // 限制ziplist长度 正数代表限制元素数量 负数代表限制内存大小unsigned int compress : QL_COMP_BITS; // 链表两端不压缩的节点数 因为两端会被频繁访问unsigned int bookmark_count: QL_BM_BITS;quicklistBookmark bookmarks[];
} quicklist;
  • quicklistNode

quicklist 里的每个节点用 quicklistNode 表示,每个节点都都有两个指针分别指向前驱节点和后继节点。
每个节点都是一个单独的 ziplist,所以还有一个zl指针指向 ziplist。同时还会记录一些额外的数据,比如元素数量,ziplist 是否被压缩,能否被压缩等等。

typedef struct quicklistNode {struct quicklistNode *prev; // 前驱节点struct quicklistNode *next; // 后继节点unsigned char *zl; // ziplist指针unsigned int sz; // ziplist大小unsigned int count : 16; // ziplist元素数量unsigned int encoding : 2; // 编码方式 ziplist/quicklistLZFunsigned int container : 2; // 存储方式unsigned int recompress : 1; // 是否压缩unsigned int attempted_compress : 1; // 数据能否被压缩 太小就没压缩的必要unsigned int extra : 10; // 预留位
} quicklistNode;
  • quicklistLZF

ziplist 采用 LZF 压缩算法,压缩后的结构是 quicklistLZF。sz 记录压缩后的数据长度,compressed 是压缩后的字节数组。

typedef struct quicklistLZF {unsigned int sz; // 压缩后的长度char compressed[]; // 压缩后的数据
} quicklistLZF;
  • quicklistEntry

quicklistEntry 代表 quicklist 里的一个 ziplist 节点里的一个元素。

typedef struct quicklistEntry {const quicklist *quicklist; // quicklist指针quicklistNode *node; // 所属node节点unsigned char *zi; // ziplist指针unsigned char *value; // 节点值指针long long longval; // 整形值unsigned int sz; // 节点长度int offset; // 偏移量
} quicklistEntry;
  • quicklistCreate

创建一个空的 quicklist。

quicklist *quicklistCreate(void) {struct quicklist *quicklist;quicklist = zmalloc(sizeof(*quicklist));quicklist->head = quicklist->tail = NULL;quicklist->len = 0;quicklist->count = 0;quicklist->compress = 0;quicklist->fill = -2; // 默认每个ziplist不超过8KBquicklist->bookmark_count = 0;return quicklist;
}
  • quicklistPush

插入元素,根据 where 判断是插入到头部还是尾部。

void quicklistPush(quicklist *quicklist, void *value, const size_t sz,int where) {// 插入到头结点还是尾节点if (where == QUICKLIST_HEAD) {quicklistPushHead(quicklist, value, sz);} else if (where == QUICKLIST_TAIL) {quicklistPushTail(quicklist, value, sz);}
}
  • quicklistPushTail

以插入到尾部为例,quicklist 在插入前都会先判断目标 ziplist 是否能容纳新的元素,如果能容纳则直接插入;否则会创建新的 ziplist 节点再插入元素,这样就可以限制每个 ziplist 大小。

int quicklistPushTail(quicklist *quicklist, void *value, size_t sz) {quicklistNode *orig_tail = quicklist->tail;assert(sz < UINT32_MAX); // 判断插入的目标node是否能容纳新元素if (likely(_quicklistNodeAllowInsert(quicklist->tail, quicklist->fill, sz))) {quicklist->tail->zl =ziplistPush(quicklist->tail->zl, value, sz, ZIPLIST_TAIL);quicklistNodeUpdateSz(quicklist->tail);} else {// 不能容纳,则创建新的节点插入quicklistNode *node = quicklistCreateNode();node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_TAIL);quicklistNodeUpdateSz(node);_quicklistInsertNodeAfter(quicklist, quicklist->tail, node);}quicklist->count++;quicklist->tail->count++;return (orig_tail != quicklist->tail);
}

尾巴

为了降低 ziplist 内存分配的开销和连锁更新带来的影响,Redis 推出了 quicklist 数据结构,它可以看作是 ziplist 的一个升级版本,核心是限制每个 ziplist 的大小,然后把它们串联成一条双向链表,这样就可以把内存分配和连锁更新的开销分摊到每个节点上,影响就不会那么大了,同时又能利用 ziplist 节省内存的优点。
需要注意的是,quicklist 不是银弹,虽然可以降低 ziplist 的一些额外开销,但它的查找效率依然是 O(N)。

相关文章:

Redis数据结构之quicklist

前言 为了节省内存&#xff0c;Redis 推出了 ziplist 数据类型&#xff0c;采用一种更加紧凑的方式来存储 hash、zset 元素。因为查找的时间复杂度是 O(N)&#xff0c;且写入需要重新分配内存&#xff0c;所以它仅适用于小数据量的存储&#xff0c;而且它还存在 连锁更新 的风…...

MMKV(1)

内存准备 通过 mmap 内存映射文件&#xff0c;提供一段可供随时写入的内存块&#xff0c;App 只管往里面写数据&#xff0c;由操作系统负责将内存回写到文件&#xff0c;不必担心 crash 导致数据丢失。 数据组织 数据序列化方面选用 protobuf 协议&#xff0c;pb 在性能和空…...

centos 7.9 源码安装htop

1.下载源码 wget http://sourceforge.net/projects/htop/files/latest/download 2.上传到tmp目录&#xff0c;并解压 tar xvzf htop-1.0.2.tar.gz mv htop-1.0.2 /opt/ 进入到 cd /opt/htop-1.0.2/ 3.编译并安装 ./configure && make && make install 4.…...

Element UI之Button 按钮

Button 按钮 常用的操作按钮。 按需引入方式 如果是完整引入可跳过此步骤 import Vue from vue import { Button } from element-ui import element-ui/lib/theme-chalk/base.css import element-ui/lib/theme-chalk/button.css import element-ui/lib/theme-chalk/icon.cs…...

dig 简明教程

哈喽大家好&#xff0c;我是咸鱼 不知道大家在日常学习或者工作当中用 dig 命令多不多 dig 是 Domain Information Groper 的缩写&#xff0c;对于网络管理员和在域名系统(DNS)领域工作的小伙伴来说&#xff0c;它是一个非常常见且有用的工具。 无论是简单的 DNS 解析查找还…...

深度分析AMQP以及在rabbitMQ中的应用

文章目录 AMQP是什么AMQP在rabbitMQ中的应用AMQP协议的三层AMQP的三大组件AMQP的连接信道RabbitMQ 如何实现信道&#xff1a; AMQP是什么 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;是一种开放标准的消息队列协议。它提供了一个统一的、可靠的、异步的消…...

GB/T 28627-2023 抹灰石膏检测

抹灰石膏是指以半水石膏、Ⅱ型无水石膏单独或两者混合后作为主要胶凝材料&#xff0c;掺入集料和外加剂制成的用于建筑物室内墙面和顶棚基底抹灰找平用的石膏砂浆。 GB/T 28627-2023抹灰石膏检测项目&#xff1a; 测试项目 测试方法 凝结时间 GB/T 28627 保水率 GB/T 286…...

JDK版本和Gradle版本配套关系

Java versionSupport for compiling/testing/…​Support for running Gradle 8 N/A 2.0 9 N/A 4.3 10 N/A 4.7 11 N/A 5.0 12 N/A 5.4 13 N/A 6.0 14 N/A 6.3 15 6.7 6.7 16 7.0 7.0 17 7.3 7.3 18 7.5 7.5 19 7.6 7.6 20 8.1 8.3 21 …...

在Linux中,怎么查看自己电脑的系统架构是什么?

2023年10月18日&#xff0c;周三晚上 这些命令会返回一个字符串&#xff0c;表示系统的架构。 常见的架构包括 x86&#xff08;32位&#xff09;、x86_64&#xff08;64位&#xff09;、ARM 等。 方法1&#xff1a;使用uname命令 uname -m方法2&#xff1a;使用arch命令 ar…...

自5月以来,俄罗斯Sandworm黑客侵入了11家乌克兰电信公司

导语&#xff1a;据乌克兰计算机应急响应团队&#xff08;CERT-UA&#xff09;的最新报告称&#xff0c;自2023年5月至9月&#xff0c;俄罗斯政府支持的黑客组织Sandworm成功侵入了乌克兰的11家电信服务提供商。这一组织被认为与俄罗斯武装部队的GRU有关。 简介 根据乌克兰计算…...

怎样做好接口自动化测试?

今天介绍一下在接口自动化测试相关实践中总结到的一些经验。 接口自动化测试的目的 自动化测试的主要目的是用来回归测试的&#xff0c;当代码有变化时&#xff0c;有可能影响不应该变化的逻辑&#xff0c;这个时候为了确认这种情况&#xff0c;就需要进行回归测试。有时候回…...

Leetcode刷题详解——找到字符串中所有字母异位词

1. 题目链接&#xff1a;438. 找到字符串中所有字母异位词 2. 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括…...

Android 自定义view 圆形进度条

Android 自定义view 圆形进度条 前言一、码前分析二、开码1.画笔2.弧度3.圆弧的位置4.暴露给外部设置进度条的方法三、使用四、完整代码 总结 前言 先来看看效果&#xff0c;大概要实现这么一个圆形的进度条 一、码前分析 要实现这么一个进度条的效果&#xff0c;实际上是要画…...

混凝土基础的智能设计:VisualFoundation 12.0 Crack

实现混凝土基础的智能设计:工程师依靠 VisualFoundation:使用这个专注的工具可以更轻松、更强大地对基础进行建模。通用 FEA 工具&#xff08;如VisualAnalysis&#xff09;可以做很多事情&#xff0c;但对于特定于基础的工程来说&#xff0c;这更快、更智能。 草图边界 快速绘…...

C++中成员函数的重载覆盖与隐藏

1.重载与覆盖 重载&#xff1a;成员函数被重载的特征&#xff1a;在同一个类中&#xff0c;函数名相同&#xff0c;参数不同&#xff0c;vritual关键字可有可无。 覆盖&#xff1a;覆盖是指派生类函数覆盖基类函数&#xff0c;特征是&#xff1a;在有继承关系的类中&#xff0…...

电子器件系列49:CD4050B缓冲器

同相和反向缓冲器 还搞不懂缓冲电路&#xff1f;看这一文&#xff0c;工作原理作用电路设计使用方法 - 知乎 (zhihu.com) 缓冲器_百度百科 (baidu.com) 1、缓冲器的定义 缓冲器是数字元件的其中一种&#xff0c;它对输入值不执行任何运算&#xff0c;其输出值和输入值一样&…...

Leetcode 349 两个数组的交集 (哈希表)

Leetcode 349 两个数组的交集 &#xff08;哈希表&#xff09; 解法1 &#x1f60b;解法2 解法1 &#x1f60b; 自己的笨比方法:【哇这居然是标准解法之一&#xff0c;我不是笨比&#x1f60b;&#x1f60b;&#x1f60b;】 创建了两个hash数组&#xff0c;nums1出现一个就对应…...

基于YOLOv8模型的水下目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型的水下目标检测系统可用于日常生活中检测与定位鱼、水母、企鹅、海鹦、鲨鱼、海星、黄貂鱼&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统…...

vue-cli脚手架创建项目时报错Error: command failed: npm install --loglevel error

项目背景 环境&#xff1a;vue-cli 5.x 在工程文件中&#xff0c;后端模块wms已经创建完成&#xff0c;现在想新建一个名为vue-web的前端模块 执行命令vue create vue-web时&#xff0c; 报错Error: command failed: npm install --loglevel error 问题分析及解决 排查过程…...

c语言练习92:链表的中间结点

链表的中间结点 链表的结点为空时无法访问其next成员否则会报错 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/typedef struct ListNode ListNode; struct ListNode* middleNode(struct ListNode* head){if(h…...

开源音频格式转换终极指南:ncmdumpGUI实现数字音乐资产自由流转的完整方案

开源音频格式转换终极指南&#xff1a;ncmdumpGUI实现数字音乐资产自由流转的完整方案 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 在数字音乐时代&#xf…...

如何彻底解决Zotero-GPT集成中的AI调用故障:从诊断到优化的完整技术指南

如何彻底解决Zotero-GPT集成中的AI调用故障&#xff1a;从诊断到优化的完整技术指南 【免费下载链接】zotero-gpt GPT Meet Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-gpt Zotero-GPT项目作为文献管理工具与大型语言模型的深度集成方案&#xff0c;为…...

FastAPI安全防线:OAuth2 + JWT 实现无状态认证的完整流程

更多内容请见: 《Python Web项目集锦》 - 专栏介绍和目录 在现代Web应用开发中,安全认证是构建可靠API的基石。FastAPI通过其强大的安全组件,为开发者提供了实现安全、可扩展认证系统的工具。本文将深入剖析OAuth2与JWT在FastAPI中的整合实现,揭示无状态认证的完整流程,提…...

实时手机检测-通用部署指南:3步完成环境搭建与模型调用

实时手机检测-通用部署指南&#xff1a;3步完成环境搭建与模型调用 1. 环境准备与快速部署 1.1 系统要求 操作系统&#xff1a;Linux/Windows/macOS&#xff08;推荐Ubuntu 20.04&#xff09;Python版本&#xff1a;3.7-3.10GPU支持&#xff1a;NVIDIA显卡&#xff08;可选&…...

互联网产品创新:基于Qwen3-ASR-0.6B的在线教育实时字幕解决方案

互联网产品创新&#xff1a;基于Qwen3-ASR-0.6B的在线教育实时字幕解决方案 1. 引言 想象一下&#xff0c;你正在上一节重要的在线直播课&#xff0c;老师讲得飞快&#xff0c;有些专业术语没听清&#xff0c;或者因为网络波动声音断断续续。又或者&#xff0c;你身处一个嘈杂…...

零基础玩转OpenClaw:星图Qwen3-32B镜像的10个入门级自动化案例

零基础玩转OpenClaw&#xff1a;星图Qwen3-32B镜像的10个入门级自动化案例 1. 为什么选择OpenClawQwen3-32B组合&#xff1f; 去年冬天&#xff0c;当我第一次听说OpenClaw这个开源自动化框架时&#xff0c;内心是既兴奋又忐忑的。兴奋的是终于有一个能在本地电脑上实现AI自动…...

导师推荐 2026 最新!降AI率软件测评与好用工具推荐

2026年真正好用的AI论文降重与改写工具&#xff0c;核心看降重效果、去AI味、格式保留、学术适配四大指标。综合实测&#xff0c;千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队&#xff0c;覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 …...

OmenSuperHub:解锁惠普游戏本隐藏性能的开源控制方案

OmenSuperHub&#xff1a;解锁惠普游戏本隐藏性能的开源控制方案 【免费下载链接】OmenSuperHub 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否厌倦了官方Omen Gaming Hub的臃肿体验&#xff1f;想要一个纯净、高效的硬件控制工具来释放你的惠普游…...

哔哩哔哩API神器bilibili-api:Python开发者的终极爬虫工具指南

哔哩哔哩API神器bilibili-api&#xff1a;Python开发者的终极爬虫工具指南 【免费下载链接】bilibili-api 哔哩哔哩常用API调用。支持视频、番剧、用户、频道、音频等功能。原仓库地址&#xff1a;https://github.com/MoyuScript/bilibili-api 项目地址: https://gitcode.com…...

5大核心功能解析:MAA_Punish如何实现《战双帕弥什》全自动游戏体验

5大核心功能解析&#xff1a;MAA_Punish如何实现《战双帕弥什》全自动游戏体验 【免费下载链接】MAA_Punish 战双帕弥什每日任务自动化 | Assistant For Punishing Gray Raven 项目地址: https://gitcode.com/gh_mirrors/ma/MAA_Punish MAA_Punish是一款专为《战双帕弥什…...