【Redis】深入探索 Redis 的数据类型 —— 列表 List

文章目录

  • 一、List 类型介绍
  • 二、List 类型相关命令
    • 2.1 LPUSH 和 RPUSH、LPUSHX 和 RPUSHX
    • 2.2 LPOP 和 RPOP、BLPOP 和 BRPOP
    • 2.3 LRANGE、LINDEX、LINSERT、LLEN
    • 2.4 列表相关命令总结
  • 三、List 类型内部编码
    • 3.1 压缩列表(ziplist)
    • 3.2 链表(linkedlist)
  • 四、List 类型的应用场景
    • 4.1 消息队列
    • 4.2 微博列表


一、List 类型介绍

list 列表类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储 2^32 - 1 个元素。在 Redis 中,可以对列表两端插人(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是⼀种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。

列表两端插入和弹出操作:

列表的获取、删除等操作:

列表类型的特点:

  • 列表中的元素是有序的,这意味着可以通过索引下标获取某个元素或者某个范围的元素列表;
  • 区分获取和删除的区别,例上图 中的 lrem 1 b 是从列表中把从左数遇到的前 1 个 b 元素删除,这个操作会导致列表的长度从 5 变成 4;但是执行 lindex 4 只会获取元素,但列表长度不会变化。
  • 列表中的元素是允许重复的,例如下图中的列表中是包含了两个 a 元素的。

二、List 类型相关命令

2.1 LPUSH 和 RPUSH、LPUSHX 和 RPUSHX

  1. LPUSHRPUSH

LPUSH 命令的作用是将一个或多个元素从左侧(头插)插入到 list 中;而 RPUSH 命令的作用则是将一个或多个元素从右侧(尾插)插入到 list 中。

语法:

LPUSH key element [element ...]RPUSH key element [element ...]
  1. LPUSHXRPUSHX

LPUSHX 命令的作用是当 key 存在时,将⼀个或者多个元素从左侧放⼊(头插)到 list 中,不存在则直接返回;而 RPUSHX 命令的作用是是当 key 存在时,将⼀个或者多个元素从右侧放⼊(头插)到 list 中,不存在则直接返回。

语法:

LPUSHX key element [element ...]RPUSHX key element [element ...]

2.2 LPOP 和 RPOP、BLPOP 和 BRPOP

  1. LPOPRPOP

LPOP 命令的作用是从左侧删除一个元素(头删),并返回删除的值;而 RPOP 则是从右侧删除(尾删),然后返回删除的值。

语法:

LPOP keyRPOP key
  1. BLPOPBRPOP

BLPOPBRPOP 命令的作用和LPOPRPOP 一样,只是需要指定一个超时时间,如果没有元素可以删除的时候,会进行阻塞,如果在设定的超时时间内向 Redis 中插入元素,则会立即执行;否则超时则之间退出。

语法:

BLPOP key [key ...] timeoutBRPOP key [key ...] timeout

另外,BLPOPBRPOP 可以同时指定多个 key 进行删除。

2.3 LRANGE、LINDEX、LINSERT、LLEN

  1. LRANGE
    LRANGE命令的作用是获取从 start 到 stop 区间的所有元素,区间左闭右闭,并且指定的位置可以是负数,表示倒数第几个。

语法:

LRANGE key start stop
  1. LINDEX

LINDEX 命令的作用是获取从左边开始第 index 位置的元素。

语法:

LINDEX key index
  1. LINSERT

LINSERT 命令的作用是在特定的位置插入元素。

语法:

LINSERT key BEFORE|AFTER pivot element

说明:

  • BEFORE 表示插入到 pivot 元素之前;
  • AFTER 表示插入到 pivot 元素之后。
  1. LLEN

LLEN 命令的作用是 获取 list 长度。

语法:

LLEN key

2.4 列表相关命令总结

以下是关于 Redis List 相关命令的总结,包括命令、作用以及时间复杂度:

命令作用时间复杂度
LPUSH从列表左侧插入一个或多个元素O(N) (N 为插入元素数量)
RPUSH从列表右侧插入一个或多个元素O(N) (N 为插入元素数量)
LPUSHX如果列表存在,从左侧插入一个或多个元素,否则不执行操作O(1)
RPUSHX如果列表存在,从右侧插入一个或多个元素,否则不执行操作O(1)
LPOP从列表左侧删除并返回一个元素O(1)
RPOP从列表右侧删除并返回一个元素O(1)
BLPOP从左侧删除并返回元素,如果列表为空则阻塞,带有超时参数O(1) 或阻塞等待
BRPOP从右侧删除并返回元素,如果列表为空则阻塞,带有超时参数O(1) 或阻塞等待
LRANGE获取指定范围内的元素列表O(Slice Size)
LINDEX获取指定位置的元素O(N) (N 为索引位置)
LINSERT在指定元素前或后插入新元素O(N) (N 为列表长度)
LLEN获取列表的长度O(1)

注意:时间复杂度中的 “N” 表示操作的复杂度与列表的长度或插入元素的数量成线性关系,而不是固定的常数时间。在实际使用中,需要根据数据规模和性能要求选择适当的命令。

三、List 类型内部编码

Redis 中的 List 数据类型在内部可以使用不同的编码方式来存储数据,具体的编码方式取决于列表的大小和元素的大小。下面将介绍两种常见的 List 内部编码方式:

3.1 压缩列表(ziplist)

压缩列表(ziplist)是 Redis 中一种紧凑的、内存优化的列表编码方式,适用于存储较小的列表,或者列表中的元素都是较小的整数或字符串。压缩列表以连续的内存块的形式存储数据,每个节点可以包含一个或多个元素,这使得压缩列表在内存使用效率上有一定优势。

特点:

  • 压缩列表可以保存多个元素在一个节点中,因此在元素较小的情况下,它可以节省内存。
  • 压缩列表支持快速的元素访问,因为可以通过索引直接访问元素。
  • 压缩列表适用于列表较小且元素较小的情况。

3.2 链表(linkedlist)

链表(linkedlist)是 Redis 中另一种列表的内部编码方式,它更适合存储大型列表或者元素大小不一致的列表。链表中的每个节点包含一个元素以及指向前一个节点和后一个节点的指针,这种结构使得链表在插入和删除元素时具有较高的效率。

特点:

  • 链表适用于列表较大或元素较大的情况,因为它不需要连续的内存块,可以更好地处理大型数据。
  • 链表对于插入和删除元素的操作更加高效,因为只需要调整节点的指针而不需要移动大量数据。
  • 链表相对于压缩列表占用更多的内存,因为需要额外的指针来维护节点之间的链接。

总之,Redis 根据列表的大小和元素的大小自动选择使用压缩列表或链表来进行编码,以平衡内存使用和操作效率。在选择数据结构和命令时,需要考虑数据的规模和操作的性能需求。

示例:

1)当元素个数较少且没有大元素时,内部编码为 ziplist:

