当前位置: 首页 > news >正文

Redis list 类型

list类型

类型介绍

列表类型 list 相当于 数组或者顺序表

list内部的编码方式更接近于 双端队列 ,支持头插 头删 尾插 尾删。

需要注意的是,Redis的下标支持负数下标。 比如数组大小为5,那么要访问下标为 -2 的值可以理解为访问 5 - 2 = 3

Redis中的数据是有序的,但是注意这里的有序不是指排序数组中的升序或者降序,而是指数据的顺序很关键。比如把元素位置调换之后,得到的新的list与原来的list是不等价的。

同样的一个词在不同的上下文中,它的意义可能是不一样的。

比如同步这个词在 线程之间和IO之间的意义就不同。 

另外list还提供了其他的一些功能,如图:

关于lindex和lrem两个命令 

在hash类型中,是不允许有重复数据的,也就是不能有重复的field。但是list可以有重复的值。

 lpush / lrange

lpush 

将⼀个或者多个元素从左侧放⼊(头插)到 list 中。  

LPUSH key element [element ...]
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。
注意:这里的插入是头插的方式,如果有多个值,那么会依次将这些值头插到list中。
如果key不存在,那么会先创建key再加入,如果key存在,并且不是list类型,那么会报错。

lrange

获取从 start 到 end 区间的所有元素,左闭右闭。 

LRANGE key start stop
时间复杂度:O(N)
返回值:指定区间的元素。

 谈到下标,那么往往就会关注超出范围的问题。

 可以看到Redis的做法是尽可能的获取到指定区间的元素,如果给定区间不合法,比如超出下标,那么依然会尽可能的获取到对应的内容。

lrange这里的l不是指left 而是指 list。 

扩展:一些超出下标范围的情况 

对于C++ :会认为这是一个未定义的行为

对于Java:会抛异常

 对于Redis:尽可能的获取到对应的内容。

lpushx / rpush / rpushx

lpushx

在 key 存在时,将⼀个或者多个元素从左侧放⼊(头插)到 list 中。不存在,直接返回
LPUSHX key element [element ...]
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。

rpush

将⼀个或者多个元素从右侧放⼊(尾插)到 list 中。

这样依次插入的元素就是顺序的 ,lpush就是倒序的

RPUSH key element [element ...]
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。

rpushx

在 key 存在时,将⼀个或者多个元素从右侧放⼊(尾插)到 list 中。 

RPUSHX key element [element ...]
时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
返回值:插⼊后 list 的⻓度。

 lpushx 和 rpushx 这里的x可以理解为exists。

lpop / rpop 

lpop

从 list 左侧取出元素(即头删)。 

 LPOP key
时间复杂度:O(1)
返回值:取出的元素或者 nil。

rpop

从 list 右侧取出元素(即尾删)。  

RPOP key
时间复杂度:O(1)
返回值:取出的元素或者 nil。

 

总结:

Redis的list其实就是一个双端队列,从两头插入/删除元素的效率都是 O(1):
搭配 lpush / lpop 可以当作一个队列使用

搭配 rpush/ rpop 可以当作一个栈使用

lindex / linsert / llen

lindex

获取从左数第 index 位置的元素。 

LINDEX key index
时间复杂度:O(N)
返回值:取出的元素或者 nil。

linsert

在特定位置插⼊元素。 

 LINSERT key <BEFORE | AFTER> pivot element
时间复杂度:O(N)
返回值:插⼊后的 list ⻓度。如果插入失败返回-1

因为list的结构不是数组,所以lindex和linsert都需要遍历找到位置,所以时间复杂度为O(N),这里的N指的就是list的长度,当list的长度不大时还好,如果list太长了,那么这两个命令的效率就低了。 

llen

获取 list ⻓度。 

LLEN key
时间复杂度:O(1)
返回值:list 的⻓度。

另外之前说过,list中是允许有重复值的,那么在insert的时候,如果选择的基准值有重复的,那么是如何插入的呢?

可以看见,当基准值有重复值时,Redis会从左向右遍历,找到以第一个符合基准值的位置为主。

lrem

批量删除等于 value的值。

当count > 0时:从左往右删除 count个元素。

当count < 0时:从右往左删除 count 个元素 。

当count = 0时:删除所有符合要求的元素。

rem 其实时 remove的缩写。

 

图中演示的就是从左往右删除 2 个 值 = 1的元素。 

ltrim / lset

ltrim

删除 除了 [left,right]区间之外的所有元素

ltrim key start stop

时间复杂度 O(N)

lset

根据下标来修改元素

lset key index element

时间复杂度O(N)

 另外这里如果下标越界了,是会直接报错的,跟lindex那里会返回一个nil是不同的。

blpop / brpop (阻塞版本命令)

 

blpop/brpop key timeout

 时间复杂度 O(1)
返回值:取出来的元素或者 nil(超时了)

