摸透原理|一文带你了解 Redis 列表底层的实现方式

Linux环境变量与Shell变量:原理、读取、配置全解析 环境变量是Linux进程间传递配置信息的核心机制,本质为execve系统调用传递的char *envp[]内存块;Shell变量则仅存在于解释器进程栈中,需export才能升格为环境变量。其技术价值在于实现跨进程、跨会话、跨用户层级的运行时配置分发,支撑PATH路径解析、JAVA_HOME定位、ANDROID_HOME集成等关键场景。在终端调试、shell脚本编程、adb shell自动化、initramfs紧急恢复及国产Linux发行版(如统信UOS、麒麟)适配中,准确读取(printenv/env/de 阅读详情

上次我们分享 Redis 字符串的底层原理 ,今天我们再来看下 Redis List 列表的底层原理。

Redis List 命令

Redis List 列表支持的相关指令比较多,比如单个元素增加、删除操作,也支持多个元素范围操作。

Redis List 列表支持列表表头元素插入/弹出( LPUSH/LPOP ),也支持表尾元素插入/弹出( RPUSH/RPOP )。

另外 Redis List 列表还支持根据下标( LINDEX )获取元素,也支持根据根据下标覆盖相应的元素( LSET )。

除此之外,Redis List 列表还支持的范围操作,比如获取指定范围内全部元素( LRANGE ),移除指定范围内的全部元素( LTRIM )。

了解完的 Redis 相关指令,我们来看下 Redis List 列表底层实现方式,使用两种数据结构:

  • 压缩列表(ziplist)
  • 双向列表(linkedlist)

ps:本篇文章基于 Redis 3.2 开始进行讲解

双向列表(linkedlist)

上面我们知道了 List 列表支持表头/表尾元素的插入/弹出,这类操作使用链表那就非常高效,时间复杂度为 O(1)。

Redis 双向列表(linkedlist) 由两个结构构成:

  • list
  • listnode

结构如下:

list 结构体中保存了表头节点,表尾节点以及链表包含的节点的数量,正因为如此操作表头/表尾元素的插入/弹出,链表长度的计算将会非常高效,时间复杂度为 O(1) 。

listnode 结构体中除了保存节点的值以外,还会保存前后节点的指针,这样如果需要获取某个节点的前置节点与后置节点也会非常高效,时间复杂度为 O(1) 。

另外如果需要指定位置插入/删除元素,那么只需要变动当前位置节点前后指针即可,这个插入/删除操作复杂度为 O(1) 。

不过需要注意了,插入/删除动作前提我们需要找到这个指定位置,这个查找动作我们只能遍历链表,复杂度为 O(N) ,所以插入/删除的复杂度为 O(N) 。

双向列表(linkedlist)除了用作在列表键以外,还广泛用于发布/订阅,慢查询等内部操作。

既然双向列表(linkedlist)可以满足列表键的操作,那为什么 Redis 列表还采用其他的数据结构?

其实主要是因为内存占用问题,双向链表由于使用两个结构体,而这两个结构体都需要保存一些必要信息,这必然将会占用部分内存。

而当元素很少的时候,如果直接使用双向链表,内存还是比较浪费的。所以 Redis 引入压缩列表。

压缩列表

压缩列表是 Redis 为了节约内存而开发,它由一系列的特殊编码的的 连续内存块 组成的顺序型数据结构,整体结构如下:

从上面结构可以看出来,压缩列表实际上类似与我们使用的数组,数组中每一个元素保存一个数据。

不过与数组不同的是,压缩列表的表头存在三个字段

zlbytes
zltail
zllen

另外压缩列表的表尾还有一个字段, zlend 里面保存一个特殊的值, OXFE ,用于标记压缩列表的末端。

一个压缩列表可以由多个节点构成,每个节点可以保存整数值或字节数组,结构如下:

使用压缩列表,如果查找定位表头元素,我们只需要使用压缩列表起始地址加上表头三个字段长度就可以直接点位,查找非常快,复杂度是 O(1)。

而压缩列表的最后一个元素,查找起来也非常轻松,我们使用压缩列表起始地址加上 zltail 包含的长度就可以直接点位,查找也非常快,复杂度是 O(1)。

至于列表中的其他元素,就没有这么好运了,我们只能从第一个元素或者最后一个元素,遍历列表查找,此时的复杂度就是 O(N) 了。

另外压缩列表的新增、删除元素,都将会导致重新分配内存,效率不高,平均复杂度为 O(N),最坏福复杂度为 O(N^2)。

编码转换

当我们创建一个 Redis 列表键,如果同时满足以下两个条件,列表对象将会使用压缩列表作为底层数据结构

  • 列表对象保存的所有字符串元素的长度都小于 64 字节
  • 列表对象中保存的元素数量小于 512 个

如果不能同时满足这两个条件,那么默认将会使用双向列表作为底层数据结构。

小结

Redis 列表底层使用两种数据结构,压缩列表与双向链表。

压缩列表由于使用了连续内存块,内存占用少,并且内存利用率高,但是新增、删除由于涉及重新分配内存,效率不高。

双向列表呢,新增、删除元素非常方便,但是由于每个节点都是独立的内存快,内存占用比较高,且内存碎片化严重。

这两种数据结构在表头/表尾插入与删除元素,都十分高效。但是其他操作,可能就效率较低。

所以我们使用 Redis 列表,一定要因地制宜,可以将其当做 FIFO 队列,这样仅使用 POP/PUSH ,效率将会很高。

原文:www.tuicool.com/articles/N7nQ73r

参考资料

  1. Redis 设计与实现

推荐阅读

从事开发一年的程序员能拿到多少钱?

字节跳动总结的设计模式 PDF 火了,完整版开放下载

刷Github时发现了一本阿里大神的算法笔记!标星70.5K

程序员50W年薪的知识体系与成长路线。

关于【暴力递归算法】你所不知道的思路

开辟鸿蒙,谁做系统,聊聊华为微内核

 

看完三件事❤️

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。

关注公众号 『 Java斗帝 』,不定期分享原创知识。

同时可以期待后续文章ing🚀

 

Spring Boot四大核心组件深度解析:Starters、AutoConfigurator、CLI与Actuator Spring Boot并非黑盒魔法,其本质是一套基于约定与条件化装配的工程化框架。理解其底层机制,需从自动配置原理出发——通过条件注解(@ConditionalOnClass/Bean/Property)实现精准装配,依托Starter作为声明式契约统一依赖、配置与激活逻辑,再由AutoConfigurator按确定性顺序调度执行。这种设计赋予框架开箱即用的能力,同时保留完全可覆盖的控制权;CLI提供轻量级原生调试入口,支持Groovy动态实验与秒级热重载;Actuator则构建运行时数字孪生体,暴露env 阅读详情

相关推荐

R语言KNN机器学习入门:零数学门槛的实战指南

KNN(k近邻算法)是一种基于实例的监督学习方法,其核心原理是通过计算样本间距离实现相似性度量与类别决策。作为典型的懒惰学习算法,它无需训练阶段、全程透明可解释,特别适合缺乏统计基础的数据分析新手快速上手。在R语言生态中,KNN实现简洁高效,仅需class包一行knn()调用即可完成分类任务,配合caret包更可无缝集成标准化、交叉验证与模型评估。本文以Iris鸢尾花数据集为载体,系统讲解从数据探索、分层抽样、特征标准化到混淆矩阵诊断的完整流程,兼顾工程鲁棒性与教学友好性,是R初学者构建首个可复现机器学习模

weixin_30505225的博客 355

python---for循环中调用remove()

在for循环中调用remove()出现的问题 在对列表的for循环中,若对列表使用了remove()操作,会出现问题 第一种情况 nums = [1,2,0,4,0] for value in nums: print(value) if value == 0: nums.remove(value) print(nums) # 输出: 1 [1, 2, 0, ...

qq_41982466的博客 3314

从零搭建UE5像素流送信令服务器:Node.js实战与架构解析

在实时音视频通信领域,WebRTC是实现低延迟、点对点媒体传输的核心技术。其工作原理是通过SDP(会话描述协议)和ICE(交互式连接建立)协议,在两端之间协商并建立直接连接,从而高效传输音视频流。这项技术的价值在于,它使得在浏览器中实现高质量、低延迟的实时互动成为可能,广泛应用于云游戏、远程渲染、数字孪生和在线协作等场景。信令服务器在这一架构中扮演着“交通指挥中心”的关键角色,它本身不传输媒体流,而是负责在应用实例(如UE5引擎)与网页客户端之间,可靠地传递用于建立和管理WebRTC连接的**控制信令**,

weixin_30328063的博客 318

python中循环删除列表中元素时的坑!

循环删除列表中元素时千万别用正序遍历,一定要用反序遍历! 废话不多说,先上案例代码: def test(data): for i in data: data.remove(i) return data data = [1, 2, 3] print(test(data)) 面对以上代码,乍一看以为会打印出空列表,因为test...

weixin_30788239的博客 605

Tiktoken实战指南:OpenAI模型精准Token计数与生产优化

Token是大语言模型输入输出的基本计量单位,其计算逻辑直接决定API调用成败、成本控制精度与上下文截断可靠性。不同于传统NLP分词器,Tiktoken采用字节级BPE+UTF-8映射机制,实现与OpenAI后端完全一致的确定性编码,核心价值在于零误差计费、毫秒级截断和跨语言(含中文、emoji、代码)统一处理。它不服务于语义分析,而专为工程化部署设计——支撑prompt长度预估、缓存key生成、高并发中间件监控及真实成本归因。本文聚焦cl100k_base编码器在gpt-4/gpt-3.5-turbo等主

weixin_30443747的博客 382

关于Python列表元素的删除:for循环下的remove()

x = [1, 2, 1, 2, 1, 2, 1] for i in x: if i == 1: x.remove(i) print(x) 输出结果:[2, 2, 2] 对于上述代码,代码成功地删除了列表中的重复元素,执行结果是完全正确的 x = [1, 2, 1, 2, 1, 1, 1] for i in x: if i == 1: x.remove(i) print(x) 输出结果:[2, 2, 1] 同样的代码,仅仅是所处理的数据发生了一点变化

南京大学软件工程硕士在读 5285

Python的for循环和remove方法

for循环remove的bug

xlk_a1540775228的博客 415

具身智能的边缘计算核心构成方案

摘要: 具身智能(Embodied Intelligence)依赖物理实体与环境交互,而边缘计算(Edge Computing)通过本地化数据处理降低延迟、提升实时性。两者结合的核心方案包含五层架构:传感器层采集环境数据,边缘处理单元执行本地计算,通信模块实现低延迟传输,决策引擎运行轻量AI模型,执行器接口转化动作为物理操作。该方案以“边缘优先”为原则,满足毫秒级响应(如延迟<50ms),同时优化能效(功耗降低30%)和隐私保护。适用于机器人、自动驾驶等场景,通过分层闭环设计确保在资源受限环境中的可靠

老郑的博客 812

python for 循环中使用 remove 删除列表中的元素

python for 循环中使用 remove 删除列表中的元素 错误的代码 # !/usr/bin/python # encoding: utf-8 # -*- coding: utf8 -*- old_list = [1, 1, 2, 3, 4, 1, 5, 6, 1, 7, 8] for member in old_list: if member == 1: old_list.remove(member) print(old_list) 原因 原因是不能在for循环中用rem

weixin_44493841的博客 5245

SpotBugs使用

spotbugs命令行参数解析

javajingling的专栏 2947

在 dell precision 7920 tower CentOS 8 Stream 上安裝nvidia驱动程序、Anaconda

简单记录一下如何在实验室dell precision 7920 tower CentOS 8 Stream上安装nvidia显卡驱动。

chen9046的博客 995

redis知识整理

前言 日常开发中经常使用redis,但每次项目基本只配置过一次,或者复制粘贴,对于从零搭建redis,其中的原理流程模糊不清,所以在这里做个梳理,日后回顾也很方便。 Redis的官网打开比较慢,而且全英文对英文不好的同学看起来不方便,这块推荐去redis中文网查看官方文档,官网地址:http://www.redis.cn/。 其实大部分内容官网都介绍的很清楚了,在这里只是对知识做一个梳理,方...

安迪爸爸 992

C#里使用NModbus来创建一个TCP从站服务

摘要:本文介绍了一个用C#实现的Modbus TCP从站服务器,基于.NET Framework 4.6.1开发。代码使用NModbus库创建TcpListener和ModbusSlaveNetwork,支持设置IP地址、端口号和从站ID。服务器实现了数据存储初始化功能(包括线圈和保持寄存器),并提供了启动/停止操作的UI界面和日志记录功能。该解决方案适用于需要调试Modbus TCP协议的场景,特别适合无法升级到更高版本.NET Framework的环境。

大坡3D软件开发 478

Redis高频面试题:从入门到源码的降维打击指南(2024火力全开版)

Redis6.0开始搞了多线程IO(只是网络IO部分哦),执行命令还是单线程——这波操作既保住了线程安全,又把网络吞吐量提升了3倍+!记住,Redis玩得6,Offer拿到手软!遇到不会的问题,就把面试官往你熟悉的领域带(比如多说说你处理过的大规模缓存架构实战)~当AOF文件过大时,重写过程可能导致内存暴涨(原AOF+新AOF同时存在),记得监控。在zset实现中,跳表平均查询效率O(logN),且范围查询吊打红黑树!预分配+惰性释放,O(1)时间复杂度获取长度!命令检测,记得拆分成多个小Key!

xiaoningaijishu的博客 770

PX4从放弃到精通(二十一):使用git管理PX4代码

文章目录前言一、设置git密钥二、将代码上传至gitee 前言 Ubuntu 18.04 PX4 1.11.3 由于github有时网速较慢,本文使用gitee。 一、设置git密钥 ssh-keygen -t rsa -C “your_email@youremail.com” your_email@youremail.com为自己注册的gitee账户邮箱.设置路径与密码时,也直接回车不设置,如下图,密钥生成的位置在红框处. 在密钥目录下按Ctrl+H显示隐藏文件,进入.ssh文件夹用gedit打开id

超维空间科技的博客 3478

2025华为od机试真题B卷【版本管理】JavaScript实现

在 软件版本管理中,版本号由点分割的数字组成,例如 1.2.3 和 2.8。现在,你需要编写一个函数,计算两个版本号之间的可用版本号个数。这里的可用版本号指的是所有满足 version1<x<version2的版本号x的个数。若 version1 >=version2 返回0.,

MISAYAONE的博客 254

Python开发者必学的Redis实战指南:从连接池到分布式锁

Redis 是一种高性能内存键值数据库,其核心原理在于基于内存的快速读写、单线程事件循环与多数据结构支持。技术价值体现在低延迟缓存、高并发协调与轻量级消息中间件能力,广泛应用于 Web 会话管理、秒杀库存控制、实时排行榜及延迟任务调度等典型场景。对 Python 开发者而言,掌握 redis-py 客户端的连接池配置、原子操作(如 SETNX/PX)、错误防御机制及生产环境 TLS/ACL 安全实践,是构建稳定服务的关键门槛。本文聚焦真实工程问题驱动的学习路径,覆盖验证码防刷、分布式锁实现、ZSET 排行榜

weixin_34380948的博客 284

点到面点云配准(Point To Plane)算法知识详解和详细推导,C++代码实现

点到面 ICP (Iterative Closest Point) 是在 3D 点云配准中常见的一种变体,通过最小化点到对应面(由法向量定义的局部平面)的距离来提高收敛速度和精度。

qq_36812406的博客 1810

Redis集群环境下高效模糊查询:RedisTemplate与Scan命令的完美结合

本文深入探讨了在Redis集群环境下如何安全高效地实现模糊查询。针对生产环境严禁使用阻塞式KEYS命令的问题,详细解析了非阻塞的Scan命令原理及其在集群中的局限性。核心解决方案是通过RedisTemplate结合Scan命令,并遍历所有集群主节点来获取完整结果。文章提供了完整的Java代码实战示例,涵盖单机与集群模式下的关键实现、序列化避坑、游标管理及性能优化建议,为开发者处理海量Key的模糊匹配需求提供了专业指导。

t4y5u6i7o的博客 433

手搓UDS Bootloader|全网独家复现0x10诊断会话控制、详解会话跳转规则与S3超时机制、助力ECU在线刷写、固件迭代、车规安全升级落地

在车载UDS诊断(ISO 14229)与Bootloader固件升级架构中,0x10诊断会话控制服务是所有高级诊断、固件刷写功能的前置核心与权限管控入口,属于UDS基础必实现服务。车载ECU通过分级会话模式,隔离常规故障诊断、高级标定、固件重编程等高、低权限操作,从协议层面保障车载电控系统的安全性与稳定性。多数嵌入式开发者开发UDS Bootloader时,仅简单实现会话切换报文应答,未吃透会话强制跳转规则、S3安全超时机制、会话权限绑定、APP在线刷写跳转逻辑。

getusushu的博客 465

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

手搓AI Agent:从ReAct原理到可运行的最小闭环系统

AI Agent不是高级提示词工程,而是具备感知、推理、行动与反馈能力的智能体系统。其核心原理源于ReAct范式——将大模型的思维过程(Reasoning)与工具调用行为(Acting)解耦并结构化。这种设计赋予系统任务分解、失败回退、状态追踪等关键工程能力,显著提升复杂业务场景下的鲁棒性与可解释性。在智能客服、自动化运营、跨系统调度等真实应用中,一个能稳定执行多跳指令、支持上下文记忆并具备熔断机制的Agent,远比‘跑通demo’的封装器更具技术价值与落地潜力。本文聚焦手搓级实践,深入拆解ReAct三层架

weixin_30819085的博客 503

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

JMeter跨线程组传参:全局变量设置与性能测试实战

在性能测试领域,模拟真实用户行为往往涉及多个连续操作,例如登录、浏览、下单等。这些操作通常需要在不同的线程组中执行,但JMeter默认的变量作用域是线程隔离的,这导致了跨线程数据传递的难题。理解JMeter的变量作用域原理是解决这一问题的关键。通过引入全局属性(Properties)机制,可以实现数据的全局共享,其技术价值在于能够构建出结构清晰、高度仿真且易于维护的复杂业务流测试脚本。这在电商、金融等需要多步骤事务验证的应用场景中尤为重要。本文将以JMeter性能测试为核心,详细解析如何利用__setPro

congdi7904的博客 413

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Windows命令注入实战:从Ping到反弹Shell的RCE利用与防御

命令注入漏洞是Web安全中常见的高危风险,其本质在于用户输入被误执行为系统命令,打破了数据与代码的边界。攻击者通过利用操作系统Shell的语法特性,将恶意指令与原有命令进行拼接,从而绕过限制执行任意代码。在Windows环境下,cmd.exe的命令连接符(如&&、&、|等)成为实现这一目标的关键。掌握命令拼接技术不仅能提升渗透测试中的系统控制能力,更能深刻理解安全编码的重要性。本文以Pikachu靶场为实验环境,深入剖析Windows RCE漏洞的利用链,涵盖从基础信息收集到文件操作、目录遍历,最终实现反弹

www.itmmd.com 384

渗透测试学习路线:从零基础到实战精通的完整指南

网络安全的核心在于主动发现并修复系统漏洞,渗透测试正是实现这一目标的关键技术。其原理是通过模拟攻击者行为,对网络、系统及应用进行安全性评估,从而识别潜在风险。掌握渗透测试技术,不仅能有效提升企业安全防御能力,也是安全工程师的核心价值所在。在实际应用中,渗透测试广泛应用于金融、互联网、政府等关键行业的等保测评、红蓝对抗及安全审计场景。本文基于渗透测试和网络安全等热词,系统梳理了从网络协议、操作系统基础到工具使用、靶场实战的完整学习路径,并深入探讨了内网渗透、移动安全等进阶领域,为初学者构建清晰、可执行的能力成

weixin_30482383的博客 1148

大二小白吃透向量数据库:从0到1实战教程(代码可直接跑,附避坑指南)

向量数据库的核心逻辑就“存向量、找相似”,比我们学过的MySQL简单多了。这篇教程的代码,我全部亲测可运行,没有任何多余的复杂逻辑,小白跟着复制就能跑通,还能理解背后的原理。学会向量数据库,不仅能搞定RAG项目,还能做推荐系统、相似检索等实战项目,不管是课程作业还是毕设,都是加分项。如果在运行代码时遇到报错、不理解某个参数,或者想拓展更复杂的功能,欢迎在评论区交流,我会尽量回复,咱们一起从小白变大佬!觉得有用的话,欢迎。

density666的博客 538

Python位运算实战:用整数掩码构建高性能权限系统

位运算不是二进制教学的冷知识,而是Python底层性能优化的核心能力。它基于CPU原生指令实现纳秒级操作,通过单个整数高效编码32+布尔状态,在内存占用、执行速度和线程安全性上远超列表或字典方案。其技术价值体现在缓存行友好、零开销原子操作与无锁并发控制,广泛应用于API网关权限校验、IoT设备配置、Redis内核绑定及PyTorch张量对齐等关键场景。本文聚焦位掩码(bitmask)这一核心模式,结合`&`权限校验、`|`原子授权、`^`状态翻转等真实工程实践,带你落地一个生产级轻量权限控制系统。

weixin_30832143的博客 415
上一篇: 华为大佬整理的“百万级”MySQL笔记,带你直追一线大厂程序员的水平
下一篇: 万字详解 阿里面试真题:请你说说索引的原理
Java斗帝之路
博客等级 码龄7年 2392粉丝 687原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值