127.0.0.1:6379> rpush listkey e1 e2 e3
OK
127.0.0.1:6379> object encoding listkey
"ziplist"

2)当元素个数超过 512 时,内部编码为 linkedlist:

127.0.0.1:6379> rpush listkey e1 e2 e3 ... 省略 e512 e513
OK
127.0.0.1:6379> object encoding listkey
"linkedlist"

3)当某个元素的长度超过 64 字节时,内部编码为 linkedlist:

127.0.0.1:6379> rpush listkey "one string is bigger than 64 bytes ... 省略 ..."
OK
127.0.0.1:6379> object encoding listkey
"linkedlist"

四、List 类型的应用场景

4.1 消息队列

Redis 可以使用 lpush + brpop 命令组合实现经典的阻塞式生产者-消费者模型队列,生产者客户端使用 lpush 从列表左侧插入元素,多个消费者客户端使用 brpop命令阻塞式地从队列中 “争抢” 队首元素。通过多个客户端来保证消费的负载均衡和高可用性。

Redis 阻塞消息队列模型:


分频道的消息队列:

Redis 可以同样使用 lpush + brpop 命令,但通过不同的键模拟频道的概念,不同的消费者可以通过 brpop 不同的键值,实现订阅不同频道的理念。

4.2 微博列表

每个用户都有属于自己的微博列表 ,现需要分页展示文章列表。此时可以考虑使用列表类型,因为列表不但是有序的,同时支持按照索引范围获取元素。

1)每篇微博使用哈希结构存储,例如微博中 3 个属性:title、timestamp、content:

