【Redis】Redis十大数据类型—列表List

news2024/11/13 10:14:52

介绍

List列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向List列表添加元素。

列表的最大长度是2^32-1,也就是每个列表支持超过40亿个元素。

实现

底层数据结构是由双向链表或压缩列表实现。

  • 如果列表的元素个数小于 512 个(默认值,可由 list-max-ziplist-entries 配置),列表每个元素的值都小于 64 字节(默认值,可由 list-max-ziplist-value 配置),Redis 会使用压缩列表作为 List 类型的底层数据结构;
  • 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构;

在Redis3.2版本之后,List数据类型底层数据结构就只由quicklist实现。

常用命令

在这里插入图片描述在这里插入图片描述

示例

LPUSH

LPUSH key element [element ...]

将一个或多个值value插入到key列表的表头(最左边),最后的值在最前面

127.0.0.1:6379> lpush k1 1 2 3 4
(integer) 4
127.0.0.1:6379> lrange k1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"

RPUSH

RPUSH key element [element ...]

将一个或多个值value插入到key列表的表尾(最右边)

127.0.0.1:6379> rpush k2 1 2 3 4
(integer) 4
127.0.0.1:6379> lrange k2 0 -1
1) "1"
2) "2"
3) "3"
4) "4"

LRANGE

LRANGE key start stop

返回列表key中指定区间内的元素,区间以偏移量start和stop指定,从0开始

LPOP

LPOP key [count]

移除并返回key列表的头元素,或者移除count个头元素

127.0.0.1:6379> lrange k2 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> LPOP k2 2
1) "1"
2) "2"
127.0.0.1:6379> lrange k2 0 -1
1) "3"
2) "4"
127.0.0.1:6379> LPOP k2
"3"
127.0.0.1:6379> lrange k2 0 -1
1) "4"

RPOP

RPOP key [count]

移除并返回key列表的尾元素

127.0.0.1:6379> lrange k2 0 -1
1) "4"
2) "k"
3) "u"
4) "a"
5) "n"
6) "g"
127.0.0.1:6379> RPOP k2
"g"
127.0.0.1:6379> lrange k2 0 -1
1) "4"
2) "k"
3) "u"
4) "a"
5) "n"
127.0.0.1:6379> RPOP k2 2
1) "n"
2) "a"
127.0.0.1:6379> lrange k2 0 -1
1) "4"
2) "k"
3) "u"

LINDEX

LINDEX key index

按照索引下标获得元素(从上到下)

127.0.0.1:6379> LRANGE k1 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> LINDEX k1 1
"3"
127.0.0.1:6379> LINDEX k1 0
"4"
127.0.0.1:6379> LINDEX k1 2
"2"

LLEN

LLEN key

获取列表中元素的个数

127.0.0.1:6379> LRANGE k1 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> LLEN k1
(integer) 3

LREM

LREM key count element

删除count 个值等于element的元素,返回值为实际删除的数量。

count等于0时,表示删除全部给定的值。

127.0.0.1:6379> LRANGE k3 0 -1
1) "v4"
2) "v3"
3) "v3"
4) "v2"
5) "v2"
6) "v1"
7) "v1"
8) "v1"
127.0.0.1:6379> LREM k3 2 v1
(integer) 2
127.0.0.1:6379> LRANGE k3 0 -1
1) "v4"
2) "v3"
3) "v3"
4) "v2"
5) "v2"
6) "v1"

127.0.0.1:6379> LREM k3 0 v2
(integer) 2
127.0.0.1:6379> LRANGE k3 0 -1
1) "v4"
2) "v3"
3) "v3"
4) "v1"

LTRIM

LTRIM key start stop

截取指定索引区间的元素,然后赋值给key

127.0.0.1:6379> LRANGE k3 0 -1
1) "v4"
2) "v3"
3) "v3"
4) "v1"
127.0.0.1:6379> LTRIM k3 1 3
OK
127.0.0.1:6379> LRANGE k3 0 -1
1) "v3"
2) "v3"
3) "v1"

RPOPLPUSH

RPOPLPUSH source destination

移除列表的最后一个元素,并将该元素添加到另一个列表并返回

127.0.0.1:6379> LRANGE k2 0 -1
1) "g"
2) "n"
3) "a"
4) "u"
5) "k"
127.0.0.1:6379> LRANGE k1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> RPOPLPUSH k1 k2
"1"
127.0.0.1:6379> LRANGE k2 0 -1
1) "1"
2) "g"
3) "n"
4) "a"
5) "u"
6) "k"
127.0.0.1:6379> LRANGE k1 0 -1
1) "4"
2) "3"
3) "2"

