当前位置: 首页 > news >正文

Redis_8_List

List类型

在redis中,List相当于数组或者顺序表。

列表需要注意:

1、列表中的元素是有序的,注意这里的有序并不是升序降序!有序的含义需要根据上下文进行区分的~这里的有序指的是顺序很关键~~如果把元素位置颠倒,顺序调换,此时得到的新的List和之前的List是不等价的!!

同一个词,怎么理解,务必要结合上下文,,结合具体场景~~

如:堆/栈,可以是数据结构的,操作系统,JVM的~

        同步,可以是同步和互斥的同步,也可以是同步和异步的同步

2、区分获取和删除的区别

lindex能获取到元素的值,lrem也能返回被删除元素的值。

3、列表中的元素是允许重复的

像hash这样的类型,field是不能重复的。


因为当前List,头和尾都能高效地擦汗如删除元素,就可以把这个List当做一个栈/队列来使用了。Redis可以作为消息队列,最早的时候,就是通过List类型实现的,后来Redis有提供了一个stream类型。

命令

lpush

将一个或者多个元素从左侧头插入list中。

LPUSH key element [element ...]

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

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

如果key已经存在,但是key的value类型不是list,此时lpush命令就要报错~(redis中所有的这些各种类型的操作,都是类似的效果)

lrange

通过上述的lpush命令,我们已经能够插入元素了。那么我们要如何查看插入是否成功呢?

使用lrange命令查看list指定范围内的元素。

LRANGE key start stop

时间复杂度:O(N)

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

此处描述的区间也是闭区间,下标支持负数。

注意:这里的序号是专门给结果集的序号和list的下标无关!!!

可以看到,hash操作也可能会得到带有序号的结果。此处的序号仅仅是标识下返回元素的顺序,和下标无关,hash类型就没有下标的概念~~

谈到下标,往往会关注超出范围的情况~~Java中,下标超出范围,一般会抛出异常~~因为多出一步下标合法性检验~~

缺点:速度更慢        优点:出现问题及时发现。

而redis的做法:直接尽可能地获取到给定区间地元素,如果给定区间非法,比如超出下表,也会尽可能地获取对应地内容。

rpush

将一个或多个元素尾插入列表中。

RPUSH key element [element ...]

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

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

那么有人就会问了,lpush是(l是left的意思)从左侧插入,rpush(r是right的意思)从右侧插入,我们有lrange查询元素,那有没有rrange呢?

没有~这里lrange的l是list的含义,没有rrange。

rpushx

在key存在时,将一个或者多个元素从右侧放入(尾插)到list中。(这里的x是exists,存在的意思)

RPUSHX key element [element ...]

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

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

lpop

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

LPOP key

时间复杂度:O(1)。

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

rpop

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

RPOP key

时间复杂度:O(1)。

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

redis中的list是一个双端队列~~

从两头插入/删除元素都是非常高效的O(1),搭配使用rpush和lpop或者lpush和rpop,就相当于队列了;搭配使用lpush和lpop或者rpush和rpop,就相当于栈了。

lindex

给定下标,获取元素。

LINDEX key index

时间复杂度:O(N),此处的N指的是列表中元素的个数。

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

linsert

在特定位置插入元素。

LINSERT key <BEFORE | AFTER> pivot element

ps:pivot表示基准(列表中的元素),before/after表示在基准之前/后,element表示当前要插入的元素。

时间复杂度:O(N),N是列表的长度。

返回值:插入之后,得到的新list的长度。

那么问题来了,万一基准值存在多个怎么办呢?

llen

获取list的长度。

LLEN key

时间复杂度:O(1)。

返回值:list的长度。

lrem

删除指定数量的元素。

LREM key count element

ps:count:要删除的个数,element:要删除的值。

时间复杂度:O(N+M),N为列表中长度的个数,M为要删除的元素个数,可近似看为O(N)

返回值:删除的元素的个数。

count>0:从前往后删除。

count<0:从后往前删除。

count=0:删除所有的元素。

观察文档,我们会发现这一行东西:

这是啥呢?

这个叫access control list——访问控制列表(权限),是从Redis6以上才开始支持的。Redis有很多命令 ,acl这块就把每个命令都打上一些标签,打好标签之后,管理员就可以给每个redis用户配置不同的权限(运行该用户可以执行哪些标签对应的命令)。

ltrim

保留start和stop之间区间内的元素(区间外面两边的元素就直接被删除了)。

LTRIM key start stop

时间复杂度:O(N)

lset

根据下标,修改元素。

LSET key index element

时间复杂度:O(N)

blpop和brpop

这两个命令是lpop和rpop的阻塞版本,如果list中存在元素,blpop和brpop就和lpop以及rpop的作用完全相同;如果list为空blpop和brpop就会产生阻塞,一直阻塞到队列不空为止。