blpop 和 brpop 是 lpop 和 rpop 的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致,除了:
在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的。但如果列表中没有元素,⾮阻塞版本会理
解返回 nil,但阻塞版本会根据 timeout,阻塞⼀段时间,期间 Redis 可以执⾏其他命令,但要求执
⾏该命令的客⼾端会表现为阻塞状态(如图 2-22 所⽰)。
命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元
素,命令⽴即返回。
如果多个客⼾端同时多⼀个键执⾏ pop,则最先执⾏命令的客⼾端会得到弹出的元素。

还可以针对多个key进行操作的,返回最先取出来的二元组。 

 

命令总结:

 

 

list内部编码 

 Redis老版本的方式

现在的redis是用一个quicklist的结构。

 

 

在redis的配置文件种,这个就是配置list的ziplist的最大长度的,这里的-2表示的是等级。 

redis配置文件的默认路径

cd /etc/redis

 

 

list的应用场景 

作为数组 

list作为数组,可以储存多个元素。

 在mysql下存储表结构

在Redis下存储

查询起来还是mysql的功能要丰富一些。

作为消息队列 

 

分频道的消息队列 

 

比如我们刷抖音,一个抖音界面有很多元素组成,比如视频,弹幕,点赞和评论等等,那么这些数据没必要由一个通道来传输,可以将这些元素分为多个通道传输。这样的好处是可以解耦合。

 

微博timeline 

每个⽤⼾都有属于⾃⼰的 Timeline(微博列表),现需要分⻚展⽰⽂章列表。此时可以考虑使⽤
列表,因为列表不但是有序的,同时⽀持按照索引范围获取元素。

 

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

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

 2)向⽤⼾ Timeline 添加微博,user:<uid>:mblogs 作为微博的键:

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

这里插入list中的是哈希表的索引。 

 3)分⻚获取⽤⼾的 Timeline,例如获取⽤⼾ 1 的前 10 篇微博:

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

 但是这里会存在一些问题:

1. 1 + n 问题。即如果每次分⻚获取的微博个数较多,需要执⾏多次 hgetall 操作,此时可以考虑使⽤pipeline(流⽔线)模式批量提交命令,或者微博不采⽤哈希类型,⽽是使⽤序列化的字符串类型,使⽤ mget 获取。

 

2. 分裂获取⽂章时,lrange 在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分。

 

 

 

相关文章:

Redis list 类型

list类型 类型介绍 列表类型 list 相当于 数组或者顺序表 list内部的编码方式更接近于 双端队列 &#xff0c;支持头插 头删 尾插 尾删。 需要注意的是&#xff0c;Redis的下标支持负数下标。 比如数组大小为5&#xff0c;那么要访问下标为 -2 的值可以理解为访问 5 - 2 3 …...

Linux更改固定IP地址

1.VMware里更改虚拟网络 一: 二: 三:确定就好了 2.修改Linux系统的固定IP 一:进入此文件 效果如下: 执行以下命令: 此时IP已更改 3.远程连接 这个是前提!!! 更改网络编辑器后网络适配器可能会修改,我就是遇着这个,困住我了一会 一:可以以主机IP对应连接 连接成功 二:主机名连…...

Qt+大恒相机回调图片刷新使用方式

一、前言 上篇文章介绍了如何调用大恒SDK获得回调图片&#xff0c;这篇介绍如何使用这些图片并刷新到界面上。考虑到相机的帧率很高&#xff0c;比如200fps是很高的回调频率。那么我们的刷新频率是做不到这么快&#xff0c;也没必要这么快。一般刷新在60帧左右就够了。 二、思路…...

Docker 环境下 PostgreSQL 监控实战:从 Exporter 到 Prometheus 的部署详解

Docker 环境下 PostgreSQL 监控实战&#xff1a;从 Exporter 到 Prometheus 的部署详解 文章目录 Docker 环境下 PostgreSQL 监控实战&#xff1a;从 Exporter 到 Prometheus 的部署详解一 节点简述二 节点监控部署1&#xff09;创建 PostgreSQL 的 exporter 账号2&#xff09;…...

构建带有调试符号的srsRAN 4G

### 构建带有调试符号 首先确保已下载srsRAN 4G&#xff0c;并已创建并导航至构建文件夹&#xff1a; bash git clone https://github.com/srsran/srsran_4g.git cd srsRAN_4G mkdir build cd build 若srsRAN 4G已构建完成&#xff0c;应清除原有构建文件夹后继续。 可以使…...

算法题总结(十)——二叉树上

#二叉树的递归遍历 // 前序遍历递归LC144_二叉树的前序遍历 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result new ArrayList<Integer>(); //也可以把result 作为全局变量&#xff0c;只需要一个函数即可。…...

【MySQL】MySQL 数据库主从复制详解

