redis list类型
一、查看list类型的命令
二、list命令详解
1、在终端数据 help @list
127.0.0.1:6379>help @list
BLPOP key [key ...] timeout
summary: Remove and get the first element ina list, or block until one is ava
ilable
since: 2.0.0
BRPOP key [key ...] timeout
summary: Remove and get the last element in alist, or block until one is avai
lable
since: 2.0.0
BRPOPLPUSH source destination timeout
summary: Pop a value from a list, push it toanother list and return it; or bl
ockuntil one is available
since: 2.2.0
LINDEX key index
summary: Get an element from a list by itsindex
since: 1.0.0
……
头元素和尾元素
头元素指的是列表左端/前端第一个元素,尾元素指的是列表右端/后端第一个元素。
举个例子,列表list包含三个元素:x, y, z,其中x是头元素,而z则是尾元素。
空列表
指不包含任何元素的列表,Redis将不存在的key也视为空列表。
lpush key value [value ...]
将值value插入到列表key的表头。
如果key不存在,一个空列表会被创建并执行lpush操作。
当key存在但不是列表类型时,返回一个错误。
时间复杂度:
O(1)
返回值:
执行lpush命令后,表的长度。
Note
在Redis 2.3版本以前的lpush命令,都只接受单个value值。
127.0.0.1:6379>lpush word d
(integer)1
127.0.0.1:6379>lpush word a
(integer)2
127.0.0.1:6379>lpush word b
(integer)3
127.0.0.1:6379>lrange word 0 -1 # 显示列表内所有元素
1)"b"
2)"a"
3)"d"
lpushx key value
将值value插入到列表key的表头,当且仅当key存在并且是一个列表。
和lpush命令相反,当key不存在时,lpushx命令什么也不做。
时间复杂度:
O(1)
返回值:
lpushx命令执行之后,表的长度。
#情况1:对空列表执行lpushx
127.0.0.1:6379>llen greet # greet是一个空列表
(integer)0
127.0.0.1:6379>lpushx greet "hello" # 尝试lpushx,失败,因为列表为空
(integer)0
#情况2:对非空列表执行lpushx
127.0.0.1:6379>lpush greet "hello" # 先用lpush创建一个有一个元素的列表
(integer)1
127.0.0.1:6379>lpushx greet "good morning" #这次lpushx执行成功
(integer)2
127.0.0.1:6379>lrange greet 0 -1
1)"good morning"
2)"hello"
rpush key value [value ...]
将值value插入到列表key的表尾。
如果key不存在,一个空列表会被创建并执行rpush操作。
当key存在但不是列表类型时,返回一个错误。
时间复杂度:
O(1)
返回值:
执行rpush操作后,表的长度。
Note
在Redis 2.3版本以前的rpush命令,都只接受单个value值。
127.0.0.1:6379>llen fp-language # 显示列表中的元素数量
(integer)0
127.0.0.1:6379>rpush fp-language lisp
(integer)1
127.0.0.1:6379>lrange fp-language 0 0 # 显示列表中的元素
1)"lisp"
127.0.0.1:6379>rpush fp-language scheme
(integer)2
127.0.0.1:6379>lrange fp-language 0 1 # 显示列表中的元素
1)"lisp"
2)"scheme"
rpushx key value
将值value插入到列表key的表尾,当且仅当key存在并且是一个列表。
和rpush命令相反,当key不存在时,rpushx命令什么也不做。
时间复杂度:
O(1)
返回值:
rpushx命令执行之后,表的长度。
#情况1:key不存在
127.0.0.1:6379>llen greet
(integer)0
127.0.0.1:6379>rpushx greet "hello" # 对不存在的key进行rpushx,PUSH失败。
(integer)0
#情况2:key存在且是一个非空列表
127.0.0.1:6379>rpush greet "hi" # 先用rpush插入一个元素
(integer)1
127.0.0.1:6379>rpushx greet "hello" # greet现在是一个列表类型,rpushx操作成功。
(integer)2
127.0.0.1:6379>lrange greet 0 -1
1)"hi"
2)"hello"
lpop key
移除并返回列表key的头元素。
时间复杂度:
O(1)
返回值:
列表的头元素。
当key不存在时,返回nil。
127.0.0.1:6379>llen course
(integer)0
127.0.0.1:6379>rpush course algorithm001
(integer)1
127.0.0.1:6379>rpush course c++101
(integer)2
127.0.0.1:6379>LPOP course # 移除头元素
"algorithm001"
rpop key
移除并返回列表key的尾元素。
时间复杂度:
O(1)
返回值:
列表的尾元素。
当key不存在时,返回nil。
127.0.0.1:6379>rpush mylist "one"
(integer)1
127.0.0.1:6379>rpush mylist "two"
(integer)2
127.0.0.1:6379>rpush mylist "three"
(integer)3
127.0.0.1:6379>rpop mylist # 返回被弹出的元素
"three"
127.0.0.1:6379>lrange mylist 0 -1 # 列表剩下的元素
1)"one"
2)"two"
rlpopkey [key ...] timeout
rlpop是列表的阻塞式(blocking)弹出原语。
它是LPOP命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被rlpop命令阻塞,直到等待超时或发现可弹出元素为止。
当给定多个key参数时,按参数key的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。
非阻塞行为
当rlpop被调用时,如果给定key内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字一起,组成结果返回给调用者。
当存在多个给定key时,rlpop按给定key参数排列的先后顺序,依次检查各个列表。
假设现在有job、 command和request三个列表,其中job不存在,command和request都持有非空列表。考虑以下命令:
rlpopjob command request 0
rlpop保证返回的元素来自command,因为它是按”查找job -> 查找command -> 查找request“这样的顺序,第一个找到的非空列表。
127.0.0.1:6379>DEL job command request # 确保key都被删除
(integer)0
127.0.0.1:6379>lpush command "update system..." # 为command列表增加一个值
(integer)1
127.0.0.1:6379>lpush request "visit page" # 为request列表增加一个值
(integer)1
127.0.0.1:6379>rlpop job command request 0 # job列表为空,被跳过,紧接着command列表的第一个元素被弹出。
1)"command" # 弹出元素所属的列表
2)"update system..." # 弹出元素所属的值阻塞行为
如果所有给定key都不存在或包含空列表,那么rlpop命令将阻塞连接,直到等待超时,或有另一个客户端对给定key的任意一个执行lpush或rpush命令为止。
超时参数timeout接受一个以秒为单位的数字作为值。超时参数设为0表示阻塞时间可以无限期延长(block indefinitely) 。
127.0.0.1:6379>EXISTS job # 确保两个key都不存在
(integer)0
127.0.0.1:6379>EXISTS command
(integer)0
127.0.0.1:6379>rlpop job command 300 #因为key一开始不存在,所以操作会被阻塞,直到另一客户端对job或者command列表进行PUSH操作。
1)"job" # 这里被push的是job
2)"do my home work" # 被弹出的值
(26.26s) # 等待的秒数
127.0.0.1:6379>rlpop job command 5 # 等待超时的情况
(nil)
(5.66s)# 等待的秒数相同的key被多个客户端同时阻塞
相同的key可以被多个客户端同时阻塞。
不同的客户端被放进一个队列中,按”先阻塞先服务”(first-rlpop,first-served)的顺序为key执行rlpop命令。
在MULTI/EXEC事务中的rlpop
rlpop可以用于流水线(pipline,批量地发送多个命令并读入多个回复),但把它用在MULTI/EXEC块当中没有意义。因为这要求整个服务器被阻塞以保证块执行时的原子性,该行为阻止了其他客户端执行lpush或rpush命令。
一个被包含在MULTI/EXEC块内的rlpop操作,行为表现得就像操作超时一样,仅仅返回一个nil值。
如果你是科幻迷,你可以想象在MULTI/EXEC块内,时间以无限的速度在流逝。
127.0.0.1:6379>MULTI
OK
127.0.0.1:6379>rlpop job 30
QUEUED
127.0.0.1:6379>EXEC
1)(nil) # 操作没有等待,立即被返回了时间复杂度:
O(1)
返回值:
假如在指定时间内没有任何元素被弹出,则返回一个nil和等待时长。
反之,返回一个含有两个元素的列表,第一个元素是被弹出元素所属的key,第二个元素是被弹出元素的值。
brpopkey [key ...] timeout
brpop是列表的阻塞式(blocking)弹出原语。
它是rpop命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被brpop命令阻塞,直到等待超时或发现可弹出元素为止。
当给定多个key参数时,按参数key的先后顺序依次检查各个列表,弹出第一个非空列表的尾部元素。
关于阻塞操作的更多信息,请查看rlpop命令,brpop除了弹出元素的位置和rlpop不同之外,其他表现一致。
时间复杂度:
O(1)
返回值:
假如在指定时间内没有任何元素被弹出,则返回一个nil和等待时长。
反之,返回一个含有两个元素的列表,第一个元素是被弹出元素所属的key,第二个元素是被弹出元素的值。
127.0.0.1:6379>llen course
(integer)0
127.0.0.1:6379>rpush course algorithm001
(integer)1
127.0.0.1:6379>rpush course c++101 # 尾部元素
(integer)2
127.0.0.1:6379>brpop course 30
1)"course" # 弹出元素的key
2)"c++101" # 弹出元素的值
llenkey
返回列表key的长度。
如果key不存在,则key被解释为一个空列表,返回0.
如果key不是列表类型,返回一个错误。
时间复杂度:
O(1)
返回值:
列表key的长度。
#情况1:空列表
127.0.0.1:6379>llen job
(integer)0
#情况2:非空列表
127.0.0.1:6379>lpush job "cook food"
(integer)1
127.0.0.1:6379>lpush job "have lunch"
(integer)2
127.0.0.1:6379>llen job
(integer)2
lrangekey start stop
返回列表key中指定区间内的元素,区间以偏移量start和stop指定。
下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。
你也可以使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
注意lrange命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表,对该列表执行lrange list 0 10,结果是一个包含11个元素的列表,这表明stop下标也在lrange命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的Range.new、Array#slice和Python的range()函数。
超出范围的下标
超出范围的下标值不会引起错误。
如果start下标比列表的最大下标end(llen list减去1)还要大,或者start > stop,lrange返回一个空列表。
如果stop下标比end下标还要大,Redis将stop的值设置为end。
时间复杂度:
O(S+N),S为偏移量start,N为指定区间内元素的数量。
返回值:
一个列表,包含指定区间内的元素。
127.0.0.1:6379>rpush fp-language lisp # 插入一个值到列表fp-language
(integer)1
127.0.0.1:6379>lrange fp-language 0 0
1)"lisp"
127.0.0.1:6379>rpush fp-language scheme
(integer)2
127.0.0.1:6379>lrange fp-language 0 1
1)"lisp"
2)"scheme"
lremkey count value
根据参数count的值,移除列表中与参数value相等的元素。
count的值可以是以下几种:
count> 0: 从表头开始向表尾搜索,移除与value相等的元素,数量为count。
count< 0: 从表尾开始向表头搜索,移除与value相等的元素,数量为count的绝对值。
count= 0: 移除表中所有与value相等的值。
时间复杂度:
O(N),N为列表的长度。
返回值:
被移除元素的数量。
因为不存在的key被视作空表(empty list),所以当key不存在时,lrem命令总是返回0。
#先创建一个表,内容排列是
#morning hello morning helllo morning
127.0.0.1:6379>lpush greet "morning"
(integer)1
127.0.0.1:6379>lpush greet "hello"
(integer)2
127.0.0.1:6379>lpush greet "morning"
(integer)3
127.0.0.1:6379>lpush greet "hello"
(integer)4
127.0.0.1:6379>lpush greet "morning"
(integer)5
127.0.0.1:6379>lrange greet 0 4 # 查看所有元素
1)"morning"
2)"hello"
3)"morning"
4)"hello"
5)"morning"
127.0.0.1:6379>lrem greet 2 morning # 移除从表头到表尾,最先发现的两个morning
(integer)2 # 两个元素被移除
127.0.0.1:6379>llen greet # 还剩3个元素
(integer)3
127.0.0.1:6379>lrange greet 0 2
1)"hello"
2)"hello"
3)"morning"
127.0.0.1:6379>lrem greet -1 morning # 移除从表尾到表头,第一个morning
(integer)1
127.0.0.1:6379>llen greet
(integer)2
127.0.0.1:6379>lrange greet 0 1
1)"hello"
2)"hello"
127.0.0.1:6379>lrem greet 0 hello # 移除表中所有hello
(integer)2 # 两个hello被移除
127.0.0.1:6379>llen greet
(integer)0
lsetkey index value
将列表key下标为index的元素的值甚至为value。
更多信息请参考lindex操作。
当index参数超出范围时,返回一个错误。
时间复杂度:
对头元素或尾元素进行lset操作,复杂度为O(1)。
其他情况下,为O(N),N为列表的长度。
返回值:
操作成功返回ok,否则返回错误信息。
127.0.0.1:6379>lpush job "cook food"
(integer)1
127.0.0.1:6379>lrange job 0 0
1)"cook food"
127.0.0.1:6379>lset job 0 "play game"
OK
127.0.0.1:6379>lrange job 0 0
1)"play game"
ltrimkey start stop
对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
举个例子,执行命令ltrim list 0 2,表示只保留列表list的前三个元素,其余元素全部删除。
下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。
你也可以使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
当key不是列表类型时,返回一个错误。
ltrim命令通常和lpush命令或rpush命令配合使用,举个例子:
lpushlog newest_log
ltrimlog 0 99这个例子模拟了一个日志程序,每次将最新日志newest_log放到log列表中,并且只保留最新的100项。注意当这样使用ltrim命令时,时间复杂度是O(1),因为平均情况下,每次只有一个元素被移除。
注意ltrim命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表list,对该列表执行ltrim list 0 10,结果是一个包含11个元素的列表,这表明stop下标也在ltrim命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的Range.new、Array#slice和Python的range()函数。
超出范围的下标
超出范围的下标值不会引起错误。
如果start下标比列表的最大下标end(llen list减去1)还要大,或者start > stop,ltrim返回一个空列表(因为ltrim已经将整个列表清空)。
如果stop下标比end下标还要大,Redis将stop的值设置为end。
时间复杂度:
O(N),N为被移除的元素的数量。
返回值:
命令执行成功时,返回ok。
#情况1:一般情况下标
127.0.0.1:6379>lrange alpha 0 -1 # 建立一个5元素的列表
1)"h"
2)"e"
3)"l"
4)"l"
5)"o"
127.0.0.1:6379>ltrim alpha 1 -1 # 删除索引为0的元素
OK
127.0.0.1:6379>lrange alpha 0 -1 # "h"被删除
1)"e"
2)"l"
3)"l"
4)"o"
#情况2:stop下标比元素的最大下标要大
127.0.0.1:6379>ltrim alpha 1 10086
OK
127.0.0.1:6379>lrange alpha 0 -1
1)"l"
2)"l"
3)"o"
#情况3:start和stop下标都比最大下标要大,且start < sotp
127.0.0.1:6379>ltrim alpha 10086 200000
OK
127.0.0.1:6379>lrange alpha 0 -1 # 整个列表被清空,等同于DEL alpha
(emptylist or set)
#情况4:start > stop
127.0.0.1:6379>lrange alpha 0 -1 # 在新建一个列表
1)"h"
2)"u"
3)"a"
4)"n"
5)"g"
6)"z"
127.0.0.1:6379>ltrim alpha 10086 4
OK
127.0.0.1:6379>lrange alpha 0 -1 # 列表同样被清空
(emptylist or set)
lindexkey index
返回列表key中,下标为index的元素。
下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。
你也可以使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
如果key不是列表类型,返回一个错误。
时间复杂度:
O(N),N为到达下标index过程中经过的元素数量。
因此,对列表的头元素和尾元素执行lindex命令,复杂度为O(1)。
返回值:
列表中下标为index的元素。
如果index参数的值不在列表的区间范围内(out of range),返回nil。
127.0.0.1:6379>lpush mylist "World"
(integer)1
127.0.0.1:6379>lpush mylist "Hello"
(integer)2
127.0.0.1:6379>lindex mylist 0
"Hello"
127.0.0.1:6379>lindex mylist -1
"World"
127.0.0.1:6379>lindex mylist 3 # index不在mylist的区间范围内
(nil)
linsertkey BEFORE|AFTER pivot value
将值value插入到列表key当中,位于值pivot之前或之后。
当pivot不存在于列表key时,不执行任何操作。
当key不存在时,key被视为空列表,不执行任何操作。
如果key不是列表类型,返回一个错误。
时间复杂度:
O(N),N为寻找pivot过程中经过的元素数量。
返回值:
如果命令执行成功,返回插入操作完成之后,列表的长度。
如果没有找到pivot,返回-1。
如果key不存在或为空列表,返回0。
127.0.0.1:6379>rpush mylist "Hello"
(integer)1
127.0.0.1:6379>rpush mylist "World"
(integer)2
127.0.0.1:6379>linsert mylist BEFORE "World" "There"
(integer)3
127.0.0.1:6379>lrange mylist 0 -1
1)"Hello"
2)"There"
3)"World"
127.0.0.1:6379>linsert mylist BEFORE "go" "let‘s" # 对一个非空列表插入,查找一个不存在的pivot
(integer)-1 # 失败
127.0.0.1:6379>EXISTS fake_list # 对一个空列表执行linsert命令
(integer)0
127.0.0.1:6379>linsert fake_list BEFORE "nono" "gogogog"
(integer)0 # 失败
rpoplpushsource destination
命令rpoplpush在一个原子时间内,执行以下两个动作:
将列表source中的最后一个元素(尾元素)弹出,并返回给客户端。
将source弹出的元素插入到列表destination,作为destination列表的的头元素。
举个例子,你有两个列表source和destination,source列表有元素a, b, c,destination列表有元素x, y, z,执行rpoplpush source destination之后,source列表包含元素a, b,destination列表包含元素c, x, y, z ,并且元素c被返回。
如果source不存在,值nil被返回,并且不执行其他动作。
如果source和destination相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。
时间复杂度:
O(1)
返回值:
假如在指定时间内没有任何元素被弹出,则返回一个nil和等待时长。
反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。
#相关数据
127.0.0.1:6379>rpush alpha a
(integer)1
127.0.0.1:6379>rpush alpha b
(integer)2
127.0.0.1:6379>rpush alpha c
(integer)3
127.0.0.1:6379>rpush alpha d
(integer)4
#情况1:source和destination不同
127.0.0.1:6379>lrange alpha 0 -1 # 查看所有元素
1)"a"
2)"b"
3)"c"
4)"d"
127.0.0.1:6379>rpoplpush alpha reciver # 执行一次rpoplpush看看
"d"
127.0.0.1:6379>lrange alpha 0 -1
1)"a"
2)"b"
3)"c"
127.0.0.1:6379>lrange reciver 0 -1
1)"d"
#情况2:source和destination相同
127.0.0.1:6379>rpoplpush alpha alpha
"c"
127.0.0.1:6379>lrange alpha 0 -1 # 原来的尾元素"c"被放到了头部
1)"c"
2)"a"
3)"b"
设计模式:一个安全的队列
Redis的列表经常被用作队列(queue),用于在不同程序之间有序地交换消息(message)。一个程序(称之为生产者,producer)通过lpush命令将消息放入队列中,而另一个程序(称之为消费者,consumer)通过rpop命令取出队列中等待时间最长的消息。
不幸的是,在这个过程中,一个消费者可能在获得一个消息之后崩溃,而未执行完成的消息也因此丢失。
使用rpoplpush命令可以解决这个问题,因为它在返回一个消息之余,还将该消息添加到另一个列表当中,另外的这个列表可以用作消息的备份表:假如一切正常,当消费者完成该消息的处理之后,可以用lrem命令将该消息从备份表删除。
另一方面,助手(helper)程序可以通过监视备份表,将超过一定处理时限的消息重新放入队列中去(负责处理该消息的消费者可能已经崩溃),这样就不会丢失任何消息了。
brpoplpushsource destination timeout
brpoplpush是rpoplpush的阻塞版本,当给定列表source不为空时,brpoplpush的表现和rpoplpush一样。
当列表source为空时,brpoplpush命令将阻塞连接,直到等待超时,或有另一个客户端对source执行lpush或rpush命令为止。
超时参数timeout接受一个以秒为单位的数字作为值。超时参数设为0表示阻塞时间可以无限期延长(block indefinitely) 。
更多相关信息,请参考rpoplpush命令。
时间复杂度:
O(1)
返回值:
假如在指定时间内没有任何元素被弹出,则返回一个nil和等待时长。
反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。
#情况1:非空列表
127.0.0.1:6379>brpoplpush msg reciver 500
"hellomoto" # 弹出元素的值
(3.38s) # 等待时长
127.0.0.1:6379>llen reciver
(integer)1
127.0.0.1:6379>lrange reciver 0 0
1)"hello moto"
#情况2:空列表
127.0.0.1:6379>brpoplpush msg reciver 1
(nil)
(1.34s)
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u014795720/article/details/47207805