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

Redis数据结构——list

目录

列表命令

lpush

lrange

lpushx

rpush 

rpushx 

lpop

rpop 

lindex

linsert

llen

lrem

ltrim

 lset

blpop / brpop

命令总结

编码方式


list相当于数组或者顺序表,但并不是简单的数组,更接近于C++中的"双端队列"(deque)。  

最左侧的下标是0,redis的下标支持负数下标。

从左侧删除叫lpop,右侧删除叫rpop,左侧插入叫lpush,右侧删除叫做rpush。

列表的特点

1.列表中的元素是有序的。

这里的有序指的是顺序很关键,而不是"升序"、"降序",如果把元素位置调换,那我们得到新的list和之前的list是不等价的。 

2.列表中的元素是允许重复的

hash这样的类型,field是不允许重复的,列表这里是可以重复的。

3.区分获取和删除的区别

lindex可以获取到元素的值,但不会将改值从列表中删除掉。

lrem也能返回被删除元素的值,但是该元素会从列表中删除。

4.列表的头和尾都能高效插入删除元素

因此,可以把List当做一个栈/队列来使用。

列表命令

lpush

头插,一次可以插入一个元素,也可以插入多个元素。如果写的是1 2 3 4,是先头插1在头插2、3、4,全都插入完毕后列表元素是4、3、2、1。

语法:

lpush key element [element ...]

时间复杂度:O(1)

返回值:list的长度

注意:命令必须和数据结构相匹配。

lrange

查看指定区间内的元素 ,此处的区间也是闭区间。这里的下标也是可以支持负数的。l是list的意思。

语法:

lrange key start end

如果要获取list所有元素,可以把start设成0,end设置成-1, -1可以理解成list的长度-1的下标。list长度的减去1刚好就是最后一个元素下标。

我们可以看到最后插入的8是第一个元素,此处这里前面的1)、2)是给结果集使用的序号,和下标没关系。

谈到下标,往往会关注超出范围的情况。

在C++中如果超出范围,一般可能会导致程序崩溃,也可能得到一个不合法的数据,也可能得到一个看起来合法,但是错误的数据,也有可能得到一个符合要求的数据.....。

redis中是如何处理超出范围的情况呢?如果是合法的区间,把数据拿到返回给你,如果给定区间非法,比如超出下标,会尽可能获取对应的内容。

key里面只有8个元素,合法的下标是0-7,但是我们给0-100, 虽然没有100个元素,但是你有多少元素我给你多少元素。就好比土匪拦路,土匪要100块钱,你没有100,那你就有多少钱给我多少钱。

 

lpushx

如果key存在,将一个或者多个元素头插到list中,不存在,直接返回

语法:

lpushx key element [element ...]

返回值:插入后list的长度

时间复杂度:O(1) 

上面我们已经设置了一个key,因此直接插入成功了。

key存在

key不存在

 现在不存在key3,因此返回的就是0,表示列表长度为0,我们使用lrange可以看到是空的列表,我们在用exists判断key3是否存在,结果是不存在。

rpush 

上述的lpush其实就是left push,这里的rpush就是right push。

rpush可以将一个或多个元素插入到list中。

语法:

rpush key element [element]

时间复杂度:O(1)

返回值:list的长度 

rpushx 

如果key存在进行尾插一个或者多个元素,不存在直接返回。

语法:

rpushx key element [element]

时间复杂度和返回值与lpush一样。

key存在

 

key不存在 

 

lpop

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

语法:

lpop key 

时间复杂度:O(1)

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

示例:

rpop 

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

语法:

rpop key 

时间复杂度:O(1)

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

示例:

搭配使用rpush和lpop,就相当于一个队列。

搭配使用rpush和rpop,就相当于一个栈。

lindex

给定一个下标,获取到对应的元素。

语法:

lindex key index

返回值:下标对应的元素,如果下标非法,返回nil

下标是从0开始的,并且可以支持负数。

linsert

在某个元素前面或者后面插入一个元素

语法:

linsert key before | after pivot element

 before和after只能出现一个,before是往基准元素(pivot)的前面插入一个元素element。

往基准元素前插入一个元素

往基准元素后插入一个元素: 

如果给一个不存在的基准值会发生什么情况?会返回-1,表示插入失败。 

下面例子中明明不存在77,非要往77前面插入99,当然失败了。

如果基准值存在多个,怎么处理呢?很简单,插入操作相当于遍历列表,如果找到了第一次出现的基准元素那就插入在它的前/后面。

返回值:插入后的列表元素个数

llen

返回列表元素个数,如果列表不存在返回0

语法:

llen key

lrem

rem =>  remov,删除的意思。

我们用lrem对下面这组数据进行操作。下面的列表中就是插入了4组1、2、3、4。

语法:

lrem key count element

count:要删除的个数。

element:要删除的值。 

如果count大于0,从左往右删除element,删除count个。

下面图我们可以看到头部的1没了,第二组的1也没了。lrem  key 2 1的意思是删除2个元素1,从左往右删。

如果count小于0,从右往左删除element,删除count个。

我们使用flushall命令清除所有的key,然后在rpush四组1、2、3、4,恢复一下数据。

此时我们使用lrem key -2 1命令,意思是删除元素1,删除2个,从右往左删。

如果count等于0,删除所有的element。

下面尾插四组1234,然后lrem key 0  1,表示列表中所有的1都被删了。

