Redis数据结构之list列表

一.list列表

列表相当于数组或者顺序表

它里面的元素是有序的,也就是可以通过下标进行访问。这里的有序的含义是要根据上下文区分的,有的时候,有序指的是升序/降序,有的时候有序指的是顺序很关键,俩个元素交换后就不是同一个集合了。这里的list就是第二种,对应的下标有对应的值。

所以说,同样的一个词,怎么解释要看上下文。就好比栈/堆,是数据结构?还是操作系统的?还是JVM的?

也比如同步,是同步互斥的同步?还是同步异步的同步?

这里的list并不是一个简单的数组,它的底层接近于双端队列deque:

如上图,这个list支持头尾高效的删除插入元素,所以可以将list当成一个栈/队列来使用。

redis有一个典型的应用场景,就是作为消息队列,最早的时候就是通过list类型,只不过后来redis又提供了stream类型

list列表中的元素是允许重复的,但是像hash这样的类型,field是不能够重复的(因为它获取value就是根据field,如果重复了就不知道获取哪个value了;而list就是根据下标进行访问)。

二.相关命令

1.lpush

一次可以插入一个或多个元素,而且是按照顺序依次进行头插,所以全部插入完毕后,最后写下的匀速就是在list的最前边

时间复杂度:O(1)

返回值:list的长度

如果key已经存在,而且对应的value类型不是list,就会报错

2.lrange查看对应的list中指定范围的元素

lrange key start stop  注意,这里的区间是左右都闭

下标支持负数

如果给定的区间非法,比如超出了范围,他就会尽可能地获取到对应的内容如下:

这体现了程序的容错能力,也体现了鲁棒性(你对我越粗鲁,我就表现得越棒)

3.lpushx

与lpush不同的是,当指定的list存在时(也就是key存在),才能将元素放进去,如果list不存在,就直接返回

list2先前没有创建,所以push不进去

4.rpush

其实lpush是left push,所以rpush就是right push,也就是尾插啦

5.lpop rpop

左删和右删

返回值是删除的元素

时间复杂度都是o(1)

小结一下,redis中的list是一个双端队列,俩头插入/删除的时间复杂度都是O(1),搭配使用rpush和lpop就相当于队列(尾进头出),搭配使用rpush和rpop就相当于栈(尾进尾出)。

6.lindex

lindex key index 给定下标,获取对应的元素

时间复杂度是O(N),其实这里的N指的是list中的元素个数,当元素很少时,就能看做O(1)

下标非法就返回nil

7.linsert

linsert key before/after pivot element  在指定元素pivot之前/后插入元素element

返回值是插入之后的list的长度

8.llen

返回list的长度

时间复杂度:O(1)

9.lrem

lrem key count element 指定删除对应的key中的count个element,如果不够count个,那就能删几个删几个

count>0 那就从head开始删

count<0那就从tail开始删

count=0那就删除所有的element

10.ltrim

ltrim key start stop 保留start到stop之间的元素

11.lset

lset key index element 根据下标,修改元素

lindex对于下标的越界访问能够很好的处理,直接返回nil,但是对于lset来说,则会报错

时间复杂度:O(1)

12.阻塞版本

首先讲一下什么是阻塞:就是当前的线程不走了,代码不继续执行了,会在满足一定的条件之后被唤醒。

阻塞版本的头尾删除是:blpop brpop

当list不为空时,blpop和brpop就和lpop rpop效果完全一样;但当为空时,b版本的就会阻塞,直到再次插入元素。

咱们讲过阻塞队列(BlockingQueue)。多线程的时候,讲过一个生产者消费者模型,就是使用队列作为交易场所,期望这个队列右两个特性:1.线程安全2.阻塞->如果队列为空,尝试出队列就产生阻塞,如果队列为满,尝试入队列,就产生阻塞,直到队列不满解除阻塞。

redis中的list也相当于阻塞队列一样。线程安全是通过单线程模型支持的,阻塞则只支持队列为空的条件,不支持队列为满。

阻塞版本会根据timeout阻塞一段时间,但是阻塞期间可以执行其他指令。可以显示设置阻塞时间,超过后就自动返回。

blpop key [key……] timeout

先看指定一个key的版本,打开两个客户端

第一个窗口中先执行blpop,设定时间为100秒

然后第二个窗口里个该list设值

在回到第一个窗口,发现blpop出现了结果,返回值是list的名称加删除的结果加使用的时间

如果针对多个list进行操作,那么他也会尝试获取,但要是都没有元素,那就是最先插入元素的客户端会得到弹出的元素,但如果都有元素,那就是返回最先执行的客户端中的元素

先看都为空的情况:

再看都为满的情况:

如上,最先执行blpop的是lt2,所以返回lt2的

这俩个阻塞命令的用途主要就是作为消息队列,可以一定程度慢则消息队列这样的要求,但是整体来说还是有局限的

三.内部编码

列表的内部编码有两种:

1.ziplist压缩列表,当列表的元素个数小于list-ziplist-entries的配置时(默认是512个)同时列表中每一个元素的长度都小于list-max-ziplist-value的设置是,就会选用ziplist的内部编码方式来减少内存消耗

