文章目录
- list
- 常见命令
- lpush
- lrange
- lpushx
- rpush
- rpushx
- lpop和rpop
- lindex
- linsert
- llen
- lrem
- ltrim
- lset
- 阻塞版本命令
- blpop
list
初步认识
在Redis中,对于list这种数据类型来说,更像是一种数组或者是顺序表,下面展示其最基本的用法
值得注意的是,在list内部的实现方式中,也就是我们之前所提及的编码方式,对于list这种数据类型来说其实底层不是一个简单的数组,而是更加类似于一种双端队列的方式来进行实现,这样就能很好的实现头插和头删尾插和尾删的操作了
对于list来说,我们约定最左侧的元素下标是0,也可以是负数,从-1开始从右向左逐渐递减
有序?
list当中的元素是有序的,对于有序这个词来说,其实有很多种含义,如果我们说此时的有序说的是升序或者降序,那么就是说这个数组中的数据突出的是按照递增还是递减,而又有时候我们说的是有序指的是顺序很关键,那么想要突出的重点是,当数组中的元素顺序进行交换之后,就会导致整个数组的并不和原来的数组等价,这是两种不同的概念
获取和删除
在list当中,会有两种方式来返回被删除的元素,一种是lindex,表示的是获取到元素的值,而lrem表示的是删除元素,此时也会返回出被删除元素的值,但是这两个虽然都能进行值的返回,但是并不相同,下面演示这两种最基本的使用方式:
127.0.0.1:6379> lpush key1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> lindex key1 3
"2"
从上面的演示中可以看到,一个比较惊奇的结果是,似乎并不是按照从左向右进行的插入,而更像是从右向左,那么下面就引入Redis中list类型的相关命令
常见命令
lpush
对于这个命令来说,它允许插入一个,也允许插入多个值,并且将会按照顺序头插这4个元素,这也就意味着,当插入结束之后,最开始插入的元素其实是在最后一个位置
所以,对于上述的操作来说,插入的元素是1 2 3 4 5,实际上在list中的标识方式应该是5 4 3 2 1,这是由list的功能特性决定的
如果此时key已经存在,那么key对应的value类型还不是list,此时lpush命令就会报错:
127.0.0.1:6379> set key1 1
OK
127.0.0.1:6379> lpush key1 1 2 3 4 5
(error) WRONGTYPE Operation against a key holding the wrong kind of value
Redis中维护的是键值对,所以即使是list也满足这个要求,在键值对中key值必须是string,不同的数据类型只能说的是value的类型,因此对于key值重复的问题一定是不能被成功插入的,因此在Redis中所有的数据类型都满足这个要求
lrange
在list中还有一个命令叫做lrange:
lrange key start stop
从这个命令也可以看出,它的功能就是表示的是展示某个key值对应的list的某个区间的值
127.0.0.1:6379> lpush key1 1 2 3 4 5 6 7 8 9
(integer) 9
127.0.0.1:6379> lrange key1 1 5
1) "8"
2) "7"
3) "6"
4) "5"
5) "4"
127.0.0.1:6379> lrange key1 0 -1
1) "9"
2) "8"
3) "7"
4) "6"
5) "5"
6) "4"
7) "3"
8) "2"
9) "1"
当说起下标,就要考虑到越界访问呢的问题,在C++这门语言中,对于越界访问这个问题,其实是一个未定义的行为,但是在Redis中,似乎并不是如此
127.0.0.1:6379> lrange key1 1 100
1) "8"
2) "7"
3) "6"
4) "5"
5) "4"
6) "3"
7) "2"
8) "1"
在C++中,对于未定义的行为,可能会导致程序崩溃,或者是不合法的数据,或者是看起来合法,实际上错误的数据,也可能正好得到的是一个符合要求的数据,总的来说,这样的行为是未定义的
而在Redis中,并没有选择这样的方法,它的做法是,尽可能的获取到给定区间的元素,如果给定的区间是非法的,那么就会尽可能获取合法的内容,对于不合法的就不表示
这样做看起来感觉还不错?少了检测的机制,会导致效率提高,但是也有弊端,弊端就是需要程序员自己来排查问题,当出现越界访问的时候Redis本身并不会对你的行为进行提示,这也并不是一个特别完美的解决方案
lpushx
下面说的是lpushx命令:
127.0.0.1:6379> lrange key1 0 -1
1) "9"
2) "8"
3) "7"
4) "6"
5) "5"
6) "4"
7) "3"
8) "2"
9) "1"
127.0.0.1:6379> lpushx key1 10 11 12 13 14
(integer) 14
127.0.0.1:6379> lrange key1 0 -1
1) "14"
2) "13"
3) "12"
4) "11"
5) "10"
6) "9"
7) "8"
8) "7"
9) "6"
10) "5"
11) "4"
12) "3"
13) "2"
14) "1"
由上述的执行效果可以看出,对于lpushx来说,其实其本质就是对于已经存在的key值依旧进行头插,而如果此时的list不存在,那么lpushx会直接返回
127.0.0.1:6379> lpushx key3
(error) ERR wrong number of arguments for 'lpushx' command
rpush
上面的lpush,其实是有些反人类直觉的插入元素的方式,毕竟我们更习惯看待的是尾插,那么下面演示的就是尾插:
127.0.0.1:6379> rpush key1 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379> lrange key1 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
127.0.0.1:6379> rpushx key1 7 8 9
(integer) 9
127.0.0.1:6379> lrange key1 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
rpushx
而对于rpushx来说,和lpushx一样,这里就不多讲述了
lpop和rpop
在当前的Redis 5版本中,是没有count参数的,而从Redis 6.2版本中,新增了一个count参数,这个参数表示的就是要删除几个元素
127.0.0.1:6379> lrange key1 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
127.0.0.1:6379> lpop key1
"1"
127.0.0.1:6379> rpop key1
"9"
127.0.0.1:6379> lrange key1 0 -1
1) "2"
2) "3"
3) "4"
4) "5"
5) "6"
6) "7"
7) "8"
Redis中的list本质上来说就是一个双端队列,从两段进行插入和删除的效率都是O(1),搭配到lpush和lpop以及rpush和rpop,其实已经可以当做栈和队列来使用了,总的来说效率还是非常不错的
lindex
这个命令表示的是,给定一个下标,获取该下标对应的元素,这里的时间复杂度是O(N),其中N表示的是list中元素的个数,如果此时的下标非法,会返回一个nil
127.0.0.1:6379> lrange key1 0 -1
1) "2"
2) "3"
3) "4"
4) "5"
5) "6"
6) "7"
7) "8"
127.0.0.1:6379> lindex key1 3
"5"
127.0.0.1:6379> lindex key1 1111
(nil)
linsert
linsert key BEFORE|AFTER pivot element
这个命令的意思是,在某个值的前面或者后面插入另外一个值,这里我举一个例子
127.0.0.1:6379> linsert key1 before 6 2222
(integer) 8
127.0.0.1:6379> lrange key1 0 -1
1) "2"
2) "3"
3) "4"
4) "5"
5) "2222"
6) "6"
7) "7"
8) "8"
这个意思就是在6之前插入一个2222
那如果在整个列表中有多个基准值该如何处理呢?具体的解决措施是从左向右进行查找,找到第一个符合基准值的位置插入就可以了
llen
llen表示的意思是列表的长度
127.0.0.1:6379> llen key1
(integer) 8
127.0.0.1:6379> llen key0
(integer) 0
lrem
rem的意思是remove,所以意思很明显,就是要移出某个元素
lrem key count element
127.0.0.1:6379> lrem key1 1 2222
(integer) 1
127.0.0.1:6379> lrem key1 2 5
(integer) 1
count表示的是要删除多少个元素,其中返回值表示的是删除成功的个数
ltrim
ltrim key start stop
该命令表示的意思是保留start到stop之间的元素,其他元素全部删除
lset
lset key index element
这个命令的意思是根据下标进行修改元素
阻塞版本命令
blpop 和 brpop 是 lpop 和 rpop 的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致,但是:
在列表中有元素的情况下,阻塞和非阻塞表现是一致的.但如果列表中没有元素,非阻塞版本会
理解返回0,但阻塞版本会根据超时值,阳塞一段时间,期间Redis可以执行其他命令,但要
求执行该命令的客户端会表现为阻塞状态
命令中如果设置了多个键,那么会从左向右进行遍历键,一旦有一个键对应的列表中可以弹出元
素,命令立即返回
如果多个客戶端同时多一个键执行POP,则最先执行命令的客戶端会得到弹出的元素
blpop
blpop key [key ...] timeout
此处表示的是可以指定一个key或者多个key,每一个key表示的都是一个list,而对于这些list来说,如果有任何一个是非空的,那么就会把这里的元素获取到,立即返回,这个这些key全部都是空的,那么此时就会在这里进行阻塞等待,直到其他客户端向这些list当中放入元素