BLPOP key [key ...] timeout
BRPOP key [key ...] timeout

ps:timeout是超时时间,单位是秒。

这个东西就有点像我们之前讲过的阻塞队列:

多线程代码案例-2 阻塞队列_线程 包饺子-CSDN博客

使用队列来作为中间的“交易场所”,期望这个队列有两个特性:

1、线程安全

2、阻塞

  • 如果队列为空,尝试出队列,就会产生阻塞,知道队列不空,阻塞解除。
  • 如果队列为满,尝试入队列,也会产生阻塞,知道队列不满,阻塞解除

redis中的list也相当于阻塞队列一样,线程安全是通过单线程模型支持。不同的是redis阻塞只支持“队列为空”的情况,不考虑“队列满”的情况。

命令特点:

1、阻塞版本会根据timeout,阻塞一段时间,期间Redis可以执行其他的命令。因此,此处的blpop和brpop看起来好像耗时很久,但是实际上并不会对redis服务器产生负面影响!!!

2、命令中如果设置了多个键,那么会从左向右进行遍历键,一旦有一个键对应的列表中可以弹出元素,命令立即返回。通俗点说,blpop和brpop都是可以同时去获取多个key的列表的元素的~~多个key对应多个list,这多个list哪个有元素了,就会返回哪个元素。

3、如果多个客户端同时对一个key执行pop,则最先执行命令的客户端会得到弹出的元素。

小结

list的编码方式

以前,list的编码方式有两种:压缩列表和链表。list现在的编码方式只有一种:quicklist,这个quicklist相当于链表和压缩列表的组合。quicklist整体还是一个链表,链表的每个节点,是一个压缩列表。

压缩列表的缺点是当元素个数多了,操作起来效率会降低,因为每次操作元素都涉及到编码的转换。使用上述quicklist的方式,就能使每个压缩列表,都不让它太大,同时再把多个压缩列表通过链式结构连起来~~

进入配置文件,可以看到:

list类型的应用场景

1、用list作为“数组”这样的结构,来存储多个元素。

例如:

结论:使用哈希类型来表示结构化数据,如:学生、班级这样的数据,使用list来表示它们之间的关联关系。

2、使用redis作为消息队列

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

4、微博Timeline

每个用户都有属于自己的Timeline(微博列表),现需要分页展示文章列表。此时可以考虑使用列表,同时支持按照索引范围获取元素。
1、每篇微博使用哈希结构存储,例如微博中的三个属性: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

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

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

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

1、1+n问题。如果每次分页获取的微博个数较多,需要执行多次hgetall操作,此时可以考虑使用pipeline(流水线)模式(将这多次hgetall命令打包成一次)批量提交命令,或者微博不采用哈希类型,而是使用序列字符串类型,使用mget获取。

2、分裂获取文章时,lrange在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分。

​​​​​​​

http://www.dtcms.com/a/585623.html

相关文章:

  • excel VBA应用
  • 第十六章 SDN与NFV概述
  • C++ STL:阅读list源码|list类模拟|优化构造|优化const迭代器|优化迭代器模板|附源码
  • 《uni-app跨平台开发完全指南》- 05 - 基础组件使用
  • 公司网页网站建设 ppt网站前置审批类型
  • Macom将生产HRL的GaN-on-SiC工艺
  • 从零开始写算法-栈-柱状图中最大的矩形
  • Flova.ai实战:AI视频创作平台的开发与应用指南
  • 网站推广是什么岗位济南建站网站
  • SEO入门
  • 异腾910B NPU实战:vLLM模型性能优化深度指南
  • 移动网站备案微信里的小程序占内存吗
  • easy_RSA(攻防世界)
  • 「JAVA 入门」JDK概念及作用 | JDK 的下载及安装 | 自动和手动配置环境变量 | 编译Java文件 | 运行class文件
  • AIGC首帧图尾帧图生成视频案例教程
  • Go语言流程控制
  • wix建设网站商品图片网站开发
  • 【AI-agent】LangChain开发智能体工具流程
  • 测量为什么要建站本地广东中山网站建设
  • 数据结构与算法:树上倍增与LCA
  • P1997 faebdc 的烦恼+P7764 [COCI 2016/2017 #5] Poklon(莫队)
  • Nginx请求超时
  • 基于单片机的交流功率测量仪设计与实现
  • Zookeeper实现分布式锁
  • 好看的个人网站设计专做轮胎的网站
  • VGG论文精细解读
  • 抖音自动化-实现给特定用户发私信
  • 安徽省教育基本建设学会网站查看网站被百度收录
  • LeetCode算法学习之旋转数组
  • webrtc降噪-NoiseSuppressor类源码分析与算法原理