【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
LPUSH
和RPUSH
LPUSH
命令的作用是将一个或多个元素从左侧(头插)插入到 list 中;而 RPUSH
命令的作用则是将一个或多个元素从右侧(尾插)插入到 list 中。
语法:
LPUSH key element [element ...]RPUSH key element [element ...]
LPUSHX
和RPUSHX
LPUSHX
命令的作用是当 key 存在时,将⼀个或者多个元素从左侧放⼊(头插)到 list 中,不存在则直接返回;而 RPUSHX
命令的作用是是当 key 存在时,将⼀个或者多个元素从右侧放⼊(头插)到 list 中,不存在则直接返回。
语法:
LPUSHX key element [element ...]RPUSHX key element [element ...]
2.2 LPOP 和 RPOP、BLPOP 和 BRPOP
LPOP
和RPOP
LPOP
命令的作用是从左侧删除一个元素(头删),并返回删除的值;而 RPOP
则是从右侧删除(尾删),然后返回删除的值。
语法:
LPOP keyRPOP key
BLPOP
和BRPOP
BLPOP
和 BRPOP
命令的作用和LPOP
、 RPOP
一样,只是需要指定一个超时时间,如果没有元素可以删除的时候,会进行阻塞,如果在设定的超时时间内向 Redis 中插入元素,则会立即执行;否则超时则之间退出。
语法:
BLPOP key [key ...] timeoutBRPOP key [key ...] timeout
另外,BLPOP
和 BRPOP
可以同时指定多个 key 进行删除。
2.3 LRANGE、LINDEX、LINSERT、LLEN
LRANGE
LRANGE
命令的作用是获取从 start 到 stop 区间的所有元素,区间左闭右闭,并且指定的位置可以是负数,表示倒数第几个。
语法:
LRANGE key start stop
LINDEX
LINDEX
命令的作用是获取从左边开始第 index 位置的元素。
语法:
LINDEX key index
LINSERT
LINSERT
命令的作用是在特定的位置插入元素。
语法:
LINSERT key BEFORE|AFTER pivot element
说明:
BEFORE
表示插入到 pivot 元素之前;AFTER
表示插入到 pivot 元素之后。
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 + n 问题。即如果每次分页获取的微博个数较多,需要执行多次
hgetall
操作,此时可以考虑使用pipeline
(流水线)模式批量提交命令,或者微博不采用哈希类型,而是使用序列化的字符串类型,使用 mget 获取。 - 分页获取文章时,
lrange
在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分。
相关文章:

