Redis List类型

列表类型是用来存储多个有序的字符串,如图所示,a、b、c、d、e 五个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素 (element),一个列表最多可以存储2的32次方 -1个元素。在 Redis 中,可以对列表两端插入(push)和弹出 (pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。

列表两端插入和弹出操作

在这里插入图片描述

列表的获取、删除等操作

在这里插入图片描述

列表类型的特点

  1. 列表中的元素是有序的,这意味着可以通过索引下标获取某个元素或者某个范围的元素列表,例如要获取下图的第5个元素,可以执行lindex user:1:messages 4 或者倒数第1个元素,lindexuser:1:messages-1就可以得到元素e。
  2. 区分获取和删除的区别,例如图中的rem 1b 是从列表中把从左数遇到的前1个b元素删除,这个操作会导致列表的长度从5变成4;但是执行 index4 只会获取元素,但列表长度是不会变化的。
  3. 列表中的元素是允许重复的,例如图中的列表中是包含了两个a元素的。

列表中允许有重复元素

在这里插入图片描述

命令

lpush

将一个或多个值插入到 Redis 列表的头部。如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。

语法

LPUSH key value1 [value2 ...]
  • key 是列表的名字。
  • value1 是要插入的值。可以同时指定多个值,Redis 会从左到右的顺序将它们插入到列表的头部。

时间复杂度:只插入一个元素为 O(1),插入多个元素为 O(N),N 为插入元素个数

返回值:返回列表的长度。

示例

127.0.0.1:6379> lpush mylist "world"
(integer) 1
127.0.0.1:6379> lpush mylist "hello"
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"

lpushx

在 key 存在时,将一个或者多个元素从左侧放入(头插)到 list 中。不存在,直接返回

语法

LPUSHX key value1 [value2 ...]

时间复杂度:只插入一个元素为 O(1),插入多个元素为 O(N),N 为插入元素个数

返回值:插入后 list 的长度。

示例

127.0.0.1:6379> lpush mylist "World"
(integer) 1
127.0.0.1:6379> lpushx mylist "Hello"
(integer) 2
127.0.0.1:6379> lpushx myotherlist "Hello"
(integer) 0
127.0.0.1:6379> lrange mylist 0 -1
1) "Hello"
2) "World"
127.0.0.1:6379> lrange myotherlist 0 -1
(empty array)

rpush

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

语法

RPUSH key value [value ...]

时间复杂度:只插入一个元素为 O(1),插入多个元素为 O(N),N 为插入元素个数

返回值:插入后 list的长度

示例

127.0.0.1:6379> rpush mylist "world"
(integer) 1
127.0.0.1:6379> rpush mylist "hello"
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
2) "hello"

rpushx

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

语法

RPUSHX key value1 [value2 ...]

时间复杂度:只插入一个元素为 O(1),插入多个元素为 O(N),N 为插入元素个数

返回值:插入后 list 的长度。

示例

127.0.0.1:6379> rpush mylist "World"
(integer) 1
127.0.0.1:6379> rpushx mylist "Hello"
(integer) 2
127.0.0.1:6379> rpushx myotherlist "Hello"
(integer) 0
127.0.0.1:6379> lrange mylist 0 -1
1) "World"
2) "Hello"
127.0.0.1:6379> lrange myotherlist 0 -1
(empty array)

lrange

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

语法

LRANGE key start stop

时间复杂度:O(N)

返回值:指定区间的元素。

示例

127.0.0.1:6379> rpush mylist "one"
(integer) 1
127.0.0.1:6379> rpush mylist "two"
(integer) 2
127.0.0.1:6379> rpush mylist "three"
(integer) 3
127.0.0.1:6379> lrange mylist 0 0
1) "one"
127.0.0.1:6379> lrange mylist -3 2
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> lrange mylist -100 100
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> lrange mylist 5 10
(empty array)

lpop

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

语法

LPOP key

时间复杂度:O(1)

返回值:取出的元素或者 nil。

示例

127.0.0.1:6379> rpush mylist "one" "two" "three" "four" "five"
(integer) 5
127.0.0.1:6379> lpop mylist
"one"
127.0.0.1:6379> lpop mylist
"two"
127.0.0.1:6379> lpop mylist
"three"
127.0.0.1:6379> lrange mylist 0 -1
1) "four"
2) "five"