2.linkedlist,除上述之外都是linkedlist

但现在已经不适用这种方式了,而是直接使用quicklist,quicklist相当于是列表和压缩列表的结合体,就是每一个压缩列表都不要太大,同时再把多个压缩列表用链式结构连起来

四.list应用场景

1.list作为数组

list作为数组存储多个元素

在MySQL中,如下表示学生和班级的信息

如果使用redis,就可以像下面一样:

也就是每一个学生/班级对应一个list,每一个list存放的都是学生信息/班级信息。

2.redis作为消息队列

一个列表,多人获取:

谁先执行brpop这个命令,谁就先拿到新来的元素。

像这样的设定就能够达到“轮询式”的效果:假设消费者执行的顺序是1,2,3,当新元素到达后,消费者1就先拿到元素并且退出,如果消费者1还想再钠元素,就要重新执行brpop命令;此时再来一个新元素就是消费者2拿到元素,它想再拿到元素就得重新执行brpop命令;再来一个新元素就是消费者3拿到了~~,就好像食堂排队打饭一样

多个列表,多人获取:

多个列表/频道,这种场景非常常见,就比如抖音/快手~~

有一个通道是传输视频数据,还有一个通道传输弹幕,还有一个频道传输点赞、转发、收藏数据,还有一个频道传输评论数据

搞成多个频道,就可以在某种数据发生问题时,不会对其他频道的数据产生影响(解耦合)

就比如上图中,brpop key1 key2的key1阻塞了,但是对key2不会有影响,还能够拿到数据,堆key3也不会有影响,最大限度地减少了阻塞带来的风险

3.微博timeline

每一个用户都有属于自己的timeline(微博列表),现在需要分页展示文章列表,就可以使用到list。因为list不单是有许多,同时支持按照索引范围获取元素

首先,每一篇微博使用hash结构存储(一篇微博对应一个hash,一个field对应一个value)

其次,要向用户添加微博,user:<uid>:mblogs就是微博的键

最后,分页获取用户的timeline

但是当前一页中要显示多少数据,不确定,就可能会到这上面的循环次数比较多,从而会触发很多次hgetall,也就是很多次网络请求。此时可以考虑使用pipeline(流水线)模式批量提交用户命令,或者微博不采用hash进行存储,而是用字符串形式,然后用mget来获取(但一般不这样)

pipeline:流水线/管道,多个redis命令合并为一个网络请求进行通信,大大降低了客户端和服务器之间的交互次数

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

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

相关文章

<<编码>> 第 16 章 存储器组织(4)--内存 示例电路

内存内部结构 info::操作说明 译码器用于写入, 操作同上 选择器用于输出, 操作同上 地址信号同时控制译码器和选择器, 注意地址的高位在右(比如 001 实际是 100, 选择的是 Q6 和 I6) 缺省情况下, 内部数据全是 0. 读者可先通过译码器写入, 再通过选择器输出 primary::在线交…

YOLO原理实现

YOLO&#xff08;You Only Look Once&#xff09;是一个标志性的目标检测模型&#xff0c;可以快速分类并定位图像中的多个对象。本文总结了YOLO模型中所有关键的数学操作。 第一步&#xff1a;定义输入 要使用YOLO模型&#xff0c;首先必须将RGB图像转换为448 x 448 x 3的张…

再看Java-笔试

放在前面的话 最近确实有些空闲&#xff0c;分配的功能从一开始的两眼一黑到现在的一上午就能完成&#xff0c;这何尝不是一种进步呢。 该说不说&#xff0c;海康的API问题相比较其他第三方的API还是蛮多的&#xff0c;而且10月份人工客服还会停运&#xff0c;不过到那个时候…

【CTF】Nginx日志注入

Nginx日志注入&#xff1a; 日志包含漏洞的成因还是服务器没有进行严格的过滤 &#xff0c;导致用户可以进行任意文件读取&#xff0c;但是前提是服务器需要开启了记录日志的功能才可以利用这个漏洞。 对于Apache&#xff0c;日志存放路径&#xff1a;/var/log/apache/access.l…

华为HarmonyOS灵活高效的消息推送服务(Push Kit) - 5 发送通知消息

场景介绍 通知消息通过Push Kit通道直接下发&#xff0c;可在终端设备的通知中心、锁屏、横幅等展示&#xff0c;用户点击后拉起应用。您可以通过设置通知消息样式来吸引用户。 开通权益 Push Kit根据消息内容&#xff0c;将通知消息分类为服务与通讯、资讯营销两大类别&…

【Qt】QSS的设置方式

QSS的设置方式 QWidget 中包含了 setStyleSheet ⽅法, 可以直接设置样式. 上述代码我们已经演⽰了上述设置⽅式 还可以通过 QApplication 的 setStyleSheet ⽅法设置整个程序的全局样式. 设置全局样式&#xff0c;可以将界面上所有的样式都集中到一起来组织。 全局样式优点:…

