文章目录
前置知识
列表类型是⽤来存储多个有序的字符串,列表中的每个字符串称为元素(element),⼀个列表最多可以存储232 – 1个元素。在Redis中,可以对列表两端插⼊(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等,列表是⼀种⽐较灵活的数据结构,它可以充当栈和队列的⻆⾊,在实际开发上有很多应⽤场景
列表两端插入和弹出操作
约定最左侧元素下标是0
列表的获取、删除等操作
列表类型的特点
1.列表类型是有序的。这意味着可以通过索引下标获取某个元素或者某个范围的元素列表
2.区分获取和删除的区别:
lrem1 b
是从列表中把从左数遇到的前1个b元素删除,这个操作会导致列表的⻓度从5变成4- 但是执⾏
lindex 4
只会获取元素,但列表⻓度是不会变化的
3.列表中的元素是允许重复的
命令
LPUSH
将⼀个或者多个元素从左侧放⼊(头插)到list中 ,如果key不存在的话,会新建key
语法:LPUSH key element [element ...]
返回值:插⼊后list的⻓度 时间复杂度:只插⼊⼀个元素为O(1),插⼊多个元素为O(N),N为插⼊元素个数
LPUSHX
在key存在时,将⼀个或者多个元素从左侧放⼊(头插)到list中。不存在,直接返回
语法:LPUSHX key element [element ...]
返回值:插⼊后list的⻓度 时间复杂度:只插⼊⼀个元素为O(1),插⼊多个元素为O(N),N为插⼊元素个数
RPUSH
将⼀个或者多个元素从右侧放⼊(尾插)到list中
语法:RPUSH key element [element ...]
返回值:插⼊后list的⻓度 时间复杂度:只插⼊⼀个元素为O(1),插⼊多个元素为O(N),N为插⼊元素个数
RPUSHX
在key存在时,将⼀个或者多个元素从右侧放⼊(尾插)到list中
语法:RPUSHX key element [element ...] #此处的X => exists
返回值:插⼊后list的⻓度 时间复杂度:只插⼊⼀个元素为O(1),插⼊多个元素为O(N),N为插⼊元素个数
LRANGE
获取从start到end区间的所有元素,左闭右闭
语法:LRANGE key start stop
返回值:指定区间的元素 时间复杂度:O(N)
注意1:前面的序号是专门给结果集使用的序号,和list的下标无关
注意2:在C++当中,下标超出范围,会认为是一个未定义行为=>可能导致程序崩溃/得到一个不合法数据/得到一个看起来合法但是错误的数据/得到一个恰好符合要求的数据
- 优点:效率最高 缺点:程序员不一定能第一时间发现问题
而在redis当中:尽可能的获取到给定区间的元素,如果给定区间非法,比如超出下标,那么就会尽可能获取对应的内容
LPOP
从list左侧取出元素(即头删)
语法:LPOP key
返回值:取出的元素或者nil 时间复杂度:O(1)
RPOP
从list右侧取出元素(即尾删)
语法:RPOP key
返回值:取出的元素或者nil 时间复杂度:O(1)
LINDEX
获取从左数第index位置的元素
语法:LINDEX key index
返回值:取出的元素,如果下标非法那么返回nil 时间复杂度:O(N)
LREM
指定删除list当中的元素
语法:LREM key count value #count:要删除的个数 element:要删除的值
根据count的值不同,决定怎么删除:
-
c
o
u
n
t
>
0
count > 0
-
c
o
u
n
t
<
0
count < 0
-
c
o
u
n
t
=
0
count = 0
区分获取和删除元素的区别:
- lindex能获取元素的值,lrem也能获取被删除元素的值
LINSERT
在特定位置插⼊元素
语法:LINSERT key <BEFORE | AFTER> pivot element
返回值:插⼊后的list⻓度 时间复杂度:O(N)
- before:在element前面插入
- after:在element后面插入
注意:如果要插入的列表当中,存在多个基准值,此时会根据基准值找到对应的位置 => 从左往右找,找到第一个符合基准值的位置,然后对应的在它前面/后面插入元素
LTRIM
只保存
[
s
t
a
r
t
,
s
t
o
p
]
[start,stop]
[start,stop]之间的元素,区间之外的两边元素被删除
语法:LTRIM key start stop
LSET
根据下标修改元素,下标从0开始,可以是负数。
语法:LSET key index element
注意:如果index下标越界,那么会报错
LLEN
获取list⻓度
语法:LLEN key
返回值:list的⻓度 时间复杂度:O(1)
阻塞版本命令
blpop和brpop是lpop和rpop的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致,不同之处如下:
- 在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的。但如果列表中没有元素,⾮阻塞版本会理解返回nil,但阻塞版本会根据timeout,阻塞⼀段时间,期间Redis可以执⾏其他命令,但要求执⾏该命令的客⼾端会表现为阻塞状态
- 命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元素,命令⽴即返回
- 如果多个客⼾端同时多⼀个键执⾏pop,则最先执⾏命令的客⼾端会得到弹出的元素
BLPOP
语法:BLPOP key [key ...] timeout
返回值:取出的元素或者超时返回nil 时间复杂度:O(1)
返回的结果是一个二元组:告诉我们当前数据来自哪个key,告诉我们取到的数据是什么
BRPOP
语法:BRPOP key [key ...] timeout
返回值:取出的元素或者nil 时间复杂度:O(1)
注意:blpop和brpop都可以同时去尝试获取多个key的列表的元素,如果等待的其中一个list当中有元素,那么立马取出元素返回,不会阻塞
如果多个客户端同时对一个键执行pop,那么最先执行命令的客户端会得到弹出的元素
命令总结
内部编码
列表类型的内部编码有3种:
ziplist
(压缩列表):当列表的元素个数⼩于list-max-ziplist-entries
配置(默认512个),同时列表中每个元素的⻓度都⼩于list-max-ziplist-value
配置(默认64字节)时,Redis会选⽤ziplist
来作为列表的内部编码实现来减少内存消耗==>将数据按照更紧凑的压缩形式进行表示,但是当元素个数多了,操作起来效率会降低linkedlist
(链表):当列表类型⽆法满⾜ziplist
的条件时,Redis会使⽤linkedlist
作为列表的内部实现
quicklist
:相当于是链表和压缩列表的结合,整体还是一个链表,但是链表的每个节点是一个压缩列表,每个压缩列表都不让它太大,同时把多个压缩列表通过链式结构连接起来
测试内部编码
1)当元素个数较少且没有⼤元素时,内部编码为ziplist:
2)当元素个数超过512时,内部编码为linkedlist:
3)当某个元素的⻓度超过64字节时,内部编码为linkedlist:
使用场景
消息队列
Redis可以使⽤lpush+brpop命令组合实现经典的阻塞式⽣产者-消费者模型队列,⽣产者客⼾端使⽤lpush从列表左侧插⼊元素,多个消费者客⼾端使⽤brpop命令阻塞式地从队列中”争抢”队⾸元素。通过多个客⼾端来保证消费的负载均衡和⾼可⽤性
brpop
:阻塞操作,当列表为空的时候,会阻塞等待,直到其它客户端push了元素,谁先执行这个brpop命令,谁就可以拿到这个新来的元素,可以构成一个”轮询式”获得元素的效果。每个获取到元素的消费者都需要重新执行brpop
分频道的消息队列
Redis使⽤lpush+brpop命令,通过不同的键模拟频道的概念,不同的消费者可以通过brpop不同的键值,实现订阅不同频道的理念
比如:一个通道用于传输短视频数据,一个通道用于传输弹幕,一个通道用于传输点赞,转发,收藏数据,一个通道用于传输评论数据
搞成多个频道,就可以在某种数据发生问题的时候,不会对其他数据造成影响(解耦合)
模拟栈和队列
同侧存取(lpush+lpop或者rpush+rpop)为栈
异侧存取(lpush+rpop或者rpush+lpop)为队列
原文地址:https://blog.csdn.net/chuxinchangcun/article/details/134299167
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_51253.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!