目录
目标
列举redis中与list相关的指令,包括作用、使用时需要注意的地方等。对于某些基本用不到的指令仅一带而过。
BLPOP
BLPOP key [key ...] 秒timeout
O(1)
阻塞队列的POP原语。如果检查key对应的所有队列都没有元素,则阻塞该连接。如果有元素,则从head即左侧删除并返回一个元素。
非阻塞行为
对于非空队列,将立刻返回。例如BLPOP list1 list2 list3 0,检查list1为空,list2和list3非空,则返回第一个非空集合-list2中元素
阻塞行为
如果所有key都不存在或者所有队列都是空的,则阻塞当前连接。如果之后任意队列进入新元素,则立刻返回key和元素。timeout为0表示不设置超时,一直阻塞。如果超时到了仍无数据,则返回null。
哪个key、client、元素优先处理
client端:client开始阻塞多key,client将会从左到右检查key,选出第一个具有元素的key并返回;如果都没有数据则阻塞。
BLPOP key1 key2 key3 key4 0
key2 和 key4有元素
返回key2和其中一个元素
server端:多个client阻塞同一个key,可理解为在server端维护一个client等待FIFO队列,队首等待时间最长,队尾等待时间最短。每次将一个元素交给队首client并移出队列,即获取元素后该client不再阻塞,之后其再次BLPOP,将进入队尾。
保证了阻塞list中一个元素只会被一个client处理。
server端:一个client阻塞多个key,这些key同时具有可用元素,server端根据接收数据的顺序维护key的list,则选择第一个接收到push命令的key提供元素,直到empty,之后选择第二个接收到push命令的key。
当多个元素push到list,BLPOP如何处理
Client A: BLPOP foo 0
Client B: LPUSH foo a b c
redis 2.6+
LPUSH执行后,list内容从左到右为c b a
BLPOP从左开始取元素,即获取到元素的顺序为c b a
不要在事务中使用BLPOP
结合redis事务支持原子性和隔离性考虑,BLPOP会阻塞server,导致server无法提供服务。
可靠性
- BLPOP 元素从server删除并返回给client,可能问题client出问题,则元素丢失。
- 使用BRPOPLPUSH,元素返回给client前,被添加到另一个list中。
使用场景:事件通知
BRPOP
BRPOP key [key ...] timeout
O(1)
阻塞队列的POP原语。如果检查key对应的所有队列都没有元素,则阻塞该连接。如果有元素,则从tail即右侧删除并返回一个元素。
其他信息参考BLPOP
LPOP key
从list head删除并返回第一个元素
O(1)
若key不存在返回null
RPOP key
从list tail删除并返回第一个元素
RPOPLPUSH
RPOPLPUSH source destination
O(1)
source list的tail删除一个元素,添加到dest list的head,返回元素。
举例
source list:a b c
dest list: x y z
执行一次RPOPLPUSH
source list : a b
dest list: c x y z
若source不存在或无数据,则返回null。
若source和dest相同,则从list tail取数据,添加到list head,形成list的自旋操作
可靠队列
使用LPOP RPOP BLPOP BRPOP,由于网络或client问题,可能出现数据丢失问题。
可靠性方案:使用RPOPLPUSH BRPOPLPUSH取数据,client处理,LREM删除dest中元素。也可使用另一个redis client对dest进行检查,对长时间未删除的元素进行处理,如再次放到source中。
循环队列
当source和dest相同时,可形成循环队列。
一个client可one by one的访问list中所有元素,而不用一次性取部分元素。
多个client可共同访问list,每个元素都可被一个client处理,所有元素处理后,可开始新一轮处理。
允许其他client向list tail加元素
适合场景:一批元素需要被多个client尽可能快的持续处理。
如需要持续监测一批网络地址是否可访问
BRPOPLPUSH
BRPOPLPUSH source destination timeout
O(1)
RPOPLPUSH的阻塞形式
LPUSH
LPUSH key value [value ...]
O(1)
向list head添加元素,多个元素时,会逐个添加到head。
当key不存在时,先新建list。若key对应val不是list,则error
LPUSH key a b c,则list数据为c b a
返回push后,list中元素个数
RPUSH
LPUSHX
LPUSHX key value
O(1)
仅当key存在且对应val为list时,向list head添加元素。
返回push后,list中元素个数
RPUSHX
LREM
LREM key count value
O(N) N:list中元素个数
从list中删除count数量的数据等于value的元素
count影响操作行为
count > 0
从head到tail进行遍历与删除
count < 0
从tail到head进行遍历与删除
count = 0
删除所有等于value的元素
返回已经删除元素个数。如果key不存在或无元素,返回0
例子
list: a b a d a
LREM list -2 a
list : a b d
LSET
LSET key index value
O(N) N:list中元素数量
设置index位置元素的数据,越界则error
举例
list : a b c d
LSET list 1 a
list : a a c d
LSET list -2 a
list : a a a d
LTRIM
LTRIM key start stop
O(N) N:删除元素数量
仅保留特定范围内元素,其他元素均清除。based-0 index,index可负。
越界
start越界或start>stop,将删除key
stop越界,则将边界视为stop
返回OK
场景:list仅保留固定数量元素
LTRIM与LPUSH/RPUSH组合使用,达到list仅保留固定范围元素的目标
如list中最多存储100个元素
LPUSH mylist someelement
LTRIM mylist 0 99
redis存储固定数量的log
时间复杂度为O(1),因为巨大多数情况只会删除tail第一个元素。
LINSERT
LINSERT key BEFORE|AFTER pivot value
O(N) N:从左开始遍历的元素个数
从左侧开始遍历定位pivot,然后在其前或后插入val
返回插入后list的长度,若pivot不存在返回-1
LRANGE
LRANGE key start stop
O(S+N) S:距离start位置的偏移量,如果是小队列则为从head开始的偏移量,若果是大型list则为从距离近的端点(head or tail)开始的偏移量.。 N:区间元素个数
读取符合start stop范围的元素,based-0 index,不影响list结构。
index>=0,则从head(左)开始取,0表示左侧第一个
index<0,则从tail(右)开始取,-1表示右侧第一个
越界
start越界,返回empty list
stop越界,返回start到边界的元素list
LINDEX
LINDEX key index
O(N) N:读取第index元素,需要遍历的元素个数。tail或head则O(1)
index>=0,则从head(左)开始取,0表示左侧第一个
index<0,则从tail(右)开始取,-1表示右侧第一个
返回值
返回定位的元素
key对应val不是list,返回error
index越界,返回null
LLEN
LLEN key
O(1)
返回list长度,如果key不存在返回0,如果key对应val不是list返回error