6、Redis系统-数据结构-07-QuickList

news/2024/10/6 17:53:12/

七、快速列表(QuickList)

快速列表(QuickList)是 Redis 中用于实现列表(List)类型的一种高效数据结构。它结合了双向链表和压缩列表的优点,既支持高效的顺序访问,又能有效节省内存。

1. 结构设计

快速列表的基本思想是将多个压缩列表(ziplist)节点连接成一个双向链表。每个快速列表节点包含一个压缩列表,快速列表节点通过双向链表连接在一起。这样,快速列表既能利用压缩列表的内存紧凑性,又能利用链表的高效插入和删除操作。

typedef struct quicklist {quicklistNode *head;      // 快速列表头节点quicklistNode *tail;      // 快速列表尾节点unsigned long count;      // 快速列表中的元素总数量unsigned long len;        // 快速列表中的节点数量int fill : QL_FILL_BITS;  // 节点的填充因子unsigned int compress : QL_COMP_BITS;  // 压缩深度quicklistBookmark bookmarks[];  // 书签,用于快速定位
} quicklist;
快速列表的结构
  1. 快速列表(quicklist):快速列表结构包含指向头节点和尾节点的指针、元素总数量、节点数量、节点填充因子和压缩深度等。
  2. 快速列表节点(quicklistNode):每个节点包含前后指针、压缩列表指针、压缩列表大小、节点中元素数量等。
typedef struct quicklistNode {struct quicklistNode *prev;   // 前一个节点struct quicklistNode *next;   // 后一个节点unsigned char *zl;            // 压缩列表指针unsigned int sz;              // 压缩列表大小unsigned int count : 16;      // 节点中元素数量unsigned int encoding : 2;    // 编码类型unsigned int container : 2;   // 容器类型unsigned int recompress : 1;  // 重新压缩标志unsigned int attempted_compress : 1;  // 尝试压缩标志unsigned int extra : 10;      // 额外空间
} quicklistNode;
节点的设计
  • prev 和 next:分别指向前一个节点和后一个节点,实现双向链表结构。
  • zl:指向实际存储数据的压缩列表。
  • sz:压缩列表的大小。
  • count:节点中包含的元素数量。
2. 快速列表的优点
  1. 内存紧凑:快速列表通过使用压缩列表来存储数据,减少了内存碎片,提高了内存利用率。
  2. 高效操作:快速列表支持在列表两端进行高效的插入和删除操作,适用于需要频繁操作的场景。
  3. 灵活性:通过双向链表结构,快速列表可以在需要时扩展或压缩,适应不同大小的数据集。
3. 操作原理
插入操作

插入新元素时,首先找到合适的节点(通常是头节点或尾节点),然后将新元素插入到节点的压缩列表中。如果当前节点已满,则创建一个新的节点,并将元素插入到新节点中。这样可以保证插入操作的高效性。

  • 在头部插入:新元素插入到头节点的压缩列表中,如果头节点满了,则创建一个新的头节点。
  • 在尾部插入:新元素插入到尾节点的压缩列表中,如果尾节点满了,则创建一个新的尾节点。
删除操作

删除元素时,首先找到包含该元素的节点,然后在压缩列表中删除元素。如果节点变为空节点,则将节点从快速列表中移除。这样可以保证删除操作的高效性。

  • 删除头部元素:从头节点的压缩列表中删除元素,如果头节点空了,则移除头节点。
  • 删除尾部元素:从尾节点的压缩列表中删除元素,如果尾节点空了,则移除尾节点。
查找操作

查找元素时,通过遍历快速列表节点,查找包含目标元素的压缩列表,然后在压缩列表中查找目标元素。这样可以保证查找操作的高效性。

  • 顺序查找:从头节点开始,依次遍历每个节点的压缩列表,直到找到目标元素。
  • 逆序查找:从尾节点开始,依次遍历每个节点的压缩列表,直到找到目标元素。
4. 快速列表的优化策略
压缩和填充因子

快速列表的填充因子用于控制每个压缩列表节点的大小。合理设置填充因子可以平衡内存利用率和操作性能。填充因子越大,每个节点包含的元素越多,内存利用率越高,但插入和删除操作的性能可能会下降;填充因子越小,每个节点包含的元素越少,插入和删除操作的性能越高,但内存利用率可能会下降。

