深入学习 Redis - 深挖经典数据类型之 list

目录

前言

一、list 类型

1.1、操作命令

lpush / rpush(插入元素)

lrange(查看范围元素)

lpushx / rpushx (有约束的插入)

lpop / rpop(头删尾删)

lindex(获取下标元素)

llen(长度)

lrem(删除指定元素)

ltrim(保留区间)

lset (根据下标修改元素)

blpop / brpop(阻塞删除)

1.2、内部编码方式

1.3、使用场景

表示多表之间的关联关系

一般消息对列

频道(多列表)消息队列

微博列表


前言


redis 中所有的 key 都是字符串,value 的类型是存在差异的,因此出现了操控不同 value 的命令,接下来,就一起来学习一下吧~

Ps1:接下来,我给出的指令都是按照 Redis 官方文档的语法格式来解析的,[ ] 相当于一个独立的单元,表示可选项(可有可无),其中 | 表示 “或者” 的意思,多个只能出现一个,[ ] 和 [ ] 之间是可以同时存在的.

Ps2:一个快速失去年终奖的小技巧 —— 清除 redis 上所有的数据 =》 FLUSHALL,这个操作可以把 redis 上所有的键值对全部带走.

一、list 类型


1.1、操作命令

 list 的内部结构类似于 “双端队列”(deque),元素是有序的,并且允许元素重复,因此头插和尾插的效率很高,可以当作一个 栈 / 队列 来使用,约定最左侧元素下标是 0,并且是是支持负数下标.

Redis 早期作为消息队列就是通过 List 来实现的,后面又提供了一种 stream 这种功能更加强大的类型来实现.

Ps:"有序" 的含义一定要根据上下文来区分,有的时候谈到有序指的是 “升序” 和 “降序” ,有的时候,指的是顺序很关键(如果把元素位置颠倒,顺序调换,那么新的 list 和之前的 list 是不对等的)~

就像面试的时候问你谈谈对 “栈 / 堆” 的理解,那么一定不要一上来就回答,而是要问清楚,到底是问数据结构中的,还是操作系统中的,还是 JVM 中.

lpush / rpush(插入元素)

lpush 和 rpush 都是用来插入元素的,分别是从左右两侧插入元素,一次可以一个或多个,例如插入 1 2 3 4 ,按照顺序使用 lpush 插入,插入完毕后,4 就是开头元素.(时间复杂度 O(1))

LPUSH key element [element ...]

lrange(查看范围元素)

查看 list 中指定范围的元素,区间为 闭区间(Redis 中的区间都是 闭区间),同样支持负数下标.

LRANGE key start stop

 Ps:Redis 中使用 lrange 如果下标超出范围,不会像 java 那样抛出异常,而是尽可能的获取到对应内容(有多少获取多少,超出的不管)

lpushx / rpushx (有约束的插入)

lpushx 表示有约束的从左侧插入一个或多个元素,只有当 key 存在时,才能将元素插入成功,不存在则插入失败,返回值为插入元素的个数(返回 0 表示插入失败).

rpushx 与 lpushx 同理,rpushx 只是从右侧插入元素.

LPUSHX key element [element ...]

 

lpop / rpop(头删尾删)

lpop 表示从最左侧删除一个元素. 

rpop 同理,从右侧删除一个元素.

LPOP key

Ps:在 redis 6.2 之后新增了一个 count 参数, count 就描述了这次要删除的元素个数.

Ps:Redis 中 list 是一个双端队列,从两头插入 / 删除元素 都是非常高效的,因此

搭配使用 rpush 和 lpop ,就相当于队列.

搭配使用 rpush 和 rpop ,就相当于栈.  

lindex(获取下标元素)

获取给定下标的对应元素,时间复杂度为 O(N),此处的 N 指的是 list 中元素个数.

LINDEX key index

 Ps:如果下标非法,返回 nil.

llen(长度)

获取 list 元素个数.

LLEN key

 

lrem(删除指定元素)

用来删除指定元素,并可以根据 count 来指定删除元素(element)的个数(list 中允许出现重复元素).

LREM key count element