【Redis】深入探索 Redis 的数据类型 —— 列表 List
文章目录 一、List 类型介绍二、List 类型相关命令2.1 LPUSH 和 RPUSH、LPUSHX 和 RPUSHX2.2 LPOP 和 RPOP、BLPOP 和 BRPOP2.3 LRANGE、LINDEX、LINSERT、LLEN2.4 列表相关命令总结 三、List 类型内部编码3.1 压缩列表(ziplist)3.2 链表(lin…...
高精度乘除法(超详细)
高精度乘除法(超详细) 题目1-高精度乘法 给定两个非负整数(不含前导 0) A 和 B,请你计算 AB 的值。 输入格式 共两行,第一行包含整数 A,第二行包含整数 B。 输出格式 共一行,包含…...
List 获取前N条数据
1.使用for循环遍历 public static void main(String[] args) {int limit 5;List<Integer> oldList Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);List<Integer> newList Lists.newArrayList();if (oldList.size() < limit) {newList.addAll(oldList);return;}fo…...
Spring入门控制反转(或依赖注入)AOP的关键概念 多配置文件与web集成
目录 1. 什么是spring,它能够做什么? 2. 什么是控制反转(或依赖注入) 3. AOP的关键概念 4. 示例 4.1 创建工程 4.2 pom文件 4.3 spring配置文件 4.4 示例代码 4.4.1 示例1 4.4.2 示例2 (abstract,parent示例) 4.4.3 使…...
排序算法-希尔排序
属性 1. 希尔排序是对直接插入排序的优化。 2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap 1时,数组已经接近有序的了,这样就会很 快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。 3.…...

ClientDataSet运行中出现“ClientDataSet:dataset not in edit or insert mode”(一)
在打开数据表文件,对ClientDataSet执行Append或Insert时,“ClientDataSet:dataset not in edit or insert mode”: 一、搜索问题 1、执行“显示数据后”,再执行Append,出错,说明ClientDataSet处…...

华为GaussDB数据库
Gauss数据库初识_高斯数据库_ygpGoogle的博客-CSDN博客 Redhat 7.6安装GaussDB_100_1.0.1详细攻略_gaussdb_100_1.0.1-database-redhat-64bit.tar.gz dow_博德1999的博客-CSDN博客 https://www.ngui.cc/el/3381579.html?actiononClick 初识GaussDB——GaussDB的发展历程、部…...

Flink、Spark、Hive集成Hudi
环境描述: hudi版本:0.13.1 flink版本:flink-1.15.2 spark版本:3.3.2 Hive版本:3.1.3 Hadoop版本:3.3.4 一.Flink集成Hive 1.拷贝hadoop包到Flink lib目录 hadoop-client-api-3.3.4.jar hadoop-client-runtime-3.3.4.jar 2.下载上传flink-hive的jar包 flink-co…...
百度编辑器 Ueditor 视频上传时 目录创建失败 解决办法
找到百度编辑器的上传类 Uploader.class.php文件.大约111左右 //$this->stateInfo $this->getStateInfo("ERROR_CREATE_DIR");//这句注释掉 $this->stateInfo $dirname;//换成这一句然后,进编辑器上传.会提示出一个错误的文件保存路径 双击复制下来这个路…...
Go 字符串处理
一、 字符串处理函数 我们从文件中将数据读取出来以后,很多情况下并不是直接将数据打印出来,而是要做相应的处理。例如:去掉空格等一些特殊的符号,对一些内容进行替换等。 这里就涉及到对一些字符串的处理。在对字符串进行处理时…...

家政服务接单小程序开发源码 家政保洁上门服务小程序源码 开源完整版
分享一个家政服务接单小程序开发源码,家政保洁上门服务小程序源码,一整套完整源码开源,可二开,含完整的前端后端和详细的安装部署教程,让你轻松搭建家政类的小程序。家政服务接单小程序开发源码为家政服务行业带来了诸…...

SuperMap iClient3D 11i (2023) SP1 for Cesium之移动实体对象
作者:nannan 目录 前言 一、代码思路 1.1 绘制面实体对象 1.2 鼠标左键按下事件 1.3 鼠标移动事件 1.4 鼠标左键抬起事件 二、运行效果 三、注意事项 前言 SuperMap 官网三维前端范例 编辑线面,可以对面实体对象的节点进行增加、删除以及修改位置…...

【深度学习 AIGC】stablediffusion-infinity 在无界限画布中输出绘画 Outpainting
代码:https://github.com/lkwq007/stablediffusion-infinity/tree/master 启动环境: git clone --recurse-submodules https://github.com/lkwq007/stablediffusion-infinity cd stablediffusion-infinity conda env create -f environment.yml conda …...

Flutter插件之阿里百川
上一篇:Flutter插件的制作和发布,我们已经了解了如何制作一个通用的双端插件,本篇就带领大家将阿里百川双端sdk制作成一个flutter插件供项目调用! 目录 登录并打开控制台,创建应用:填写应用相关信息开通百川…...

✔ ★ 算法基础笔记(Acwing)(三)—— 搜索与图论(17道题)【java版本】
搜索与图论 1. DFS1. 排列数字(3分钟)2. n-皇后问题 2. BFS(队列)1. 走迷宫二刷总结(队列存储一个节点pair<int,int>)三刷总结 走过的点标记上距离(既可以记录距离,也可以判断是否走过) ★ ★ 例题2. 八数码二刷…...

初试占比70%,计算机招生近200人,安徽理工大学考情分析
安徽理工大学 考研难度(☆) 内容:23考情概况(拟录取和复试分析)、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文980字,预计阅读:3分钟 2023考情概况 安徽理工大…...
LeetCode题解:1720. 解码异或后的数组,异或,JavaScript,详细注释
原题链接: https://leetcode.cn/problems/decode-xored-array/ 解题思路: 异或有如下性质: a ^ a 0a ^ 0 aa ^ b b ^ a 根据题意,已知encoded[i - 1] arr[i - 1] ^ arr[i],可以做如下转换: encoded[i…...

【C刷题】day2
一、选择题 1、以下程序段的输出结果是( ) #include<stdio.h> int main() { char s[] "\\123456\123456\t"; printf("%d\n", strlen(s)); return 0; } A: 12 B: 13 C: 16 D: 以上都不对【答案】: A 【解析】…...

Apollo源码安装的问题及解决方法
问题一 在进行git clone时,会报错Failed to connect to github.com port 443: Timed out,经过实践后推荐以下两种方法。 方法一:在原地址前加https://ghproxy.com 原地址:git clone https://github.com/ApolloAuto/apollo.git …...
Flutter 挖孔屏的状态栏占用问题怎么解决,横屏后去掉了状态栏,还是会有一块黑色的竖条
使用下方代码后依旧有一条黑色的区域 overridevoid initState() {// TODO: implement initStatesuper.initState();///关闭状态栏,与底部虚拟操作按钮SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);//隐藏状态栏,底部按钮栏S…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...