hmset mblog:1 title xx timestamp 1476536196 content xxxxx
...
hmset mblog:n title xx timestamp 1476536196 content xxxxx

2)向用户 的微博列表中添加微博,使用 user:<uid>:mblogs 作为微博的键:

lpush user:1:mblogs mblog:1 mblog:3
...
lpush user:k:mblogs mblog:9

3)分页获取用户的微博列表,例如获取用户1 的前 10 篇微博:

keylist = lrange user:1:mblogs 0 9
for key in keylist {hgetall key
}

此外,此方案在实际中可能存在两个问题:

  1. 1 + n 问题。即如果每次分页获取的微博个数较多,需要执行多次 hgetall 操作,此时可以考虑使用 pipeline(流水线)模式批量提交命令,或者微博不采用哈希类型,而是使用序列化的字符串类型,使用 mget 获取。
  2. 分页获取文章时,lrange 在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/78962.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《向量数据库指南》——Milvus Cloud云原生分布式向量数据库的优势有哪些?

首先解释一下什么是分布式,什么是云原生。分布式的概念相对容易理解,就是系统的各个组件在不同的节点上进行协作和分工,以实现更大规模和更高性能的处理。而云原生并不仅仅指运行在 Kubernetes(K8s)上或在公有云上的服务。在我的理解中,分布式云原生意味着系统首先是一个…

【Java 基础篇】Java可变参数:灵活处理不定数量的方法参数

在Java编程中&#xff0c;可变参数是一项强大的功能&#xff0c;它允许你编写更加灵活的方法&#xff0c;接受不定数量的参数。本文将详细解释Java可变参数的用法、语法以及最佳实践。 什么是可变参数&#xff1f; 可变参数是Java 5引入的一项功能&#xff0c;它允许你在方法…

汇总selenium利用xpath等找网页节点的方法

一、通过子节点定位父节点&#xff0c;模拟建立一个test.html <!--子节点定位父节点--> <html> <body> <div id"A"><div>定位到这里1<div>定位到这里2<div>定位到这里3<div id"C">子节点</div><…

贝叶斯分位数回归、lasso和自适应lasso贝叶斯分位数回归分析免疫球蛋白、前列腺癌数据...

原文链接&#xff1a;http://tecdat.cn/?p22702 贝叶斯回归分位数在最近的文献中受到广泛关注&#xff0c;本文实现了贝叶斯系数估计和回归分位数&#xff08;RQ&#xff09;中的变量选择&#xff0c;带有lasso和自适应lasso惩罚的贝叶斯&#xff08;点击文末“阅读原文”获取…

vue基础知识十:Vue中组件和插件有什么区别?

一、组件是什么 回顾以前对组件的定义&#xff1a; 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式&#xff0c;在Vue中每一个.vue文件都可以视为一个组件 组件的优势 降低整个系统的耦合度&#xff0c;在保持接口不…

【洛谷 P1364】医院设置 题解(图论+深度优先搜索)

医院设置 题目描述 设有一棵二叉树&#xff0c;如图&#xff1a; 其中&#xff0c;圈中的数字表示结点中居民的人口。圈边上数字表示结点编号&#xff0c;现在要求在某个结点上建立一个医院&#xff0c;使所有居民所走的路程之和为最小&#xff0c;同时约定&#xff0c;相邻接…

C#,数值计算——64位哈希表的计算方法与实现代码