LSET

LSET key index element

设置索引为index的元素值为element。

127.0.0.1:6379> LSET k3 0 v5
OK
127.0.0.1:6379> LRANGE k3 0 -1
1) "v5"
2) "v3"
3) "v1"

LINSERT

LINSERT key <BEFORE | AFTER> pivot element

在list某个已有值pivot的前后再添加具体值element

127.0.0.1:6379> LRANGE k3 0 -1
1) "v5"
2) "v3"
3) "v1"
127.0.0.1:6379> LINSERT k3 before v3 v4
(integer) 4
127.0.0.1:6379> LRANGE k3 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v1"
127.0.0.1:6379> LINSERT k3 after v1 v6
(integer) 5
127.0.0.1:6379> LRANGE k3 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v1"
5) "v6"

BLPOP

BLPOP key [key ...] timeout

从key列表表头弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞

127.0.0.1:6379> lrange k2 0 -1
1) "u"
127.0.0.1:6379> BLPOP k2 0
1) "k2"
2) "u"
127.0.0.1:6379> BLPOP k2 0 #k2中没有元素,这时执行BLPOP,同时timeout为0,导致一直阻塞
 

BRPOP

BRPOP key [key ...] timeout

从key列表表尾弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞

应用场景

消息队列

消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息和保证消息可靠性

Redis 的 List 和 Stream 两种数据类型,就可以满足消息队列的这三个需求。我们先来了解下基于 List 的消息队列实现方法,后面在介绍 Stream 数据类型时候,在详细说说 Stream。

1、如何满足消息保序需求?

List 本身就是按先进先出的顺序对数据进行存取的,所以,如果使用 List 作为消息队列保存消息的话,就已经能满足消息保序的需求了。

List 可以使用 LPUSH + RPOP (或者反过来,RPUSH+LPOP)命令实现消息队列。

fd0282dbb76d666176d52f64bbae0ef8.png

  • 生产者使用 LPUSH key value[value...] 将消息插入到队列的头部,如果 key 不存在则会创建一个空的队列再插入消息。
  • 消费者使用 RPOP key 依次读取队列的消息,先进先出。

在生产者往 List 中写入数据时,List 并不会主动地通知消费者有新消息写入,如果消费者想要及时处理消息,就需要在程序中不停地调用 RPOP 命令(比如使用一个while(1)循环)。如果有新消息写入,RPOP命令就会返回结果,否则,RPOP命令返回空值,再继续循环。

所以,即使没有新消息写入List,消费者也要不停地调用 RPOP 命令,这就会导致消费者程序的 CPU 一直消耗在执行 RPOP 命令上,带来不必要的性能损失。

为了解决这个问题,Redis提供了 BRPOP 命令。BRPOP命令也称为阻塞式读取,客户端在没有读到队列数据时,自动阻塞,直到有新的数据写入队列,再开始读取新数据。和消费者程序自己不停地调用RPOP命令相比,这种方式能节省CPU开销。

2、如何处理重复的消息?

消费者要实现重复消息的判断,需要 2 个方面的要求:

  • 每个消息都有一个全局的 ID。
  • 消费者要记录已经处理过的消息的 ID。当收到一条消息后,消费者程序就可以对比收到的消息 ID 和记录的已处理过的消息 ID,来判断当前收到的消息有没有经过处理。如果已经处理过,那么,消费者程序就不再进行处理了。

但是 List 并不会为每个消息生成 ID 号,所以我们需要自行为每个消息生成一个全局唯一ID,生成之后,我们在用 LPUSH 命令把消息插入 List 时,需要在消息中包含这个全局唯一 ID。

例如,我们执行以下命令,就把一条全局 ID 为 111000102、库存量为 99 的消息插入了消息队列:

> LPUSH mq "111000102:stock:99"
(integer) 1

3、如何保证消息可靠性?

当消费者程序从 List 中读取一条消息后,List 就不会再留存这条消息了。所以,如果消费者程序在处理消息的过程出现了故障或宕机,就会导致消息没有处理完成,那么,消费者程序再次启动后,就没法再次从 List 中读取消息了。