图神经网络的新篇章:通用、强大、可扩展的图变换器

人工智能咨询培训老师叶梓 转载标明出处 图变换器&#xff08;Graph Transformers, GTs&#xff09;因其在处理节点间全局依赖关系方面的能力而受到广泛关注。然而&#xff0c;现有的GTs模型在处理大规模图时面临着计算复杂度高、泛化能力有限等问题。为了解决这些问题&#x…

UnLua扩展接口

一、在蓝图中创建接口 1、创建BlueprintInterface 2、声明接口函数 3、继承接口 注意&#xff0c;接口不需要绑定Lua&#xff0c;也没有Bind按钮 二、在Lua中实现接口函数 1、实现接口函数 BP_Player.lua function BP_Player_C:UpdateAiming(IsAiming)if IsAiming thensel…

maven手动导入本地仓库

maven手动导入本地仓库 1.在maven仓库下载对应的依赖 一定要把jar包下载到maven仓库的bin下 2.找到自己仓库的maven仓库下的bin目录cmd进去 在cmd窗口中输入以下命令&#xff1a;&#xff08;这里根据你的groupId、artifactId、version修改即可&#xff09; <!-- https:…

gpu scene cull

(1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) LaunchComputeRelevanceTask 调用堆栈 (1) (1)

12k star,这可能是我见过最强的国产开源支付系统!(附源码)

最近有读者问到支付系统相关的问题&#xff0c;这里推荐两个总体完成度还不错的国产开源支付系统&#xff0c;可以拿来学习&#xff0c;也可以根据项目需求直接拿来用。 01 Jeepay 项目介绍 &#xff1a; 一套适合互联网企业使用的开源支付系统&#xff0c;提供了交易、退款、…

IO流中的异常捕获

Java简化 接口AutoCloseable

【深入学习Redis丨第六篇】Redis哨兵模式与操作详解

〇、前言 哨兵是一个分布式系统&#xff0c;你可以在一个架构中运行多个哨兵进程&#xff0c;这些进程使用流言协议来接收关于Master主服务器是否下线的信息&#xff0c;并使用投票协议来决定是否执行自动故障迁移&#xff0c;以及选择哪个Slave作为新的Master。 文章目录 〇、…

vue3扩展echart封装为组件库-快速复用

ECharts ECharts&#xff0c;全称Enterprise Charts&#xff0c;是一款由百度团队开发并开源&#xff0c;后捐赠给Apache基金会的纯JavaScript图表库。它提供了直观、生动、可交互、可个性化定制的数据可视化图表&#xff0c;广泛应用于数据分析、商业智能、网页开发等领域。以…

在已安装的openresty上添加安装upstream模块报错的解决以及使用Consul服务发现时定时变更nginx的upstream的shell脚本

一、在已经安装好的openresty环境上添加安装upstream模块报错&#xff1a; 在已经安装好的openresty环境上添加安装upstream模块报错&#xff1a;http upstream check module can not find any check server, make sure you ve added the check 的问题解决。 服务器上已经安装好…

JavaWeb+Web服务器简介

一、Java Web 1.1 简介 Web&#xff0c;在英语中web即表示网页的意思&#xff0c;它用于表示Internet主机上供外界访问的资源。 Java Web指的是使用Java技术开发的Web应用程序。Java在Web开发中有着广泛的应用&#xff0c;主要得益于其跨平台性、安全性和丰富的开发工具与框…

鼻咽癌中三级淋巴结构的单细胞与空间转录组分析|文献精析·24-09-22

小罗碎碎念 研究团队通过单细胞和空间转录组分析&#xff0c;揭示了与鼻咽癌进展和免疫治疗反应相关的三级淋巴结构。 作者角色作者姓名单位&#xff08;中文&#xff09;第一作者Yang Liu/通讯作者Jin-Xin Bei国家癌症中心南方肿瘤学重点实验室&#xff0c;鼻咽癌诊断治疗广东…

TryHackMe 第3天 | Pre Security (二)

该学习路径讲解了网络安全入门的必备技术知识&#xff0c;比如计算机网络、网络协议、Linux命令、Windows设置等内容。上一篇中简短介绍了计算机网络相关的知识&#xff0c;本篇博客将记录 网络协议 部分。 How the web works? DNS in detail DNS (Domain name system&…

『功能项目』QFrameWork更新道具图片UGUI【71】

我们打开上一篇70QFrameWork物品交换UGUI的项目&#xff0c; 在资源商店免费下载图片 创建Image重命名为Icon并且隐藏Name 给Icon一张随意道具图片Icon 重新绑定对象 接下来创建IItem.cs接口 与 ItemConfig.cs道具配置类 创建Config文件夹 创建脚本&#xff1a;ItemConfig.cs 编…

【416】【举报垃圾信息】

这题倒挺简单的 注意一下映射关系&#xff0c;再使用字典即可。 class Solution:def reportSpam(self, message: List[str], bannedWords: List[str]) -> bool:nlen(message)if n1:return Falsedictdefaultdict(int)num0for a in message:dict[a]1for b in bannedWords:if…