1 文本格式 using System; namespace Legalsoft.Truffer { public class HashAll { public HashAll() { } /// <summary> /// Pseudo-DES hashing of the 64-bit word(lword, rword). Both 32-bit arguments /// are …

GDB之调试系统接口syscall(九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

JavaScript 知识扫盲

JavaScript 知识扫盲 写在前面一、JavaScript 写入形式二、常用输入输出三、JS 是动态类型语言四、运算符五、数组1、数组创建2、获取和修改数组元素3、新增元素4、删除元素 六、函数七、对象1、对象的创建2、属性方法的使用 八、JavaScript 和 Java 对比九、事件1、常见事件2、…

Kubernetes(k8s)上搭建nacos集群

Kubernetes上搭建nacos集群 环境准备Kubernetes准备数据库准备 部署nacos集群官方镜像地址创建configmap创建部署文件根据yaml资源清单文件部署nacos 环境准备 Kubernetes准备 你需要准备一个Kubernetes集群&#xff0c;如图我的集群已经准备完毕&#xff1a; 数据库准备 …

【蓝桥杯选拔赛真题60】Scratch旋转风车 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析

目录 scratch旋转风车 一、题目要求 编程实现 二、案例分析 1、角色分析

【脑机接口论文与代码】 基于自适应FBCCA的脑机接口控制机械臂

Brain-Controlled Robotic Arm Based on Adaptive FBCCA 基于自适应FBCCA的脑机接口控制机械臂论文下载&#xff1a;算法程序下载&#xff1a;摘要1 项目介绍2 方法2.1CCA算法2.2FBCCA 算法2.3自适应FBCCA算法 3数据获取4结果4.1脑地形图4.2频谱图4.3准确率 5结论 基于自适应FB…

Spring底层的核心原理解析

这篇文章大致讲解一下spring的整个执行流程&#xff0c;也就是在我们脑子里面建立一个笼统的概念 spring如何创建一个容器呢 容器里面是对象 上面就是利用AnnotationConfigApplicationContext这个对象&#xff0c;然后传入了一个配置类的字节码对象给我们创建一个Spring容器&am…

Hyper-V 安装 CentOS (二)

总目录 https://preparedata.blog.csdn.net/article/details/132877836 文章目录 总目录一、Hyper-V 创建centos的虚拟机实例二、虚拟机安装Centos ISO镜像三、重启后&#xff0c;进入系统 一、Hyper-V 创建centos的虚拟机实例 网络连接先不选择&#xff0c;后面文章专门配置网…

【软考】系统架构设计师 - 知识扩展 - “区块链技术“

目录 一 简介&#x1f451; 1 比特币❤️ 2 区块链的特点❤️ 3 共识算法❤️ 二 练习题&#x1f451; 三 扩展&#x1f451; 1 哈希算法❤️ 2 哈希指针❤️ 3 UTXO❤️ 4 参考资料❤️ 一 简介&#x1f451; 1 比特币❤️ 比特币底层采用了区块链技术。 比特币交易…

03目标检测-传统方法与深度学习算法对比

目录 一、目标学习的检测方法变迁及对比 二、深度学习目标检测算法基本流程 三、传统目标检测算法VS深度学习目标检测算法 一、目标学习的检测方法变迁及对比 “目标检测“是当前计算机视觉和机器学习领域的研究热点。从Viola-Jones Detector、DPM等冷兵器时代的智…

【数据结构】二叉树的链式结构

【数据结构】二叉树的链式存储结构 二叉树的存储结构 typedef int BTDataType; // 二叉树的结构 typedef struct BinaryTreeNode {BTDataType data; // 树的值struct BinaryTreeNode *left; // 左孩子struct BinaryTreeNode *right;// 右孩子 } BinaryTreeNode;二…

EXCEL如何把一个单元格内的文本和数字分开?例如:龚龚15565 = 龚龚 15565

使用工具&#xff1a;WPS 举例&#xff1a; EXCEL如何把一个单元格内的文本和数字批量分开&#xff1f;不使用数据分列。 第一步、将第二行数据冻结 第二步、在B1、C1单元格输入需要分开的示例 第三步、点击选中B1单元格&#xff0c;输入快捷键【CTRLE】进行填充。B2单元格也是…

【AIGC】图片生成的原理与应用

前言 近两年 AI 发展非常迅速&#xff0c;其中的 AI 绘画也越来越火爆&#xff0c;AI 绘画在很多应用领域有巨大的潜力&#xff0c;AI 甚至能模仿各种著名艺术家的风格进行绘画。 目前比较有名商业化的 AI 绘画软件有 Midjourney、DALLE2、以及百度出品的文心一格&#xff1a;…

MinGW-W64 下载、安装与配置(支持最新版的GCC,目前 GCC 13.2.0)VSCode配置c/c++环境 彻底删除vscode(包括插件及配置!)

目录 一、简介 二、下载 1 旧版安装&#xff08;8.1.0&#xff09; 从 sourceforge.net 下载 2 新版安装(本次采用较新版本~~~) 从 github 下载 从 镜像站点 下载 自己编译 三、安装与配置 1. 在线安装&#xff08;这里仅作参考了解&#xff09; 2. 离线安装&…