rpop

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

语法

RPOP key

时间复杂度:O(1)

返回值:取出的元素或者 nil。

示例

127.0.0.1:6379> rpush mylist "one" "two" "three" "four" "five"
(integer) 5
127.0.0.1:6379> rpop mylist
"five"
127.0.0.1:6379> lrange mylist 0 -1
1) "one"
2) "two"
3) "three"
4) "four"

lindex

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

语法

LINDEX key index

时间复杂度:O(N)

返回值:取出的元素或者 nil。

示例

127.0.0.1:6379> lpush mylist "World"
(integer) 1
127.0.0.1:6379> lpush mylist "Hello"
(integer) 2
127.0.0.1:6379> lindex mylist 0
"Hello"
127.0.0.1:6379> lindex mylist -1
"World"
127.0.0.1:6379> lindex mylist 3
(nil)

linsert

在特定位置插入元素。

语法

LINSERT key BEFORE|AFTER pivot value

这里:

  • key 是列表的键名。
  • BEFOREAFTER 是插入位置选项,用于指定新值是插在参考值的前面还是后面。
  • pivot 是列表中的现有值,新值会插入到这个值的前面或后面。
  • value 是要插入的新值。

时间复杂度:O(N)

返回值:插入后的 list 长度。

示例

127.0.0.1:6379> rpush mylist "Hello"
(integer) 1
127.0.0.1:6379> rpush mylist "World"
(integer) 2
127.0.0.1:6379> linsert mylist before "World" "There"
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "Hello"
2) "There"
3) "World"

llen

获取 list 长度

语法

LLEN key

时间复杂度:O(1)

返回值:list 的长度。

示例

127.0.0.1:6379> lpush mylist "World"
(integer) 1
127.0.0.1:6379> lpush mylist "Hello"
(integer) 2
127.0.0.1:6379> llen mylist
(integer) 2

阻塞版本命令

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

  • 在列表中有元素的情况下,阻塞和非阻塞表现是一致的。但如果列表中没有元素,非阻塞版本会理解返回nil,但阻塞版本会根据timeout,阻塞一段时间,期间 Redis 可以执行其他命令,但要求执行该命令的客户端会表现为阻塞状态。
  • 命令中如果设置了多个键,那么会从左向右进行遍历键,一旦有一个键对应的列表中可以弹出元素,命令立即返回。
  • 如果多个客户端同时多一个键执行 pop,则最先执行命令的客户端会得到弹出的元素。

阻塞版本的 blpop 和 非阻塞版本 lpop 的区别

在这里插入图片描述

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

blpop

语法

BLPOP key [key ...] timeout

时间复杂度:O(1)

返回值:取出的元素或者 nil。

示例

127.0.0.1:6379> blpop list1 0
1) "list1"
2) "a"
127.0.0.1:6379> blpop list1 60
1) "list1"
2) "b"
127.0.0.1:6379> blpop list1 60
1) "list1"
2) "c"
#开启另一个终端
127.0.0.1:6379> lpush list1 d
(integer) 1
#原来终端
127.0.0.1:6379> blpop list1 60
1) "list1"
2) "d"
(14.63s)

brpop

语法

BRPOP key [key ...] timeout

时间复杂度:O(1)

返回值:取出的元素或者 nil。

示例

127.0.0.1:6379> del list1
(integer) 0
127.0.0.1:6379> rpush list1 a b c
(integer) 3
127.0.0.1:6379> brpop list1 60
1) "list1"
2) "c"
127.0.0.1:6379> brpop list1 60
1) "list1"
2) "b"
127.0.0.1:6379> brpop list1 60
1) "list1"
2) "a"
#另一个终端运行
127.0.0.1:6379> lpush list1 d
(integer) 1
#原来终端
127.0.0.1:6379> brpop list1 60
1) "list1"
2) "d"
(7.83s)

内部编码

list 类型的内部编码有两种:

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

1)当元素个数较少且没有大元素时,内部编码为 ziplist:

127.0.0.1:6379> rpush listkey e1 e2 e3
(integer) 3
127.0.0.1:6379> object encoding listkey
"ziplist"

