Redis远程字典服务器(6) —— list类型详解

news2024/11/17 19:32:52

目录

一,基本情况

二,list常用命令

2.1 lpush,lrange

2.2 对于“下标越界”的思考 

2.3 lpushx,rpush,rpushx

2.4 lpop,rpop

2.5 lindex,linsert,llen 

2.6 lrem

2.7 ltrim,lset

2.8 阻塞版本命令

 2.9 blpop,brpop

三,内部编码

四,应用场景

4.1 作为数组

4.2 作为消息队列


一,基本情况

  1. 列表(list)相当于数组或者顺序表,约定最左边元素下标为0,后面依次递增;但是Redis的list支持负数下标,规定最右边的下标为-1,往左依次递减,如下图:
  2. 如上图,list支持左右两边的插入和删除:lpus,lpop,rpush,rpop。
  3. 所以list内部的编码方式,并非一个简单的数组,而是接近于deque那样的双端队列

 list类型特点

  • 列表中的元素是有序的:“有序”的含义要根据上下文区分,此处的“有序”不仅仅是升序降序,指的是顺序很关键(如果把元素位置调换,得到的新的list和旧的list是不等价的;当调换后新list和旧list一样,就称之为顺序不关键),所以一个词要怎么理解,务必要结合上下文,结合具体场景去理解
  • 区分获取元素和删除元素的区别:lrem是删除,lindex是获取,两个命令的返回值是一样的,容易混淆。
  • list中的元素允许重复:像hash这样的类型,field不能重复
  • 因为当前的list,能头和尾都能插入和删除,可以把list当作一个栈或者队列来使用

二,list常用命令

命令查询文档传送门:Commands | Docs (redis.io)

2.1 lpush,lrange

lpush表示从列表左边头插元素(插入1,2,3,4,完成操作后4在最前面),可以一次插入多个,能减少网络开销;lrange作用是查询指定区间的值,有三个参数,第一个为key,第二个和第三个为指定区间的开始下标和结束下标,是一个闭区间:

要想一次查询所有元素,只需要将lrange的开始设为0,结尾设为-1即可: 

注意

  • 如果key已经存在并且对应的value不是list,那么lpush就会报错 
  • lrange前面显示的序号和下标无关,是专门给结果集使用的序号,给我们看的。(hash类型操作也有这样的序号,但是也和下标无关,因为hash没有下标的概念)

2.2 对于“下标越界”的思考 

问题:谈到下标,往往会有“超过范围”这样的情况,如何理解?

解答: C++中,下标超出范围,一般会认为这是一个“未定义行为”,可能会导致程序崩溃,也可以会得到一个不合法的数据,还有可能会得到一个“看起来合法,但是错误”的数据,还有可能得到符合要求的数据(类似开盲盒);而在Java中,下标超出范围,一般会“抛异常”。

而在Redis中,两种行为都为采用,如果区间是合法的就正常搞,如果不合法,就直接尽可能去获取对应的内容,这种处理方式接近于Python的“切片”的处理方式。

比如,盆友找我借100,但是我只有50,盆友说:“50就50吧,借我一下谢谢”,能给多少给多少这样。

C++和Java对于越界的处理方式,有哪些优点缺点呢?

C++的处理方式:

  • 优点:效率是最高的,因为Java要抛异常,就代表Java要多出一步“下标合法性验证”的步骤,做的工作多了,效率就低了
  • 缺点:程序员不一定能第一时间发现问题,而且很难发现,就导致最后的结果是“带伤运行”,最后越积越多,导致严重后果

Java的处理方式:

  • 优点:出现问题能及时发现
  • 缺点:效率没C++高,因为多了一步

Redis或Python的处理方式,是一种更加柔和式的做法,称之为“鲁棒性”(你对我越粗鲁,我就表现得越棒),这样的设定能大大提高程序的“容错性”,但是也有代价,所以这三种方式的实现,还是需要集合具体场景去搞

2.3 lpushx,rpush,rpushx

