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.mzph.cn/news/227032.shtml

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

相关文章

Linux 基本语句_15_Tcp并发服务器

原理&#xff1a; 利用父子进程。父进程接收客户端的连接请求&#xff0c;子进程处理客户端的数据处理操作&#xff0c;两者各施其职。最终实现能够多个客户端连接一个服务端的操作。 代码&#xff1a; 服务端代码&#xff1a; #include <stdio.h> #include <sys/…

【Java】猜数字小游戏

规则 游戏开始随机生成4位数字符串&#xff0c;每个数字从0到9各不相同&#xff0c;比如0123玩家10次猜数机会&#xff0c;输入4位数字符串&#xff0c;每个数字从0到9各不相同游戏判断玩家输入与所猜谜底数&#xff0c;给出结果nAnB&#xff0c;A表示位置和数字都猜对的个数&…

借着期末作业,写一个JavaWeb项目

合集传送门 要求 学生成绩管理系统设计与实现 设计一个学生成绩管理系统。根据以下功能&#xff0c;分析使用的逻辑结构和存储结构。并设计菜单&#xff0c;显示相应结果。 &#xff08;1&#xff09;录入功能&#xff1a;能够录入学生成绩&#xff08;包括&#xff1a;学号…

一个遗憾,特此纪念

这是学习笔记的第 2479篇文章 说一件有些遗憾的事情。其实今年遗憾的事情有好几件&#xff0c;这一件算是其中之一。倒不是它发生在今天&#xff0c;而是每每想起来&#xff0c;都有一种无力感和酸楚&#xff0c;索性简单写一写纪念一下。 这件事情就是放弃了读博士的想法。 在…

linux dotnet环境安装

https://dotnet.microsoft.com/en-us/download/dotnet dotnet安装 #配置.net源 rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm #安装dotnet yum install dotnet-sdk-3.1 aspnetcore-runtime-3.1

第一次数学建模赛后总结

大家好&#xff0c;这里是七七。 前些日子参加了一次数学建模比赛&#xff0c;赛后总结了一下&#xff0c;发现有很多事情是到了动手操作的时候&#xff0c;才发现问题的。总结了一下&#xff0c;有以下几点。 一、准备 在赛前准备阶段只傻傻的准备了很多学校给我们列举的数…

权重衰减(Weight Decay)

在深度学习中&#xff0c;权重衰减&#xff08;Weight Decay&#xff09;是一种常用的正则化技术&#xff0c;旨在减少模型的过拟合现象。权重衰减通过向损失函数添加一个正则化项&#xff0c;以惩罚模型中较大的权重值。 一、权重衰减 在深度学习中&#xff0c;模型的训练过程…

SQL基础:操作环境搭建

在上一节中&#xff0c;我们简单讲述了数据库和SQL的基本概念。 本节我们讲述一下环境搭建&#xff0c;为下一节讲表的基本操作做下铺垫。 环境搭建 具体到操作&#xff0c;我们就要准备一些环境了。如果不进行练习&#xff0c;我们学习的知识将很快被遗忘。 MySQL安装&…

【MySQL内置函数】

目录&#xff1a; 前言一、日期函数获取日期获取时间获取时间戳在日期上增加时间在日期上减去时间计算两个日期相差多少天当前时间案例&#xff1a;留言板 二、字符串函数查看字符串字符集字符串连接查找字符串大小写转换子串提取字符串长度字符串替换字符串比较消除左右空格案…

【话题】低代码123

目录 一、什么是低代码 二、低代码的优缺点 三、你认为低代码会替代传统编程吗&#xff1f; 四、有哪些低代码工具和框架 4.1 国外的平台 4.2 国内的平台 五、未来的软件研发 低代码&#xff0c;听着就过瘾的一个词。而且不是无代码&#xff0c;这说明&#xff0c;低代码…

计算机组成原理-函数调用的汇编表示(call和ret指令 访问栈帧 切换栈帧 传递参数和返回值)

文章目录 call指令和ret指令高级语言的函数调用x86汇编语言的函数调用call ret指令小结其他问题 如何访问栈帧函数调用栈在内存中的位置标记栈帧范围&#xff1a;EBP ESP寄存器访问栈帧数据&#xff1a;push pop指令访问栈帧数据&#xff1a;mov指令小结 如何切换栈帧函数返回时…

Spring入门

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

Toyota Programming Contest 2023#8(AtCoder Beginner Contest 333)

A - Three Threes 题目大意&#xff1a;给你一个整数n&#xff0c;将这个数n输出n次。 呃呃 B - Pentagon 题目大意&#xff1a;给你一个正五边形ABCDE&#xff0c;给你任意两条边&#xff0c;判断是否相等 主要问题要判断一下内边&#xff1a;AD&#xff0c;AC&#xff0c;…

store-sales-time-series-forecasting

首先题意为预测未来三年中的每一天中的每一家超市中的每一个商品的销售价值 目前我的思路是&#xff1a; 因为本道题目涉及多种特征&#xff0c;并且有着明确的时间线&#xff0c;并且题意也表示&#xff0c;这是一道时间预测的题目&#xff0c;那么对于该道题目我考虑使用LS…

小主机折腾记19

近一个月来折腾如下 1.购买了一个m92p&#xff0c;安装了3470t以及16g内存&#xff0c;常开&#xff0c;挂向日葵作为家中的远程控制主机&#xff1b; 2.400g2dm 安装chrome os flex到傲腾m10&#xff0c;失败&#xff0c;提示至少需要16g空间&#xff08;傲腾实际13.5左右&…

基于ssm图书商城网站的设计和开发论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本图书商城网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

Win11极速安装Tensorflow-gpu+CUDA+cudnn

文章目录 0.pip/conda换默认源1.Anacondapython虚拟环境2.安装CUDA以及cudnn 0.pip/conda换默认源 为了高效下载&#xff0c;建议先把默认源换了&#xff0c;很简单这里不再赘述。&#xff08;我用梯子&#xff0c;所以没换源&#x1f60b;&#xff09; 1.Anacondapython虚拟…

Go 语言中切片的使用和理解

切片与数组类似&#xff0c;但更强大和灵活。与数组一样&#xff0c;切片也用于在单个变量中存储相同类型的多个值。然而&#xff0c;与数组不同的是&#xff0c;切片的长度可以根据需要增长和缩小。在 Go 中&#xff0c;有几种创建切片的方法&#xff1a; 使用[]datatype{valu…

最棒的 7 款精选我的世界光影水反效果包

光影支持基础Mod下载 版本&#xff1a;1.12✔1.11.2✔1.10.2✔1.9.4✔1.8✔1.7.10✔ 下载和安装&#xff1a; GLSL Shaders Mod 或者 OptiFine 我的世界光影支持Mod可以帮助玩家提示游戏画面&#xff0c;加强你的游戏录制视频效果和实时游戏体验。有数量众多的光影效果包提供…

一文了解Tomcat

文章目录 1、Tomcat介绍2、Tomcat使用配置2.1、Tomcat下载启动2.2、Tomcat启动乱码2.3、Tomcat端口号修改 3、Tomcat项目部署4、IDEA中使用Tomcat方式 1、Tomcat介绍 什么是Tomcat ​ Tomcat是Apache软件基金会一个核心项目&#xff0c;是一个开源免费的轻量级web服务器&#x…