2)当元素个数超过 512 时,内部编码为 linkedlist:

127.0.0.1:6379> rpush listkey e1 e2 e3 ... 省略 e512 e513
OK
127.0.0.1:6379> object encoding listkey
"linkedlist"

3)当某个元素的长度超过 64 字节时,内部编码为 linkedlist:

127.0.0.1:6379> rpush listkey "one string is bigger than 64 bytes ... 省略 ..."
OK
127.0.0.1:6379> object encoding listkey
"linkedlist"

使用场景

消息队列

Redis 可以使用 lpush + brpop 命令组合实现经典的阻塞式生产者-消费者模型队列, 生产者客户端使用 lpush 从列表左侧插⼊元素,多个消费者客户端使用 brpop 命令阻塞式地从队列中 “争抢” 队首元素。通过多个客户端来保证消费的负载均衡和高可用性。

Redis 阻塞消息队列模型

在这里插入图片描述

分频道的消息队列

Redis 同样使用 lpush + brpop 命令,但通过不同的键模拟频道的概念,不同的消费者可以通过 brpop 不同的键值,实现订阅不同频道的理念。

Redis 分频道阻塞消息队列模型

在这里插入图片描述

微博 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::mblogs 作为微博的键:

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

3)分页获取用户的 Timeline,例如获取用户 1 的前 10 篇微博:

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

此方案在实际中可能存在两个问题:

  • 1+n 问题。即如果每次分页获取的微博个数较多,需要执行多次 hgetall 操作,此时可以考虑使用 pipeline (流水线)模式批量提交命令,或者微博不采用哈希类型,而是使用序列化的字符串类型,使用 mget 获取。
  • 分裂获取文章时,lrange 在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分。

选择列表类型时,请参考

同侧存取(lpush + lpop 或者 rpush + rpop)为栈
异侧存取(lpush + rpop 或者 rpush + lpop)为队列

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于松鼠算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于松鼠算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于松鼠算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.松鼠算法4.实验参数设定5.算法结果6.参考文献7.MA…

虚幻学习笔记14—重叠和碰撞事件

一、前言 在开发应用当中两个物体的重叠和碰撞事件会经常用到,在虚幻中哲两个有很大的区别,在官方文档碰撞概述其实已经讲了怎样发生碰撞和重叠,但是还是遗漏不少注意事项合细节,主要文档写的太粗糙了,这也让我在使用的…

CSS的三大特性(层叠性、继承性、优先级---------很重要)

CSS 有三个非常重要的三个特性:层叠性、继承性、优先级。 层叠性 场景:相同选择器给设置相同的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式。层叠性主要解决样式冲突 的问题 原则:  样式冲突&am…

【JAVA日志框架】JUL,JDK原生日志框架详解。

前言 Java日志体系混乱?Java日志框架系列,清晰简洁整理好整个Java的日志框架体系。第一篇,JDK原生日志框架——JUL。 目录 1.概述 2.日志级别 3.配置 4.继承关系 1.概述 日志框架的核心问题: 日志是用来记录应用的一些运行…

uniapp实现检查版本检测,更新

1.首先需要获取当前app的版本 const systemInfo uni.getSystemInfoSync();// 应用程序版本号// #ifdef APPme.version systemInfo.appWgtVersion;// #endif// #ifdef H5me.version systemInfo.appVersion;// #endif2.在获取到服务器保存的app版本 3.点击按钮验证版本号 //…

Docker单机部署OceanBase

文章目录 说明机器软硬件要求指导文档本次部署环境说明 OceanBase单机部署(Docker)一:拉取 OceanBase 数据库相关镜像二:启动 OceanBase 数据库实例完整启动日志展示 三:连接实例遇到报错:没有mysql客户端 …

关联规则 python实现Apriori算法

python实现Apriori算法 根据我们上个博客的例子 def load_dataset():# 载入数据集的函数dataset [[A, , D],[B, C, E],[A, B, C, E],[B, E]]return datasetdef create_candidates(dataset):# 生成1项集的候选集函数candidates []for transaction in dataset:for item in t…