lpushx作用是,如果key存在,就头插操作,如果不存在就什么都不做;rpush就是尾插,其余机制和lpush一样;rpushx和lpushx的作用一样,只是变成了尾插:

问题:有lrange,有没有rrange呢?

解答:没有,因为lrange,延长来说是list range,不是left range 

2.4 lpop,rpop

lpop头删,,当key不存在,返回nil;rpop尾删,当key不存在,返回nil

注意

在从Redis 6.2 版本中,新增了count参数,但是当前的Redis 5 版本没有,count表示一次要删除几个数,因为一次只删一次相比一次删多个效率确实低了点  

2.5 lindex,linsert,llen 

lindex作用是根据下标来获取元素,下标非法返回nil;linsert就是在指定下标插入元素,可以自定义在左边插入还是在右边插入,下标非法返回nil;llen返回list长度,key不存在返回0:

lindex: 

linsert: 

linsert key BEFORE|AFTER pivot element

先从左往右根据基准值找到符合要求的位置,再进行插入 

llen

2.6 lrem

lrem key count element

count表示要删除的个数,element表示要删除的值

关于count还有一些说法,官方文档给出的解释如下:

解释一下: 

  • 当count > 0:从左往右去找,比如list值为“1 2 3 4 1 2 3 4 1 2 3 4”,count为2,element为1,表示从左往右找1,删两次1,结果变成“2 3 4 2 3 4 1 2 3 4”,前面两个1被删除
  • 当count < 0:从右往做找,以上面的为例,count为-2,element为1,表示从右往左找两个1删除,最后变成“1 2 3 4 2 3 4 2 3 4”,后面的两个1被删除
  • 当count = 0:删除所有的指定元素,还是以上面的为例,count为0,element为1,就找到所有的1删除,结果为“2 3 4 2 3 4 2 3 4

2.7 ltrim,lset

ltrim作用也是删除元素,但是是反过来的,指定一个区间,保存这个区间里的元素,区间外的就删除,区间不合法时返回0;lset作用是根据下标修改元素:

ltrim: 

在官方文档中查询ltrim时,还有一个东西: 

  1. 其中ACL全程是access control list,访问控制列表,是一个和权限相关的东西,从Redis 6 版本开始支持
  2. Redis有很多命令,acl这块就把每个命令打上一些标签,比如上面的@write表示这是一个“写”命令,@list表示这是一个和list类型相关的命令,@slow表示这个命令可能会很耗时
  3. 打好标签之后,管理员给每个Redis用户配置不同的权限,让该用户执行“能执行”的命令

lset: 

lset key index element

index表示要开始修改的下标位置,element表示要修改的元素

2.8 阻塞版本命令

阻塞:当前的线程不走了,代码不继续执行了,在满足一定条件后被唤醒

blpop,brpop是阻塞命令中两个最重要的,前面的b表示block阻塞

我们在学习生产者消费者模型时,讲到了一个阻塞队列:Linux系统编程——生产者消费者模型_编程 消费者-CSDN博客

 用队列来作为交易场所,并且希望这个队列有两个特性:1,线程安全    2,阻塞:

  • 如果队列为空,此时尝试出队列,就阻塞,直到队列不为空,阻塞接触
  • 如果队列为满,此时尝试入队列,就阻塞,直到队列不为满,阻塞接触

Redis中list也相当于一个阻塞队列, 首先线程安全通过单线程模型能保证,而阻塞只支持“队列为空”的情况,不考虑“队列为满”。

