列表类型
list可以存储一个有序的字符串列表,一般用于在两端添加元素,并从两端获取数据,或获取列表中一个片段数据列。Redis使用双向链表实现列表,因此两端添加元素时间复杂度为O(1),因此两端添加元素性能较好;获取时,越接近两端的元素获取速度就越快。(因此获取两端有限长度的子列表,如获取首尾的10条记录,从一个千万级和一个百位级的列表获取速度是一样的)。
因为采用了双向链表实现,虽然首尾添加和读取数据很快,但是要根据索引查找一个元素性能较慢。和java的LinkedList
类似,查找元素时,如查找一个确切位置123
,则列表需要移动指针到指定位置,并读取数据,因此位置离头尾越远,则查找过程时间越长,相对应的性能越低,这里的例子时间复杂度为O(123),如果长度为n
的列表,从一端查找元素,则最差为O(n)
。
列表类型最多可容纳2^32-1
个元素。列表的值类型必须是字符串,不能再嵌套其他Redis类型,如散列、列表、集合等。
命令
向列表两端增加元素,使用的指令如下:
LPUSH key value [value ...]
RPUSH key value [value ...]
LPUSH指令用来向列表左边增加元素,返回值表示增加元素后列表的长度。当有多个值元素时,依次加入到列表。
LPUSH key v1 v2 v3
# 此时列表的元素为[v3, v2, v1]
RPUSH指令用来向列表右侧增加元素,和LPUSH类似,返回值为添加后的列表长度。
RPUSH key v4 v5
# 此时列表的元素为[v3, v2, v1, v4, v5]
从两端获取元素
LPOP key
RPOP key
BLPOP list1 list2... TIMEOUT
BRPOP list1 list2... TIMEOUT
LPOP指令从列表左侧取出第一个元素,取出意味着先移除,再返回。LPOP后,则原始列表的长度减少1
。
LPOP a
# "3"
# 此时列表的元素为[2, 1, 4, 5]
RPOP指令从列表右侧取出第一个元素,和LPOP指令类似,移除右侧第一个元素后,并返回,列表长度减少1
。
RPOP a
# "5"
# 此时列表元素为[2, 1, 4]
BLPOP指令从指定的列表(list1,list2支持多个列表)左侧弹出元素,当列表没有元素时,会阻塞列表直到TIMEOUT超时,TIMEOUT=0
时会一直阻塞下去。
当列表为空时,返回nil
(只有TIMEOUT非0时,到期后没有获取到数据,就返回nil
),否则返回成对的数据,第一个元素为被弹出得列表key(list1),第二个元素为弹出的数据。
# 客户端1
BLPOP mylist 0
# 此时客户端阻塞,当客户端2放入数据后,立即弹出数据
1) "mylist"
2) "1"
(19.50s)
# 最后的时间标识阻塞开始知道弹出数据的时间
# 客户端2
PUSH mylist 1 2
BRPOP指令同BLPOP指令基本功能一致,只是弹出方向为列表右侧。
获取列表长度
LLEN key
LLEN指令可以查询一个列表的长度,当key不存在时返回0
。Redis的设计,有记录列表长度的信息,因此读取列表长度,将会直接返回长度值,因此其时间负责读为O(1),性能较高。
LLEN ab #不存在
# (integer) 0
LLEN a
# (integer) 3
查询列表子集
LRANGE key start stop
LRANGE通常会比LPOP、RPOP更为常用,后者可能主要是作为栈、队列来使用,相对来说使用不是很频繁(队列采用MQ的可能性更大);Redis的队列作为热门条目、个人收藏列表等更为常见,其读取的操作跟多为子集列表;配合start和stop可以实现任意子集的读取,Redis的列表索引从0
开始。
# 仍使用之前的a列表[2, 1, 4]
LRANGE a 0 1
# "2" "1"
LRANGE在读取列表子集时,返回后,不会删除列表元素,在获取子集时,包含stop位置的元素,如上述指令中,stop=1
,则会返回所谓位置1
的元素。
start
和stop
支持负值,当索引位置为负值时,表示从右侧开始返回,-1
表示右侧第一个元素,-2
表示右侧第二个元素,依次类推。
(当stop超过了列表长度,则实际的stop位置为右边第一个元素)
(如果start > stop,则返回空列表)
# 返回从左侧第一个元素开始,到右侧第一个元素,因此该指令返回列表的全部元素
LRANGE a 0 -1
# "2" "1" "4"
# stop=4超过了列表长度, 则会返回全部数据,到最右边元素为止
LRANGE a 0 4
# "2" "1" "4"
LRANGE a -1 -4
# start > stop,返回空列表
LRANGE a 2 1
(empty list or set)
LRANGE a -1 -2
(empty list or set)
删除列表指定元素
LREM key count value
LREM指令用于删除key
列表中,指定的元素,会按照一定的方向(从左往右或从右往左),删除当前方向上,前count
个值为value
的元素。返回值为删除的元素个数。
count=0
,删除列表中所有的value
元素
count>0
,从左向右,删除前count
个值为value
的元素
count<0
,从右向左,删除前abs(count)
个值为value
的元素
LRANGE a 0 -1
# "1" "2" "1" "4" "1"
LREM a 2 1
# (integer) 2
LRANGE a 0 -1
# "2" "4" "1"
LREM a -2 1
# (integer) 1
LRANGE a 0 -1
# "2" "4"
LPUSH a 4
RPUSH a 4
LRANGE a 0 -1
# "4" "2" "4" "4"
LREM a 0 4
#(integer) 3
LRANGE a 0 -1
# "2"
获取指定索引的值
LINDEX key index
LINDEX指令用于返回key
列表指定索引index
位置的值。
index >= 0
,从左边开始查找,索引从0
开始
index < 0
,从右边开始查找,最右侧第一个元素索引为-1
当
index
超出列表长度,则返回空nil
LRANGE a 0 -1
# "1" "2" "3"
LINDEX a 1
# "2"
LINDEX a -2
# "2"
LINDEX a 3
# (nil)
设置指定索引的值
LSET key index value
LSET指令将key
列表的index
索引位置设置值为value
。
index >= 0
,从左边开始,对指定索引位置设置为value
index < 0
,从右边开始,对指定索引位置设置为value
index
超出列表范围(无论是大于0还是小于0),均报错:超出索引范围
LRANGE a 0 -1
# "1" "2" "3"
LSET a 1 4
# OK
LRANGE a 0 -1
# "1" "4" "3"
LSET a -2 5
# OK
LRANGE a 0 -1
# "1" "5" "3"
LSET a 3 6
# (error) ERR index out of range
往列表中插入元素
LINSERT key BEFORE|AFTER pivot value
LINSERT指令,从左到右,找到值为pivot
的元素,并将值value
插入到pivot
之前(BEFORE),或之后(AFTER);如果pivot
在列表中有多个,则从左找到的第一个进行插入。
当
pivot
元素存在于列表中,插入完成,返回插入后的列表长度当
pivot
不存在时,返回-1
当
key
不存在时,返回0
如果要操作的
key
存在,且不是列表,则异常
LRANGE a 0 -1
# "1" "5" "3"
LINSERT a AFTER 5 4
# (integer) 4
LRANGE a 0 -1
# "1" "5" "4" "3"
LINSERT a BEFORE 5 4
# (integer) 5
LRANGE a 0 -1
# "1" "4" "5" "4" "3"
LINSERT a BEFORE 4 6 # 有多个4,从左边找到第一个4,进行插入操作
# (integer) 6
LRANGE a 0 -1
# "1" "6" "4" "5" "4" "3"
LINSERT a BEFORE 0 23 # 未找到0,返回-1
# (integer) -1
LINSERT aa BEFORE 1 1 # aa不存在,返回0
# (integer) 0
列表裁剪指令LTRIM
LTRIM key start stop
LTRIM指令对一个列表进行删除指定范围(start
和stop
)之外的所有元素,最终保留为start
至stop
之间的元素,包括start
和stop
位置的元素。不在这个范围的元素都将被删除。
start
、stop
取值从0开始到末尾,可以为负值,表示从右侧开始,-1
为最右侧元素当
start > stop
时,将清空所有的元素
LRANGE a 0 -1
# "1" "6" "4" "5" "4" "3"
LTRIM a 1 4
# OK
LRANGE a 0 -1
# "6" "4" "5" "4"
LTRIM a -3 -2
# OK
LRANGE a 0 -1
# "4" "5"
LTRIM a 1 0
# OK
LRANGE a 0 -1
(empty list or set)
移动列表最后一个元素到新列表RPOPLPUSH
RPOPLPUSH source destionation
RPOPLPUSH指令,将从一个列表末尾(最右侧)弹出一个元素,并加入到目标列表的左侧;并返回该元素的值。这个过程是原子的。当源列表为空时,执行该指令,将不发生弹出和压入操作,返回空。
LRANGE a 0 -1
# "3" "2" "1"
RPOPLPUSH a b
# "1"
LRANGE a 0 -1
# "3" "2"
LRANGE b 0 -1
# "1"