当前位置: 首页 > 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…...

【ubuntu】ubuntu20.04安装显卡驱动

1.安装 点击右下角Apply Changes。 等安装好之后&#xff0c;重启。 现在的nvidia驱动已经很好安装了&#xff0c;比早期时安装出现黑屏等情况好了很多。 2.验证 nvidia-smi...

Mongo Java Driver使用getCollection做分页查询遇到的一些坑

背景 最近在做Mongo上的表数据的迁移&#xff0c;原本应该是DBA要干的活&#xff0c;但是想着DBA排期比较长&#xff0c;加上我们开发的权限又非常有限&#xff0c;而且数据量又没有多少&#xff0c;就想着自己开发个小小的程序从旧实例上查&#xff0c;写到新实例上去算了。于…...

RK3568笔记六十四:SG90驱动测试

若该文为原创文章,转载请注明原文出处。 前面有测试过PWM驱动,现在使用两种方式来产生PWM驱动SG90,实现舵机旋转任意角度 方法一:使用硬件PWM 方法二:使用高精度定时器,GPIO模拟PWM. 一、PWM子系统框架 二、SG90控制方法 舵机的控制需要MCU产生一个周期为20ms的脉冲信号…...

31 基于51单片机的水位监测系统仿真

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;DHT11温湿度检测&#xff0c;水位检测&#xff0c;通过LCD1602显示&#xff0c;超过阈值报警&#xff0c;继电器驱动电机转动。通过矩阵按键切换选择设置各项参数阈值。 …...

Docker 实践与应用举例

一、容器化Web应用&#xff1a; 创建一个Docker容器来运行一个简单的Web应用&#xff0c;例如一个基于Node.js的Express应用。首先&#xff0c;编写Dockerfile来定义容器的构建过程&#xff0c;然后使用Docker命令来构建和运行容器。 使用Docker Compose来定义和管理多个容器组…...

公开数据集网站分享

参考链接&#xff1a;常用的医学组织切片细胞图像数据集_细胞分割数据集-CSDN博客文章浏览阅读1.3w次&#xff0c;点赞32次&#xff0c;收藏133次。乳腺癌细胞图像数据集、血细胞图像数据集、HE染色切片、疟疾细胞图像图像识别、分类、分割_细胞分割数据集https://blog.csdn.ne…...

实验OSPF路由协议(课内实验)

实验1&#xff1a;OSPF路由协议 实验目的及要求&#xff1a; 通过实验&#xff0c;能够理解链路状态型路由协议OSPF协议的工作原理&#xff0c;掌握如何实现单区域 OSPFv2配置指令&#xff0c;能够熟练的应用各种OSPF协议相关的配置指令完善网络设计。掌握验证OSPFv2网络连接…...

GPU Puzzles讲解(一)

GPU-Puzzles项目可以让你学习到GPU编程和cuda核心并行编程的概念&#xff0c;通过一个个小问题让你理解cuda的编程和调用&#xff0c;创建共享显存空间&#xff0c;实现卷积和矩阵乘法等&#xff0c;通过每个小问题之后还会奖励一个狗狗小视频&#x1f601; 下面是项目的仓库&…...

滚雪球学Oracle[1.3讲]:内存与进程架构

全文目录&#xff1a; 前言一、SGA的深度解析1.1 SGA的作用与构成SGA的大小与调整 1.2 数据库缓冲区缓存&#xff08;DB Cache&#xff09;DB Cache的工作原理案例演示&#xff1a;调整DB Cache的大小 1.3 共享池&#xff08;Shared Pool&#xff09;的构成与调优共享池的组成部…...

Nginx的正向与反向代理

一、Nginx简介 1. 什么是Nginx Nginx&#xff08;发音为“engine-x”&#xff09;是一个高性能的HTTP和反向代理服务器&#xff0c;同时也是一个IMAP/POP3/SMTP代理服务器。Nginx是由俄罗斯的Igor Sysoev&#xff08;伊戈尔赛索耶夫&#xff09;为解决C10k问题&#xff08;即…...