为了留存消息,List 类型提供了 BRPOPLPUSH 命令,这个命令的作用是让消费者程序从一个 List 中读取消息,同时,Redis 会把这个消息再插入到另一个 List(可以叫作备份 List)留存

这样一来,如果消费者程序读了消息但没能正常处理,等它重启后,就可以从备份 List 中重新读取消息并进行处理了。

好了,到这里可以知道基于 List 类型的消息队列,满足消息队列的三大需求(消息保序、处理重复的消息和保证消息可靠性)。

  • 消息保序:使用 LPUSH + RPOP;
  • 阻塞读取:使用 BRPOP;
  • 重复消息处理:生产者自行实现全局唯一 ID;
  • 消息的可靠性:使用 BRPOPLPUSH

但是,在用 List 做消息队列时,如果生产者消息发送很快,而消费者处理消息的速度比较慢,这就导致 List 中的消息越积越多,给 Redis 的内存带来很大压力

要解决这个问题,就要启动多个消费者程序组成一个消费组,一起分担处理 List 中的消息。但是,List 类型并不支持消费组的实现

Redis 从 5.0 版本开始提供的 Stream 数据类型了,Stream 同样能够满足消息队列的三大需求,而且它还支持「消费组」形式的消息读取。

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

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

相关文章

Python获取某乎问答区计算机专业学生应聘保洁这一内容,看看为啥会有此事发生

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 不知道现在还有多少人玩知某乎&#xff0c; 今天刷话题的时候看到这么一个问答&#xff0c; 这么有趣的话题&#xff0c;咱们就对其问答内容进行采集一下&#xff1f;&#xff1f; 效果展示 可以看到&#xff0c;数据…

Linux 远程访问控制 SSH SCP SFTP TCP-Wrappers

SSH&#xff08;secure shell&#xff09;协议 一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程复制等功能。 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令 SSH客户端<-----------------网络------------------…

android 布局优化

1.绘制和布局加载原理 本文仅供个人学习记录&#xff0c;详细介绍可查看下面链接 Android布局优化&#xff0c;多套方案全面解析 布局优化的原因&#xff1a;布局嵌套过深&#xff0c;或者其他原因导致布局渲染性能不佳&#xff0c;可能会导致应用卡顿。 android绘制原理&am…

5.3 牛顿-科茨公式

学习目标&#xff1a; 理解微积分基础知识&#xff0c;例如导数和微分的概念。学习牛顿-科茨公式的推导过程。这个公式实际上是使用泰勒公式对被积函数进行展开&#xff0c;并使用微积分的基本原理进行简化得到的。学习如何使用牛顿-科茨公式进行数值积分。这通常涉及到将被积…

Ajax超详解(新手入门指南)

文章目录 1. AJAX简介2. 前后端交互3. XHR3.1 XMLHttpRequest对象3.2 获取模拟的后端数据3.3 获取网络数据3.4 使用json-server模拟服务器3.4.1 安装node.js3.4.2 安装并使用json-server 3.5 常见的请求方式3.5.1 GET请求3.5.2 POST请求3.5.3 PUT请求3.5.4 PATCH请求3.5.5 DELE…

【图像分割】Segment Anything(Meta AI)论文解读

文章目录 摘要一、引言二、segment anything任务1.任务2.预训练3.zero shot transfer4.相关任务5.讨论 三*、Segment Anything 模型四、Segment Anything 数据引擎五、Segment Anything 数据集六、Segment Anything RAI分析七、Zero-Shot Transfer 实验1.zero shot 单点有效掩模…

springboot本地local配置覆盖远程Apollo配置(含Apollo配置加载顺序说明)

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/130302692 目录 前言 Apollo配置加载顺序 步骤 第一步&#xff1a;Apollo创建properties 第二步&#xff1a;添加namespaces&…

js的dom事件流、事件委托和阻止绑定事件触发

主要讲解事件绑定和事件委托&#xff0c;onclick事件和addEventListener的区别 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…

IT项目管理计算题【太原理工大学】

计算题好像也没多少考点&#xff0c;主要就是记公式吧&#xff0c;其他的不想看了&#xff0c;直接考啥看啥&#xff0c;就看两个&#xff1a; ① 根据进度网络图写出时间参数表&#xff0c;ES、EF、LS、LF、TF 以及 FF&#xff0c;关键路径&#xff0c;总工期&#xff1b;② 挣…

volatile 保证内存变量可见性的实现原理解析