返回值:删除了多少个元素

ltrim

保留start到stop之间内的元素,区间外面两边的都被删了。区间也是闭区间。start和stop是下标。

语法:

ltrim key start stop

可以看到,下标2-5之间的元素多存在,其它的元素都没了。 

 

 lset

根据下标修改元素。

语法:

lset key index element

下面是将下标为2的元素5修改为99。 

 

此处如果给的index超出范围,会直接越界报错。 

blpop / brpop

阻塞:当前线程不走了,代码不继续执行了,会在满足一定的条件之后,被唤醒。

blpop和brpop的b就是block阻塞。

redis中的list的阻塞,只支持"队列为空"的情况。

阻塞的特性

  • 如果list中存在元素,blpop和brpop就和lpop以及rpop作用相同。
  • 但如果list中元素为空,blpop和brpop就会产生阻塞,一直阻塞到list不空为止。
  • 在使用blpop和brpop的时候,是可以显示设置阻塞时间的,不一定是无休止的等待。
  • 阻塞期间redis可以执行其它的命令。 
  • blpop和brpop可以同时尝试获取多个key列表的元素,多个key对应的多个list,这多个list哪个有元素了,就会返回哪个元素。
  • 如果多个客户端同时对一个key执行pop,则最先执行命令的客户端会得到返回的结果。

语法:

blpop key [key ...] timeout

此处可以指定一个key或者多个key,每个key都对应一个list,如果这些list有任意一个非空,那么blpop都能把这里的元素给获取到从而立即返回,如果这些list都是空,那么就阻塞等待,等待其它客户端往这些list中插入元素。此处可以指定超时时间,这里timeout的超时时间单位是秒。reids6中允许设定成小数,redis5中,超时时间只能是整数。

1)针对非列表进行操作

返回的结果相当于一个pair(二元组),一方面是告诉我们当前的数据来自哪个key,一方面告诉我们取到的数据是什么。lpop本来就是头删,因此返回1。

2)针对空列表进行操作 

我使用del将key清除了,然后在对key进行lpop操作。

我们可以看到被阻塞了。这里阻塞时间设置了100秒。

此时我们在开启一个客户端,当我右边的客户端往key里插入数据一敲回车之后,左边客户端立刻返回了结果,告诉我们得到的结果1来自于key,它等待了96.99秒。

 3)针对多个key进行操作,只要任意一个key有数据就立刻返回。

brpop和blpop效果完全一致 ,此处就不介绍了,只不过一个是头删一个是尾删。

这两组命令有啥用呢?此处这两阻塞命令用途主要是用来作为"消息队列"。但是实际用到的场景几乎很少,了解它们的作用用途即可。

命令总结

操作类型命令时间复杂度
添加rpush key value [value...]O(k),k是元素个数
lpush key value [value...]       O(k),k是元素个数
linsert key before | after pivot valueO(n), n是pivot距离头尾的距离
查找lrange key start endO(s + n),s是start偏移量 n是start到end
lindex key indexO(n), n是索引的偏移量
len keyO(1)
删除lpop keyO(1)
rpop keyO(1)
lrem key count valueO(k),k是元素个数
ltrim key start endO(k),k是元素个数
修改lset key index valueO(n), n是索引的偏移量
阻塞操作blpop brpopO(1)

编码方式

ziplist(压缩列表):把数据按照更紧凑的压缩形式进行表示的,节省空间,当元素个数多了,操作起来效率会降低。

linkedlist(链表):如果元素多了会使用链表来应对数据多的时候,虽然空间比ziplist开销更多,但效率更高。

quicklist:相当于是链表和压缩链表的结合,整体还是一个链表,链表的每个节点是一个压缩列表,每个压缩列表都不让它太大,同时再把多个压缩列表通过链式结果连起来。

redis3之后都是用的quicklist,而之前的版本使用的是ziplist和linkedlist。

object encoding 可以查看key的编码方式。


http://www.kler.cn/a/578037.html

相关文章:

  • nacos和Eureka的学习
  • Core Speech Kit(基础语音服务)
  • ICRA顶会 | 当无人机遇上扩散模型:如何让四旋翼飞行器在复杂环境中「稳如泰山」?
  • 重塑用户体验:用户界面设计、交互设计及视觉体验优化的融合策略
  • 【C语言】外围电路异常排查方式
  • Python刷题:Python基础
  • 蓝桥-反倍数-oj152
  • 3.6c语言
  • 导电陶瓷粉:掺铑(Rh)钛酸钡在MLCC内电极浆料中的应用与创新-京煌科技
  • Spring Cloud Alibaba OpenFeign 实战:打造稳定高效的远程调用
  • MySql的安装及数据库的基本操作命令
  • 物联网-智慧农业中与市场需求对接的一体化解决方案
  • JS如何实现全选以及联动效果
  • 【AI速读】突破功能验证性能瓶颈:UVM++与仿真器随机化测试平台的融合实践
  • Electron:点击右键保存图片到本地
  • MouseBoost Pro for Mac 鼠标右键助手右键菜单
  • oracle goldengate 各版本支持的源端和目标端的数据库版本列表
  • 从厨电模范到数字先锋,看永洪科技如何助力方太集团开启数字新征程
  • 大彩串口屏开发 —— MODBUS通信
  • 通过计费集成和警报监控 Elasticsearch Service 成本