压缩深度

快速列表的压缩深度用于控制数据压缩的程度。合理设置压缩深度可以进一步节省内存。压缩深度越大,压缩列表节点之间的数据压缩程度越高,内存利用率越高,但解压缩操作的开销可能会增加;压缩深度越小,压缩列表节点之间的数据压缩程度越低,解压缩操作的开销较小,但内存利用率可能会下降。

5. 使用示例

以下是一些使用 Redis 快速列表的示例,展示了如何利用快速列表进行数据的存储和操作。

插入数据

LPUSH mylist "hello"
LPUSH mylist "world"
RPUSH mylist "foo"
RPUSH mylist "bar"

获取数据

LRANGE mylist 0 -1
# 1) "world"
# 2) "hello"
# 3) "foo"
# 4) "bar"

删除数据

LPOP mylist
# "world"RPOP mylist
# "bar"LRANGE mylist 0 -1
# 1) "hello"
# 2) "foo"
结论

通过上述解析,我们可以更好地理解快速列表的设计思想和实现原理,从而在实际开发中更好地利用快速列表提供的优势。在 Redis 中,快速列表通过结合双向链表和压缩列表的优点,实现了高效的存储和操作,适用于需要频繁插入、删除和查找的场景。了解快速列表的内部实现,可以帮助我们在实际应用中更好地利用 Redis 的性能和功能。


http://www.ppmy.cn/news/1474000.html

相关文章

Spring Boot 创建定时任务

在现代应用程序开发中,定时任务是一个常见的需求。Spring Boot作为一个强大的框架,提供了简单易用的定时任务调度功能。本文将详细介绍如何在Spring Boot中创建和管理定时任务,并提供完整的代码示例。 1. 什么是定时任务 定时任务是指在预定…

C#的多线程UI窗体控件显示方案

在C#中,特别是在使用Windows窗体(WinForms)或WPF(Windows Presentation Foundation)进行UI开发时,处理多线程与UI控件的交互需要特别小心。由于UI控件不是线程安全的,直接从非UI线程&#xff08…

WebKit简介及工作流程

WebKit是一个开源的浏览器网页排版引擎,起源于苹果公司,最初是为了开发Safari浏览器而创建的。它以其跨平台支持、可扩展性和定制化、安全性与隐私保护、可访问性和国际化等特点,在现代Web浏览器的发展中起到了关键的作用。WebKit的主要组件包…

HUAWEI MPLS 静态配置和动态LDP配置

MPLS(Multi-Protocol Label Switching,多协议标签交换技术)技术的出现,极大地推动了互联网的发展和应用。例如:利用MPLS技术,可以有效而灵活地部署VPN(Virtual Private Network,虚拟专用网),TE(Traffic Eng…

解码AWS EC2:塑造云服务器新标杆的五大核心优势

在云计算领域,亚马逊弹性计算云(Amazon Elastic Compute Cloud, 简称EC2)作为AWS的明星服务,凭借其卓越的性能、灵活性和广泛的生态系统,已经成为企业构建云上基础设施的首选。EC2不仅仅是一个简单的云服务器租用服务&…

【鸿蒙学习笔记】MVVM模式

官方文档:MVVM模式 [Q&A] 什么是MVVM ArkUI采取MVVM Model View ViewModel模式。 Model层:存储数据和相关逻辑的模型。View层:在ArkUI中通常是Component装饰组件渲染的UI。ViewModel层:在ArkUI中,ViewModel是…

swiftui中封装一个carditem视图,结合toolbar实现滚动的瀑布流,仿小红书首页

实现的效果如上图所示,支持左右滑动切换页面,也支持点击顶部的toolbar菜单切换页面,每个页面里面的每一项都是一个carditem.swift,这是我封装的一个card组件,用于展示每一个card内容,carditem.swift内容如下…

React+TS前台项目实战(二十五)-- 全局常用排序组件SortButton封装

文章目录 前言SortButton组件1. 功能分析2. 代码详细注释3. 使用到的全局hook代码4. 使用方式5. 效果展示 总结 前言 今天要封装的SortButton 组件,主要用在表格列排序上,运用于更新路由并跳转更新,起到刷新页面仍然处于当前排序数据。 Sor…