目录 volatile 的定义 可见性问题 JMM&#xff08;JavaMemoryModel&#xff09; 保证可见性 现代计算机的内存模型 MESI&#xff08;缓存一致性协议&#xff09; 嗅探 总线风暴 volatile 的两条实现原则 volatile 的定义 Java代码在编译后会编程 Java …

GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作

写在前面 本文主要针对使用GD&#xff08;兆易创新&#xff09;系列的FLASH做启动配置片时&#xff0c;遇到的相关问题进行简单整理复盘&#xff0c;避免后人踩坑。 本人操作固化芯片型号为&#xff1a;ZYNQ7045、690T&#xff08;复旦微替代型号V7 690T&#xff09;。 7系列…

02-waf绕过漏洞发现之代理池指纹被动探针

WAF绕过-漏洞发现之代理池指纹被动探针 思维导图 漏洞发现触发WAF点-针对xray工具&#xff0c;awvs工具等 1.扫描速度&#xff08;绕过方法&#xff1a;代理池&#xff0c;延迟&#xff0c;爬虫白名单&#xff09;2.工具指纹&#xff08;绕过方法&#xff1a;特征指纹&#x…

Qt Quick - Container

Qt Quick - Container使用总结 一、概述二、使用容器三、管理当前索引四、容器实现 一、概述 Container 提供容器通用功能的抽象基类。Container是类容器用户界面控件的基本类型&#xff0c;允许动态插入和删除Item。DialogButtonBox, MenuBar, SwipeView, 和 TabBar 都是继承…

测试工程师为什么要关注研发效能?

研发效能中的“研发”&#xff0c;指的是广义的研发团队&#xff0c;包含开发、测试、和研发团队内部的产品经理&#xff08;不包含业务部门的产品经理&#xff09;。测试工程师身处其中&#xff0c;作为研发团队的一员&#xff0c;对于整体的效能如何提升也应该了然于胸。这篇…

【论文写作】如何写科技论文?万能模板!!!(以IEEE会议论文为例)

0. 写在前面 常言道&#xff0c;科技论文犹如“八股文”&#xff0c;有固定的写作模式。本篇博客主要是针对工程方面的论文的结构以及写作链条的一些整理&#xff0c;并不是为了提高或者润色一篇论文的表达。基本上所有的论文&#xff0c;都需要先构思好一些点子&#xff0c;有…

「计算机控制系统」5. 模拟设计法

模拟控制器的离散化 数字PID控制器 Smith预估控制 文章目录 模拟控制器的离散化数值积分法一阶后向差分法一阶前向差分法双线性变换法&#xff08;Tustin&#xff09; 零极点匹配法其他方法 数字PID控制器模拟PID控制器的离散化数字PID的改进PID控制各环节的作用PID参数的整定扩…

win11删除的文件不在回收站原因及找回文件方法

win11是微软最新推出的操作系统&#xff0c;它的外观和功能都有所升级。但是&#xff0c;在使用win11的过程中&#xff0c;有时候你会误删一些重要的文件&#xff0c;而这些文件并没有进入回收站&#xff0c;这该怎么办呢&#xff1f;win11删除的文件不在回收站怎么找回&#x…

[强化学习]学习路线和关键词拾零

强化学习学习方法和路线 学习路线 先从基础教材开始&#xff0c;构建RL的知识框架&#xff0c;熟悉关键名词和公式推导&#xff0c;扩展到Model-Free的Value-Based和Policy-Based方法&#xff0c;同时参考github的代码练习。接下来精读几篇经典论文&#xff0c;如DQN,PPO等。…

Node内置模块 【压缩zlib模块】

文章目录 &#x1f31f;前言&#x1f31f;zlib模块&#x1f31f;关于gzip与deflate&#x1f31f;使用zlib&#x1f31f;压缩与解压缩&#x1f31f;案例&#xff1a;压缩&#x1f31f;案例&#xff1a;解压缩 &#x1f31f;服务端gzip压缩&#x1f31f;HTTP配置&#x1f31f;HTT…

Android Binder图文详解和驱动源码分析

文章目录 前言一、跨进程通讯的过程1. AIDL客户端代码2. AIDL服务端代码3. 通信过程a. 发送请求时序图b. 接收请求时序图 二、Binder一次拷贝1. 发送给Binder驱动的数据2. 一次拷贝示意图 三、Binder驱动源码1. 相关数据结构2. 阅读Binder驱动源码 参考 前言 最近在学习Binder…