blpop 和 brpop 是 lpop 和 rpop 的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致,除了:

  • 在list不为空的情况下,blpop 和 brpop 就和 lpop 和 rpop作用一样;但如果list为空,blpop 和 brpop就会阻塞住,直到队列不为空
  • 使用blpop 和 brpop 的时候,是可以设置阻塞时间的,如果阻塞了,那么在这个阻塞时间内是可以执行其它命令的;当阻塞时间到了,会自动返回(例子:我约女生晚上6点吃饭,结果我等到9点女生还没来,我就不等了,及时止损,节约我的时间)
  • blpop 华人 brpop 都是可以同时去获取多个key的列表的元素的,就是命令行可以同时出现多个key的,这多个list哪个有元素了,就会返回哪个值(例子:我可以同时约多个女生出来吃饭,哪个女生先到了我就和哪个去吃饭,其她的不管了)
  • 如果多个客⼾端同时多⼀个键执⾏ pop,则最先执⾏命令的客⼾端会得到弹出的元素(例子:多个人约女生,当女生有空时,哪个人最先约的女生,女生就和谁去吃饭)

 2.9 blpop,brpop

blpop key [key ...] timeout
  1. blpop的选项和brpop是一样的,可以指定多个key,每个key都对应一个list,如果这些list有任意一个非空,blpop和brpop都能够把这里的元素获取到立即返回,
  2. 如果list都为空,就会阻塞住,等待其他客户端往list插入数据;
  3. 另外还可以指定超时时间,单位为秒;在Redis 6 版本后,允许设为小数 

我们先针对一个非空的list进行操作:

 

  • 返回的结果是一个pair,一方面告诉我们你当前的数据来自于哪个key,另一方面告诉我们取到的数据是啥

我们针对空的列表进行操作: 

我们删掉key后,在blpop就阻塞住了,然后我们在右边的客户端一创建key, 左边的客户端就立马拿到了数据,brpop作用和现象和blpop一样,就不做演示了

这两个阻塞命令,用途主要就是来作为“消息队列”,但是我们一般不使用,因为前面也说过了,Redis不适合拿来做消息队列,因为有其他更好的产品可以用作消息队列,而且提供的功能也比较多

三,内部编码

旧版本是用ziplist和linkedlist作为底层实现的,但是现在已经不用了,直接用的quicklist来实现了,但是我们去查一些文档时,上面可能还是解释的ziplist和linkedlist,所以我们只简单了解下这两个,重点还是在quicklist:

  • ziplist(压缩列表):当列表的元素个数⼩于 list-max-ziplist-entries 配置(默认 512 个),同时 列表中每个元素的⻓度都⼩于 list-max-ziplist-value 配置(默认 64 字节)时,Redis 会选⽤ ziplist 来作为列表的内部编码实现来减少内存消耗。
  • linkedlist(链表):当列表类型⽆法满⾜ ziplist 的条件时,Redis 会使⽤ linkedlist 作为列表的内 部实现。

quicklist相当于链表和压缩列表的结合,整体是一个链表,但是它的每个节点是一个压缩列表(每个压缩列表都限制大小,然后再把多个压缩列表通过链式结构组织起来,就是quicklist)

四,应用场景

4.1 作为数组

最经典的,就是用list作为“数组”来存储多个元素

4.2 作为消息队列

虽说Redis不经常用来做消息队列,但毕竟是Redis设计的初心,了解一下有利于了解Redis的发展 

多个客户端执行brpop操作,当列表为空时,brpop就会阻塞住,一旦有新元素来了,谁先执行的brpop命令,谁就能拿到这个新来的元素,像这样的设定,就能构成一个“轮询”式的效果。

假设消费者执行的顺序是1 2 3:

  1. 当新元素到达后,首先是消费者1最先执行的brpop,所以它最先拿到元素,然后brpop执行执行完了直接返回,假设线程1还想继续消费,就需要重新执行brpop,重新去排队
  2. 然后再来一个新元素,就是消费者2拿到元素,也从brpop返回,要想再拿数据也需要重新排队
  3. 再来一个新元素,就是消费者3拿到元素了

