List
List是Redis的另一种基本数据类型,Redis中的List是以双向链表形式存在的,key持有对链表头元素和尾元素的索引。向双向链表的头部或尾部添加数据的时间复杂度是常数级别的。
基本命令
1.向列表中添加元素
既然list是双向链表,那就必然支持从两端向list中添加元素。对应的命令分别为:
lpush key value [value …],
rpush key value [value …]
表示从左侧添加元素和从右侧添加元素。
命令:lrange key start stop,表示从根据开始和结束索引获取list中的元素。
# 从左侧添加元素
> lpush list a b c d
(integer) 4
# 使用lrange命令获取list中的元素,参数为开始元素和结束元素的索引
> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
# 从右侧添加元素x,x会被添加至a的右侧
> rpush list x
(integer) 5
> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "x"
2.从列表中弹出元素
命令:lpop key 和 rpop key
分别代表从列表的左侧和右侧弹出一个元素。
# 从左侧弹出元素
> lpop list
"d"
# 从右侧弹出元素
> rpop list
"x"
应用
1.list的同向push和pop,就实现了一个栈(stack),数据的入栈与出栈满足先进后出。
2.list的异向push和pop,则实现了一个队列(queue),数据的入队与出队满足先进先出。
3.一些场景下使用Redis的List来代替应用程序中的栈或队列,可以在应用宕机情况下保证数据不丢失,同时还可以确保线程安全。
3.根据索引获取和修改元素
命令:lindex key index
实现根据list的下标索引去获取元素;
命令:lset key index value
实现根据list的下标索引去修改元素。
# list中当前元素为:d c b a
> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
# 获取下标为2的元素
> lindex list 2
"b"
# 修改下标为2的元素
> lset list 3 xxx
OK
> lrange list
1) "d"
2) "c"
3) "xxx"
4) "a"
根据索引去操作list实际上实现了数组的功能。
4.截取元素
命令:ltrim key start stop
用于截取list中索引由start至stop之间的元素
# list中当前元素为:d c b a
> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
# 截取第0到-1号索引的内容,即全部元素
> ltrim list 0 -1
OK
# 此时list中元素没有发生变化
> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
# 截取第1个元素至倒数第二个元素,即取出第0个元素和最后一个元素
> ltrim list 1 -2
OK
# 此时剩余元素为c和b
> lrange list 0 -1
1) "c"
2) "b"
5.List中的阻塞操作
假设你需要用Redis的list构建一个基于生产者-消费者模式的队列,生产者用lpush从一端放入数据,消费者用rpop从另一端取出数据。
问题在于:可能出现数据全部被消费,即list已经为空的情况。此时如果使用rpop只能返回null。这种情况下消费者只能稍作等待再重试从list中获取数据。这会导致所有对该空list的操作都是无效的,只能返回null。
为了解决这个问题,Redis提供了rpop和lpop的阻塞版本:brpop和blpop。如果list为空,brpop和blpop会阻塞,直到有新的元素被加入list或者达到用户设定的超时时间。
命令格式:
blpop key [key …] timeout
brpop key [key …] timeout
这里举一个例子:
# 初始化一个list
> lpush list 5 4 3 2 1
(integer) 7
> lrange list 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "c"
7) "b"
# 使用blpop以阻塞方式从list左侧获取一个元素,超时时间为5秒,返回key和对应获取到的值
> blpop list 5
1) "list"
2) "1"
blpop和brpop命令可以添加多个list作为key,返回的数据格式为一个包含两个元素的数组。显示第一个返回的list的key及对应值。
6.key的自动创建与销毁
根据Redis官方的介绍:
It is Redis’ responsibility to delete keys when lists are left empty, or to create an empty list if the key does not exist and we are trying to add elements to it.
Redis是个有责任心的组件,如果一个list中已经没有元素了,该key会自动销毁;如果向一个未被创建的key中添加元素,Redis会自动创建一个空的list。
总结下来有一下三点:
1.当我们向一个聚合数据类型中添加元素时,如果目标key还不存在,Redis会在添加元素之前创建一个空的key;例如:
# 删除名为list的key
> del list
(integer) 1
> lpush list 1 2 3
(integer) 3
2.如果从一个聚合数据类型中取完数据,该value已经是空的了,那么这个key会自动被销毁(Stream类型的数据除外),如:
> lpush list 1 2
(integer) 2
> exists list
(integer) 1
# 此时将list中全部元素弹出
> lpop list
"2"
> lpop list
"1"
# 再次判断key是否存在,此时key已被销毁
> exists list
(integer) 0
3.针对已为空的list调用如llen这样的只读命令或移除元素的命令时,Redis会制造一种假象,仿佛一个指向空list的key还存在,并正确返回命令的结果,如:
# 删除key
> del list
(integer) 0
# 获取list的长度
> llen list
(integer) 0
# 从list中获取元素
> lpop list
(nil)
以上就是Redis中List的基本概念与常用命令,大家是否学到了呢?
Redis List深入解析
本文详细介绍了Redis中的List数据类型,包括其双向链表结构、基本命令、应用场景、阻塞操作及key的自动管理机制,适合Redis初学者和进阶用户。
6万+

被折叠的 条评论
为什么被折叠?