目录 1. 基本概念1.1 主从架构1.2 复制类型 2. 工作原理2.1 复制过程2.2 主要组件 3. 配置步骤3.1 准备工作3.2 在主服务器上配置3.3 在从服务器上配置 4. 监控和维护4.1 监控复制状态4.2 处理复制延迟4.3 故障恢复 5. 备份策略5.1 逻辑备份与物理备份5.2 增量备份 6. 使用场景…...

一种格式化printf hex 数据的方法

格式化输出HEX数据 调试过程中通常需要个格式化输出16进制数据&#xff0c;为了方便美观可以参考如下方法。 #define __is_print(ch) ((unsigned int)((ch) - ) < 127u - )/*** dump_hex* * brief hex打印* * param buf: 需要打印的原始数据* param size: 原始数据类型*…...

在LabVIEW中如何读取EXCEL

在LabVIEW中读取Excel文件通常使用“报告生成工具包”&#xff08;Report Generation Toolkit&#xff09;。以下是详细步骤&#xff1a; ​ 安装工具包&#xff1a;确保已安装“报告生成工具包”。这通常随LabVIEW一起提供&#xff0c;但需要单独安装。 创建VI&#xff1a; 打…...

布匹瑕疵检测数据集 4类 2800张 布料缺陷 带标注 voc yolo

布匹瑕疵检测数据集 4类 2800张 布料缺陷 带标注 voc yolo 对应标注&#xff0c;格式VOC (XML)&#xff0c;选配Y0L0(TXT) label| pic_ num| box_ _num hole: (425&#xff0c; 481) suspension_ wire: (1739&#xff0c; 1782) topbasi: (46&#xff0c; 46) dirty: (613&…...

灵动微高集成度电机MCU单片机

由于锂电技术的持续进步、消费者需求的演变、工具种类的革新以及应用领域的扩展&#xff0c;电动工具行业正呈现出无绳化、锂电化、大功率化、小型化、智能化和一机多能化的发展趋势。无绳化和锂电化的电动工具因其便携性和高效能的特性&#xff0c;已成为市场增长的重要驱动力…...

陪护小程序|护理陪护系统|陪护小程序成品

智能化&#xff0c;作为智慧医疗宏伟蓝图的基石&#xff0c;正引领着一场医疗服务的深刻变革。在这场变革的浪潮中&#xff0c;智慧医院小程序犹如璀璨新星&#xff0c;迅速崛起&#xff0c;而陪护小程序的诞生&#xff0c;更是如春风化雨&#xff0c;细腻地触及了老年病患、家…...

【JVM】基础篇

1 初识JVM 1.1 什么是JVM JVM 全称是 Java Virtual Machine&#xff0c;中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件。 Java源代码执行流程如下&#xff1a; 分为三个步骤&#xff1a; 1、编写Java源代码文件。 …...

软件测试工程师 朝哪里进阶?

软件测试工程师 朝哪里进阶&#xff1f; 这里浅谈一下我的看法。 软件测试工程师 朝哪里进阶呢&#xff1f; 当我们测试工程师工作了2-3年后&#xff0c;就需要往前走往高走&#xff0c;就像一句名言说的&#xff1a;我们需要像ceo一样工作。 将自己的边界扩大一点&#xff0…...

Obsidian Plugin Release Pre-check

- [ ] 修改代码 - [ ] 修改README.md - [ ] 修改manifest.json - [ ] --将上述修改push到GitHub-- - [ ] 修改release版本 git tag git tag -a 1.0.6 -m "1.0.6" git push origin 1.0.6 ------------------------------------------- 备忘https://semver.org/lang/…...

Unity中实现预制体自动巡逻与攻击敌人的完整实现指南

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

OpenJudge | Shortest Prefixes

总时间限制: 1000ms 内存限制: 65536kB 描述 A prefix of a string is a substring starting at the beginning of the given string. The prefixes of “carbon” are: “c”, “ca”, “car”, “carb”, “carbo”, and “carbon”. Note that the empty string is not co…...

速盾:高防服务器是如何防御CC攻击的?

高防服务器是一种专门用于防御DDoS&#xff08;分布式拒绝服务&#xff09;攻击的服务器。其中一种常见的DDoS攻击就是CC&#xff08;连续性攻击&#xff09;&#xff0c;它通过向目标服务器发送大量的请求来耗尽服务器资源&#xff0c;使网站无法正常运行。高防服务器采用多种…...

Android阶段学习思维导图

前言 记录下自己做的一个对Android原生应用层的思维导图&#xff0c;方便个人记忆扩展&#xff1b;这里只露出二级标题。 后语 虽然有些内容只是初步了解&#xff0c;但还是记录了下来&#xff1b;算是对过去一段学习的告别。...

React生命周期案例详解

React 组件的生命周期是指组件从创建、渲染、更新到卸载的整个过程。在 React 16 及之前的版本中&#xff0c;生命周期方法被分为几个不同的阶段&#xff1a;挂载&#xff08;Mounting&#xff09;、更新&#xff08;Updating&#xff09;、卸载&#xff08;Unmounting&#xf…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...