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

news2024/12/23 14:32:07

文章目录

  • 一、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 key

RPOP key
  1. BLPOPBRPOP

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

语法:

BLPOP key [key ...] timeout

BRPOP 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.coloradmin.cn/o/1010177.html

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

相关文章

铝及铝合金产品标识知识学习记录

声明 本文是学习GB-T 42916-2023 铝及铝合金产品标识. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1— 圆铸锭表面&#xff1b; 2——切完头尾的圆铸锭尾端(引锭头端)。 图 9 圆铸锭刻痕标识示意图(一) 示 例 2 : 5A06 牌号、铸态、尺寸规格为…

4.4-Spring源码循环依赖终极讲解

回顾上期内容 new 容器 new AnnotateBeanDefinitionReader 的时候创建很多创世纪的类&#xff0c;其中有一个ConfigurationPostProcessor是用来解析配置类的&#xff0c;将其注册起来存到Bean定义的Map中【这个类是基于Bean工厂后置处理器的】 这一步是将配置类注册到Bean定…

VUE之滚动条参数设置

/*css主要部分的样式*/ /*定义滚动条宽高及背景&#xff0c;宽高分别对应横竖滚动条的尺寸*/ ::-webkit-scrollbar {width: 6px; /*对垂直流动条有效*/height: 6px; /*对水平流动条有效*/ }/*定义滚动条的轨道颜色、内阴影及圆角*/ ::-webkit-scrollbar-track{border-radius: 4…

Linux学习笔记-Ubuntu系统下配置用户ssh只能访问git仓库

目录 一、基本信息1.1 系统信息1.2 git版本[^1]1.2.1 服务器端git版本1.2.2 客户端TortoiseGit版本1.2.3 客户端Git for windows版本 二、创建git用户和群组[^2]2.1 使用groupadd创建群组2.2 创建git用户2.2.1 使用useradd创建git用户2.2.2 配置新建的git用户ssh免密访问 2.3 创…

Cglib代理和JDK代理原理的区别

一、JDK Jdk动态代理&#xff0c;拿到目标类所继承的接口&#xff0c;生成代理类&#xff0c;并且代理类也会实现和目标类一样的接口。 二、Cglib Cglib代理功能更强&#xff0c;无论目标类是否实现接口都可以代理&#xff0c;他是基于继承的方式类代理目标类&#xff0c;如果…

23下半年学习计划

大二上学期计划 现在已经是大二了&#xff0c;java只学了些皮毛&#xff0c;要学的知识还有很多&#xff0c;新的学期要找准方向&#xff0c;把要学的知识罗列&#xff0c;按部就班地完成计划&#xff0c;合理安排时间&#xff0c;按时完成学习任务。 学习node.js&#xff0c…

Python Opencv实践 - HoG特征计算

参考资料&#xff1a;https://www.cnblogs.com/alexme/p/11361563.html https://blog.csdn.net/qq_43348528/article/details/108638030 import cv2 as cv import numpy as np import matplotlib.pyplot as plt from skimage import exposure from skimage.feature i…

线段树上树剖再拿线段树维护:0914T4

cp 一种常见套路&#xff1a; 如果在线段树上进行一段区间修改&#xff0c;那么必然是一段右节点一段左节点 这个过程其实就是zkw的本质 下面都要用zkw来理解 考虑原题&#xff0c;有一棵不规则的线段树 类似zkw&#xff0c;在这类题目中&#xff0c;我们要先把开区间变成闭…

华为云Stack的学习(六)

七、华为云Stack计算服务介绍 1.计算服务整体介绍 2.弹性云服务器ECS ECS&#xff08;Elastic Cloud Server&#xff09;&#xff0c;即弹性云服务器&#xff0c;是由vCPU、内存、磁盘等组成的&#xff0c;获取方便、弹性可扩展、按需使用的、虚拟的计算服务器。 ECS只需要花…

【深度学习】 Python 和 NumPy 系列教程(十四):Matplotlib详解:1、2d绘图(下):箱线图、热力图、面积图、等高线图、极坐标图

目录 一、前言 二、实验环境 三、Matplotlib详解 1、2d绘图类型 0. 设置中文字体 1-5. 折线图、散点图、柱状图、直方图、饼图 6. 箱线图&#xff08;Box Plot&#xff09; 7. 热力图&#xff08;Heatmap&#xff09; 8. 面积图&#xff08;Area Plot&#xff09; 9. 等…

Zabbix“专家坐诊”第203期问答汇总

问题一 Q&#xff1a;用的模板&#xff0c;没用创建动作&#xff0c;但是触发器触发了我钉钉直接被通知了&#xff0c;怎么取消模板自带的动作&#xff1f; A&#xff1a;没有动作是不会触发事件告警的 &#xff0c;确定是从这个平台推出的钉钉消息&#xff1f;或者看下zabbix…

【操作系统】进程的通信IPC

进程通信是指进程之间的信息交换。 低级通信方式&#xff1a;PV操作 高级通信方式&#xff1a;1.共享存储2.消息传递3.管道通信 共享存储 低级数据结构共享&#xff0c;高级存储区共享。 对共享空间进行读写操作时&#xff0c;需要用到互斥工具。 消息传递 利用发送消息和…

Leetcode算法入门与数组丨3. 数组基础

文章目录 前言1 数组简介2 数组的基本操作2.1 访问元素2.2 查找元素2.3 插入元素2.4 改变元素2.5 删除元素 3 总结task03task04 前言 Datawhale组队学习丨9月Leetcode算法入门与数组丨打卡笔记 这篇博客是一个 入门型 的文章&#xff0c;主要是自己学习的一个记录。 内容会参…

Matlab图像处理-三原色

三原色 根据详细的实验结果&#xff0c;人眼中负责颜色感知的细胞中约有65%对红光敏感&#xff0c;33%对绿光敏感&#xff0c;只有2%对蓝光敏感。正是人眼的这些吸收特性决定了所看到的彩色是一般所谓的原色红&#xff08;R&#xff09;、绿&#xff08;G&#xff09;和蓝&…

十四、流式编程(1)

本章概要 流支持流创建 随机数流int 类型的范围generate()iterate()流的建造者模式Arrays正则表达式 集合优化了对象的存储&#xff0c;而流&#xff08;Streams&#xff09;则是关于一组组对象的处理。 流&#xff08;Streams&#xff09;是与任何特定存储机制无关的元素序列…

【2023】windows下安装libevent

Windows安装libevent 1.安装Visual Studio2.安装openssl第一种安装方式&#xff1a;[简便安装](https://slproweb.com/products/Win32OpenSSL.html)第二种&#xff1a;自己编译openssl 3.libevent下载libevent修改文件1.下边三个文件加入宏定义 #define _WIN32_WINNT 0x05002.修…

基于卷积神经网络的手写字体识别(详细笔记)

主要参考博客&#xff1a; 1、 基于卷积神经网络的手写数字识别&#xff08;附数据集完整代码操作说明&#xff09; 2、用PyTorch实现MNIST手写数字识别&#xff08;最新&#xff0c;非常详细&#xff09; 基于卷积神经网络的手写字体识别——目录 1 前言1.1 实现效果1.2 学习背…

国产洗碗机打响超越战

“征服世界的将是这样一些人&#xff1a;开始的时候&#xff0c;他们试图找到梦想中的乐园。最终&#xff0c;当他们无法找到时&#xff0c;就亲自创造了它。”诺贝尔文学奖获得者萧伯纳的这句话&#xff0c;适用于许多中国行业和企业&#xff0c;洗碗机就是其中之一。 对热爱…

十进制小数转换为单双精度浮点数方法

1 将十进制小数转换为单精度浮点数的方法如下&#xff1a; 2. 将十进制小数转换为双精度浮点数的方法如下&#xff1a; 和单精度浮点值转换一样

前端Layui框架介绍

当涉及到前端UI框架时&#xff0c;Layui&#xff08;简称layui&#xff09;是一个备受欢迎的框架之一。在这篇博客中&#xff0c;我们将深入了解layui&#xff0c;包括其市场占有率、开发语言、使用场景、框架特点以及一些使用案例。 1. 市场占有率 Layui 是一款流行的前端UI框…