电子学会C/C++编程等级考试2021年06月(六级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:逆波兰表达式 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* +…

Java 数据结构篇-实现堆的核心方法与堆的应用(实现 TOP-K 问题:最小 k 个数)

文章目录 1.0 堆的说明 2.0 堆的成员变量及其构造方法 3.0 实现堆的核心方法 3.1 实现堆的核心方法 - 获取堆顶元素 peek() 3.2 实现堆的核心方法 - 下潜 down(int i) 3.3 实现堆的核心方法 - 交换元素 swap(int i,int j) 3.4 实现堆核心方法 - 删除堆顶元素 poll() 3.5 实现堆…

论文阅读——Semantic-SAM

Semantic-SAM可以做什么: 整合了七个数据集: 一般的分割数据集,目标级别分割数据集:MSCOCO, Objects365, ADE20k 部分分割数据集:PASCAL Part, PACO, PartImagenet, and SA-1B The datasets are SA-1B, COCO panopt…

第15章 《乐趣》Page305~311, 代码精简以后,讨论一下引用含义的问题

将Page305~311的代码精简了一下&#xff0c;讨论一下引用含义的问题&#xff0c;精简之后的代码如下&#xff1a; #include <iostream> #include <SDL2/SDL.h>using namespace std;namespace sdl2 {char const* last_error() {return SDL_GetError(); }struct Ini…

10 新字符设备驱动文件

一、新字符设备驱动原理 因为 register_chrdev 和 unregister_chrdev 两个函数是老版本驱动文件&#xff0c;现在可以用新字符设备驱动 API 函数。 1. 分配和和释放设备号 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可&#xff0c;但是这样会带来两…

pytest之allure测试报告03:allure动态自定义报告

1、测试用例模块中引入allure&#xff1a;import allure 2、yaml文件中定义添加title、story的值&#xff1a; 3、测试用例中读取调用。eg:allure.dynamic.title() 4、运行报告查看&#xff1a;成功动态展示yaml文件中配置的story、title

【Spark精讲】Spark内存管理

目录 前言 Java内存管理 Java运行时数据区 Java堆 新生代与老年代 永久代 元空间 垃圾回收机制 JVM GC的类型和策略 Minor GC Major GC 分代GC Full GC Minor GC 和 Full GC区别 Executor内存管理 内存类型 堆内内存 堆外内存 内存管理模式 静态内存管理 …

时序预测 | Python实现LSTM电力需求预测

时序预测 | Python实现LSTM电力需求预测 目录 时序预测 | Python实现LSTM电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前最先进的行业预测进行比较。使用…

git代码管理学习文档

1.版本控制 每一版本都会发生变化 更新版本&#xff0c;回退版本 版本控制实际就是控制文件的变化 服务器端和每个人的电脑上都会记录版本的变化&#xff0c;也就是说整个团队都记录了版本的变化。 不需要连网&#xff0c;他是分布式的&#xff0c;在自己电脑上也可以操作。 …

Docker构建镜像时空间不足:/var/lib/docker,no space left on device

背景 在一次更新业务服务功能后&#xff0c;重新在服务器上构建微服务镜像&#xff0c;在构建镜像时报错空间不足&#xff1a; /var/lib/docker, no space left on device 赶紧用 df -h 看了下磁盘使用情况&#xff0c;果然&#xff0c; devicemapper 已经满了。。由于需要紧急…

Python+Requests+Pytest+YAML+Allure实现接口自动化

本项目实现接口自动化的技术选型&#xff1a;PythonRequestsPytestYAMLAllure &#xff0c;主要是针对之前开发的一个接口项目来进行学习&#xff0c;通过 PythonRequests 来发送和处理HTTP协议的请求接口&#xff0c;使用 Pytest 作为测试执行器&#xff0c;使用 YAML 来管理测…

【halcon深度学习】目标检测的数据准备过程中的一个库函数determine_dl_model_detection_param

determine_dl_model_detection_param “determine_dl_model_detection_param” 直译为 “确定深度学习模型检测参数”。 这个过程会自动针对给定数据集估算模型的某些高级参数&#xff0c;强烈建议使用这一过程来优化训练和推断性能。 过程签名 determine_dl_model_detection…

智能优化算法应用:基于秃鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于秃鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于秃鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.秃鹰算法4.实验参数设定5.算法结果6.参考文献7.MA…