将上面的模型扩大一下,就是下面这样的了: 

 因为多个 列表或者频道是非常常见的,比如抖音,需要有一个通道来传输视频数据,还有传输弹幕,传输点赞收藏转发,传输评论数据等等,都需要一个频道来传输,因为像这样搞成多个频道,就可以在一个数据通道发生问题时,不会对其他数据造成影响(解耦合

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

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

相关文章

基于B站的热门视频数据分析与情感分析【关联性、主题、情感分析】

目录 2 研究内容 2.1 主要研究内容 2.2 拟解决的关键问题 2.2.1热门视频特征的识别和提取 2.2.2情感分析与用户反馈 2.3技术路线 2.3.1数据收集 2.3.2数据预处理 2.3.3数据挖掘 2.3.4 数据可视化 2.4可行性分析 2.4.1技术可行性 2.4.2数据可行性 2.4.3经济可行性 2.5数据库设计…

vba发送邮件功能实现方法:如何调试测试?

vba发送邮件的配置步骤流程&#xff1f;vba发送邮件的安全指南&#xff1f; VBA是一种常用于自动化Office应用程序的编程语言。利用VBA发送邮件功能&#xff0c;用户可以实现自动化发送邮件的任务&#xff0c;无需手动操作。AokSend将详细探讨如何通过调试与测试来确保VBA发送…

ThreadLoad如何防止内存溢出

优质博文&#xff1a;IT-BLOG-CN 从 ThreadLocalMap看 ThreadLocal使用不当的内存泄漏问题 【1】基础概念 &#xff1a; 首先我们先看看ThreadLocalMap的类图&#xff0c;我们知道 ThreadLocal只是一个工具类&#xff0c;他为用户提供get、set、remove接口操作实际存放本地变…

MT7621+MT7915(MT7905)+MT7975 (W7621A6G-SDK)编译固件与升级固件方法

一、搭建开发环境&#xff0c;编译固件。 1、安装在Ubuntu 14.04.5 x86_64系统后&#xff0c;然后安装下面命令行。 $ sudo apt-get install git g make libncurses5-dev subversion libssl-dev gawk libxml-parser-perl unzip wget python xz-utils vim zlibc zlib1g zlib1g…

XSS---DOM破坏靶场复现

目录 一、OK&#xff0c;Boomer 一、网址&#xff1a; 二、源码分析&#xff1a; 三、 解决思路&#xff1a; 1.页面中的元素可以通过id和name直接取出来 2.覆盖 3.覆盖方法 四、ToString 五、setTimeout函数 六、使用框架白名单 七、成功绕过 ​编辑 二、案例分析…

才来鱼厂实习 1 个月,就转正了!

大家好&#xff0c;我是程序员鱼皮。昨天&#xff0c;我给才来我们公司 实习一个月 的前端开发同学转正了&#xff0c;直接发了正式 Offer&#xff01;这个转正速度&#xff0c;放眼到所有公司中&#xff0c;我相信也是炸裂的。 看小伙子那么激动&#xff0c;让我回想到了 19 年…

认识 bufferbloat

很多人并不理解 bufferbloat 的本质&#xff0c;我引用《计算机网络-自顶向下方法(第 8 版)》第四章的一个解释&#xff1a; 很形象的比喻&#xff0c;buffer 就像盐&#xff0c;不可或缺&#xff0c;适量增味&#xff0c;过量食物就不能吃了。高血压患者更有所感受&#xff…

STM32是基于ARM架构的,那么ARM究竟是什么呢?

一、什么是ARM 首先&#xff0c;ARM是一家英国公司&#xff0c;全称Advanced RISC Machines&#xff0c;高级精简指令集机器&#xff0c;RISC意味着是精简指令集的芯片。同时也有复杂指令集CSIC的芯片&#xff0c;如X86&#xff0c;常以Intel和AMD为主。 其次&#xff0c;之后…

如何跳过极狐GitLab 密钥推送保护功能?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

vue 子组件全局自动导入,不在需要每个组件import

main.js import vue from vue import App from ./App.vue import axios from axios axios.defaults.baseURL HTTP://LOCALHOST:3000/api/ Vue.prototype.$http axios; vue config.productionTip false; //子组件全局自动导入 const requireComponents require.cont…

MK米客方德推出新一代工业级SD NAND——更长寿命、更高速度、更优功耗

博客目录 关注我&#xff0c;不迷路&#xff0c;共学习&#xff0c;同进步一、产品封装与兼容性二、SLC 存储颗粒的使用三、高性能 IOPS 表现四、智能健康监测功能五、内嵌 ECC 校验、坏块管理和其他保护机制六、低功耗设计总结 作为 SD NAND 领域的领跑者&#xff0c;MK 米客方…

【Chromium】分享一个网址 Chromium Browser Snapshots

利用 Chromium Browser Snapshots 进行开发和调试 author: jwensh & chatgpt date:20240819 文章目录 利用 Chromium Browser Snapshots 进行开发和调试1. 获取最新的浏览器特性2. 测试和调试浏览器兼容性问题3. 开发和测试浏览器扩展4. 安全研究和漏洞分析5. 提前为新特性…

如何一键删除iPhone相册所有照片

拍照已成为我们记录日常生活的常态。但是&#xff0c;大量照片便会积累在设备上&#xff0c;这不仅占用了大量存储空间&#xff0c;而且随着时间的推移&#xff0c;管理这些照片也变得越来越困难。如果你决定清理旧照片&#xff0c;或者出于隐私考虑需要删除所有照片&#xff0…

2024:AI新纪元,轻松打造你的专属AI助手

引入 在数字化时代的潮流中&#xff0c;人工智能已经成为了我们生活中不可或缺的一部分。2024年被誉为“AI元年”&#xff0c;这不仅是因为人工智能技术的飞速发展&#xff0c;更是因为它已经渗透到我们的日常生活中&#xff0c;为我们带来了无数便利和可能性。在这个充满活力…

FPGA使用笔记:GPIO操作方式(用于测试设备io驱动性能)

一、前言 使用FPGA测试IO速率&#xff0c;用于后续驱动高速AD/DA等高速芯片做铺垫&#xff0c;很多芯片的驱动都是使用并行接口&#xff0c;不是使用专用接口的&#xff0c;这样采样速率的快慢就有CPU的时许周期决定了。 本文测试FPGA和STM32&#xff0c;后续如果用到更快的芯…

探索大模型时代:全面解析Agent智能体的奥秘

前言&#xff1a; 在2024年&#xff0c;大模型圈子的Agent是一个绝对热门的话题&#xff0c;agent也被各种各样的公众人物所追捧 Agent智能体能够最大化的激发大模型潜能还有人说agent智能体式大模型时代的APP&#xff0c;也有人说agent是在toB场景落地的主要方式之一 无论任…

信创(国产化)方案

信创 信创&#xff0c;即信息技术应用创新&#xff0c;旨在实现信息技术自主可控 openEuler openEuler是一款开源、免费的操作系统&#xff0c;由openEuler社区运作&#xff0c;前身为运行在华为公司通用服务器上的操作系统EulerOS。openEuler作为一款开源、免费的操作系统&…

QT6.0如何开启白名单保活

1. 概述 使用Qt开发android应用往往会存在这样一个问题:我们的android应用和后台需要时刻保持通信,但是往往我们在切换任务或者息屏,将我们开发的应用变更为后台应用的时候,由于android的电池策略,会将后台的应用关闭掉从而释放资源供其他应用使用.会给应用带来不好的使用…

Dubbo从入门到应用:实战技巧和最佳实践

远程调用 一、Dubbo快速上手提供者DubboService 调用者DubboReference 开启Dubbo调用EnableDubbo 二、Dubbo快速入门1、添加 Dubbo 相关的 maven 依赖。2、定义服务接口3、 定义服务端的实现4、配置服务端及消费端 Yml 配置文件5、基于 Spring 配置服务端及消费端启动类6、消费…

每日学习笔记:C++ STL之堆栈容器stack

目录 stack定义 核心接口 stack class声明 stack class定义 用户自定义的Stack Class C11特色的插入元素的新形式 运用实例 stack定义 核心接口 stack class声明 stack class定义 用户自定义的Stack Class C11特色的插入元素的新形式 运用实例