当 count > 0 时,从最左侧删除元素 count 个 element 的元素

当 count < 0 时,从最右侧删除元素 count 个 element 的元素

当 count = 0 时,删除所有的 element 元素.

 

ltrim(保留区间)

LTRIM key start stop

保留 start 到 stop 之间的元素(闭区间,并且删除 闭区间 之外的所有元素)

 Redis 的官方文档中还给出了访问控制列表(redis 6 及以上版本支持),acl 就是给每一个命令都打上标签,这样管理员就可以给每一个 redis 用户配置不同的权限(允许该用户可以执行哪些命令).这不是一个知识点,只是用到的时候查一下配置怎么写.

lset (根据下标修改元素)

用来根据指定下标修改元素,处理的时间复杂度为 O(N).

LSET key index element

 

Ps:这里不会像 lindex 那样下标越界能很好的处理,lset 下标越界就会报错.

blpop / brpop(阻塞删除)

这类似于阻塞队列(BlockingQueue)实现生产者消费者模型,阻塞就表示当前的线程不再往后执行了,满足一定条件以后才被唤醒.

在 redis 中的 list 只支持 "队列为空" 的情况,不考虑 "队列满",具体规则如下:

  1. 如果 list 中 存在元素, blpop 和 brpop 就和 lpop 以及 rpop 作用完全相同.
  2. 如果 list 中为空,blpop 和 brpop 就会产生阻塞,一直阻塞到队列不为空为止.
  3. 可以显式设置阻塞时间,并且阻塞期间可以执行其他命令(阻塞期间并不会对 redis 服务器产生负面影响).
  4. 命令中若设置了多个键,那么会从左向右进行遍历,一旦有一个键对应列表中可以弹出的元素,命令立即返回.
  5. 如果有多个客户端同时执行 blpop,则先执行命令的客户端得到弹出的元素((这就像是有一个女神,但是有多个屌丝去追,当女神有空了以后,哪个先约的,哪个人就能先约到女神).

blpop 和 brpop 两个阻塞命令,主要用途就是用来做 "消息队列",但是这两命令的功能还是比较有限的(实现消息队列我们一般不用 redis).

BLPOP key [key ...] timeout

Ps:此处的超时时间,单位是 秒(redis 5), redis 6 超时时间允许设置成小数.

1.针对一个空队列进行操作,就阻塞住了~

2.再开启一个 redis 客户端,向 key1 中再塞一个元素阻塞就解除了.

 

针对多个 key 进行操作,哪个 key 先放入元素,就取哪个~

 

1.2、内部编码方式

在 redis 早期的版本中,有以下两种编码方式:

  1. linkedlist:双向链表,当一个 list 包含了数量比较多的元素,又或者 list 中包含的元素都是比较长的字符串时,Redis就会使用 linkedlist 作为 list 的底层实现。
  2. ziplist:压缩列表,当哈希表里的元素比较少的时候,就优化成了 ziplist 了,能够节省空间(压缩的原因:redis 上有很多 key,可能某些 key 的 value 是 hash,此时如果 key 特别多,对应的 hash 也特别多,但是每个 hash 又不是特别大的情况下,就尽量去压缩,让整体占用内存更小了);
     

现在的 redis 中 list 内部编码为 quicklist,包含了以上两种编码方式的有优点.

quick 相当于是 链表 和 压缩列表 的结合,整体还是一个双向链表,链表的每一个节点是一个压缩列表(控制链表每个节点不能过大).

之前的 list-max-ziplist-entries 配置 和 list-max-ziplist-value 都不在使用了,现在使用的配置是 list-max-ziplist-size .

1.3、使用场景

表示多表之间的关联关系

可以将 list 作为 "数组" 这样的结构来存储多个元素,例如现在有学生和班级两张表,使用 hash + list 的方式就可以将 学生和班级信息关联起来.

一般消息对列

通过 blpop / brpop 就可以实现生产者消费者模型.

当有多个消费者时,谁先执行 brpop 命令,谁就能先拿到元素,像这样的设定,就能构成一个 “轮询” 的效果~  

假设消费者执行顺序执行的顺序是1、2、3,当新的元素到来的时候,消费者1 就可以先拿到元素,之后 消费者1 还想继续消费,就需要重新执行 brpop ,执行后就意味 消费者1 的执行顺序被排到了最后,之后每个消费者都依次轮询...

频道(多列表)消息队列

多列表这种场景也是很常见的,例如抖音这个软件,一个通道来了可以传输短视频、另一个通道来了,可以传输弹幕、还有...这样多个通道就实现了解耦操作,互不干扰.

 

微博列表

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

分页获取用户用户前 10 个文章伪代码,如下:

keylist = lrange user:1:mblogs 0 9

for key in keylist {
 hgetall key
}

每一页有多少数据是不确定的,有可能触发很多 hgetall 操作,导致过多的网路请求

正确的解决办法就是分流水线去做,假设某个用户发了 1w 个微博,长度就是 1w ,我们就可以把中 1w 数据拆成 10 份,每个就是 1k .

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实现锂电池形状的数据可视化css+js

1.效果图 2.需求根据后端返回数据改变里面的高度 HTML&#xff1a; <div class"dianchichi"><div class"limian" id"divElementId"></div></div> css: .dianchichi {width: 84px;height: 146px;display: flex;justify-…

【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 还整了一个如何相互之间调用函数的文章&#xff0c;感兴趣可以看&#xff1a;【Visual Studio】Qt 在其他 cpp 文件中调用主工程下文件中的函数。 文章目录 …

react 实现小球加入购物车动画

代码 import React, { useRef } from react;const ProductLayout () > {const box useRef(null);const createBall (left, top) > {const ball document.createElement(div);ball.style.position absolute;ball.style.left left - 10 px;ball.style.top top - 1…

四个现实中的商品样例,帮助你理解如何使用css【前端CSS入门样例】

实现商品列表 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>商品列表图片</title><style>.row > img {width: 15%;}</style></head><body><div class"row"><img sr…

C/C++ 程序 IDE 开发工具 CLion

下载地址&#xff1a; https://www.jetbrains.com/clion/ https://www.jetbrains.com/clion/ 下载地址&#xff1a; https://www.jetbrains.com/clion/download/ https://www.jetbrains.com/clion/download/ 历史版本&#xff08;老版本&#xff09;下载地址&#xff1a; h…

计算机科学cs/电子信息ei面试准备——python复习|理解题|简答题

目录 1 请简要概述python技术的主要应用场景? 2 python的基本数据类型是那几种? 3 python数组和列表有什么区别? 4 Python中的函数是什么&#xff1f; 5 请写出删除列表中的元素有几种方式? 6 描述python函数中递归的理解? 7 请介绍join()和split()的区别? 8 介绍…

每天五分钟机器学习:多项式非线性回归模型

本文重点 在前面的课程中,我们学习了线性回归模型和非线性回归模型的区别和联系。多项式非线性回归模型是一种用于拟合非线性数据的回归模型。与线性回归模型不同,多项式非线性回归模型可以通过增加多项式的次数来适应更复杂的数据模式。在本文中,我们将介绍多项式非线性回…

dpdpdp

这里写目录标题 139. 单词拆分322. 零钱兑换300. 最长递增子序列120. 三角形最小路径和64. 最小路径和63. 不同路径 II5. 最长回文子串&#xff08;回文dp&#xff09;⭐97. 交错字符串⭐&#xff08;抽象成路径问题&#xff09;221. 最大正方形⭐ 139. 单词拆分 class Soluti…

文心千帆为你而来

1. 前言 3月16号百度率先发布了国内第一个人工智能大语言模型—文心一言。文心一言的发布在业界引起了不小的震动。而文心一言的企业服务则由文心千帆大模型平台提供。文心千帆大模型平台是百度智能云打造出来的一站式大模型开发与应用平台&#xff0c;提供包括文心一言在内的…

Observability:Synthetic monitoring - 动手实践

在我之前的如下文章里&#xff1a; Observability&#xff1a;Synthetic monitoring - 合成监测入门&#xff08;一&#xff09;&#xff08;二&#xff09; Observability&#xff1a;Synthetic monitoring - 创建浏览器监测&#xff0c;配置单独的浏览器监测器及项目 我详…

408-2009

一、选择题&#xff08;2 分/题&#xff09; 1.为解决计算机主机与打印机之间速度不匹配问题&#xff0c;通常设置一个打印数据缓冲区&#xff0c;主机将要输出的数据一次写入该缓冲取&#xff0c;而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是______。 A.栈 …

【JavaEE】Servlet常用的API

目录 前言 一、HttpServlet类 1、Servlet的生命周期 ✨tomcat的两个端口 ✨设置告诉浏览器使用那种字符集解析响应 ✨Java中Unicode和utf8字符集的使用 二、HttpServletRequest类 1、获取请求的信息 2、 前端给后端传递数据的三种方式 2.1、通过query string传递 2.2…

【云原生】Prometheus 监控系统的初步了解与系统搭建

前言 promethues是一个开源的系统监控和报警系统&#xff0c;现在已经加入到CNCF基金会&#xff0c;成为继k8s之后第二个在CNCF托管的项目&#xff0c;在kubernetes容器管理系统中&#xff0c;通常会搭配prometheus进行监控&#xff0c;同时也支持多种exporter采集数据&#x…

S32K144 GPIO外设分析

1. S32K144 GPIO外设特性 下面的内容来自于S32K用户手册的翻译&#xff0c;或者网上关于S32K系列的一些pdf文件介绍。有些内容可能会出现理解不到位或者翻译错误方面&#xff0c;如果大家有疑问最好可以查阅用户手册。 GPIO和PORT的数量 从用户手册&#xff0c;对于PCR&#x…

【广州华锐互动】列车人员疏散VR虚拟演练系统

随着科技的不断发展&#xff0c;虚拟现实(VR)技术已经逐渐应用于各个领域。在火车站安全方面&#xff0c;为了提高旅客的安全意识和应对突发事件的能力&#xff0c;列车人员疏散VR虚拟演练系统应运而生。 列车人员疏散VR虚拟演练系统是一种基于虚拟现实技术的教育培训系统&…

15 QMessageBox消息对话框

错误提示对话框 信息提示对话框 循环对话框 默认是Yes和No&#xff0c;可以修改属性。第5个参数关联回车键 QMessageBox::Save | QMessageBox::Cancel 可以通过捕获按键获取点击结果 警告提示 代码&#xff1a; //QMessageBox 消息对话框//错误提示QMessageBox::critical(th…

老年公寓人员定位管理系统:提升安全与关怀的智能解决方案

老年公寓作为提供安全居住环境和关怀服务的重要场所&#xff0c;面临着人员管理和安全控制的挑战。为了解决这些问题&#xff0c;老年公寓人员定位管理系统应运而生。基于为提供全面的安全管理和个性化关怀服务&#xff0c;华安联大便通过老年公寓人员定位管理系统的技术原理、…

[数据结构 -- C语言] 二叉树(BinaryTree)

目录 1、树的概念及结构 1.1 树的概念 1.2 树的相关概念&#xff08;很重要&#xff09; 1.3 树的表示 2、二叉树的概念及结构 2.1 概念 2.2 特殊二叉树 2.3 二叉树的性质&#xff08;很重要&#xff09; 2.4 练习题 2.5 二叉树的存储结构 2.5.1 顺序存储 2.5.2 链…

微服务保护——Sentinel【快速入门】

一、雪崩问题&#x1f349; (一) 什么是雪崩&#x1f95d; 微服务调用链路中的某个服务故障&#xff0c;引起整个链路中的所有微服务都不可用&#xff0c;这就是雪崩。服务D故障引起服务A故障&#xff0c;服务A引起其他服务故障&#xff0c;渐渐导致所有微服务都不可用。有人…

基础算法(三)

目录 一、双指针算法 二、位运算 三、区间合并 一、双指针算法 双指针算法模板: for(int i 0,j 0;i < n;i) {while(j < i && check(i,j)) j;//每道题的具体逻辑 } 1.1两个指针指向两个队列1.2两个指针指向一个队列 案例习题: 分割字符串 #include<…