• 2021-05-17更新:增加Redis 6.2新增的LMOVEBLMOVE命令。

在前文中,我们已经介绍了Redis列表相关的LPUSHLPOP等命令。在本文中,我将继续介绍Redis中列表的LTRIMRPOPLPUSHBLPOPBRPOPBRPOPLPUSHLPOS以及Redis 6.2新增的LMOVE以及BLMOVE命令。

从Redis 6.2.0开始,RPOPLPUSH以及BRPOPLPUSH命令将考虑被启用,请分别使用LMOVE以及BLMOVE替代。

LTRIM

LTRIM命令用于对列表进行修建,即只保留指定范围内的部分元素。指定范围的偏移量startstop都为以0为开始,即索引0为列表中的第一个元素,负数值表示相对于列表队尾的位置(如-1代表列表中最后一个元素)。例如命令LTRIM mykey 0 4在执行后只保留列表中的前五个元素,其它元素将被删除。

LTRIM key start stop

start的值大于列表的长度或start大于stop时,结果将为一个空列表。若stop大于列表的长度,其值将被设置为列表最后一个元素的索引值。

在Redis文档中提到了使用LTRIMLPUSHRPUSH命令配合使用,将达到使列表长度保持在指定大小内的效果,例如执行下述命令时,将使mylist列表的长度始终保持在100以内(包括100)。

redis> LPUSH mylist someelement
redis> LTRIM mylist 0 99

示例

redis> RPUSH mykey "value1" "value2" "value3" "value4" "value5"
(integer) 5
redis> LTRIM mykey 1 -2
OK
redis> LRANGE mykey 0 -1
1) "value2"
2) "value3"
3) "value4"

处理超出边界的情况:

redis> RPUSH mykey "value1" "value2" "value3" "value4" "value5"
(integer) 5
# stop大于列表大小
redis> LTRIM mykey 2 10
OK
redis> LRANGE mykey 0 -1
1) "value3"
2) "value4"
3) "value5"
# start与stop皆大于列表大小
redis> LTRIM mykey 5 10
OK
redis> LRANGE mykey 0 -1
(empty array)

RPOPLPUSH

RPOPLPUSH命令用于将source所指定的列表中队尾位置的元素移除,并插入到destination所指定的列表队首位置。该命令执行后将返回从source中移除并插入到destination中的元素。

RPOPLPUSH source destination

source所指定的列表不存在,将返回nil且不执行其它操作。若destination所指定的列表不存在,则将创建一个空队列并执行插入操作。

sourcedestination相同,执行后的结果将为移除队尾的元素并插入到队首。

正如上文提到,从Redis 6.2.0开始RPOPLPUSH命令将考虑被弃用,请在新的代码实现中使用LMOVE代替。

示例

# mykey不存在
redis> RPOPLPUSH mykey newkey
(nil)
redis> RPUSH mykey "value1" "value2" "value3"
(integer) 3
redis> RPOPLPUSH mykey newkey
"value3"
redis> LRANGE newkey 0 -1
1) "value3"
redis> LRANGE mykey 0 -1
1) "value1"
2) "value2"
# 源键与目标键相同
redis> RPOPLPUSH mykey mykey
"value2"
redis> LRANGE mykey 0 -1
1) "value2"
2) "value1"

BLPOP / BRPOP

BLPOP命令是阻塞版的LPOP,当给定列表中无元素可被弹出时将阻塞连接,直到超时或有元素可被弹出。与LPOP不同的是,BLPOP可以给定多个键名,并将依次检查各个列表。若给定的键名中存在至少一个为非空列表,执行BLPOP将弹出并返回第一个非空列表中的队首元素。

BRPOP命令与BLPOP相似,即为阻塞版的RPOP操作,其与BLPOP的区别为存在非空列表时将从队尾弹出元素。

BLPOP key [key ...] timeout
BRPOP key [key ...] timeout

BLPOP/BRPOP参数中的timeout为一个以秒为单位的数值,用于表示阻塞的最长时间。当timeout的值为0时,表示将无限期地阻塞,直到有元素可被弹出。

BLPOP/BRPOP命令执行后将返回一个数组,其第一个元素为键名,第二个元素为被弹出的元素。当列表直到超时也无元素可被弹出时,返回nil

关于更多有关BLPOP/BRPOP命令的介绍,例如当使用LPUSH插入多个元素时或在MULTI/EXEC事务中的行为,可以参考BLPOP文档

示例

redis> BLPOP mykey 10
# 等待10秒后
(nil)
redis> RPUSH mykey "value1" "value2" "value3"
(integer) 3
redis> BLPOP mykey 10
1) "mykey"
2) "value1"

在执行BLPOP/BRPOP后在超时时间内在通过另外的客户端连接往列表中插入元素,示例中使用redis1redis2来区分不同的客户端连接:

redis1> BLPOP mykey 10
# redis2> LPUSH mykey "value"
# (integer) 1
1) "mykey"
2) "value"

给定的列表中存在非空列表:

# redis> LPUSH key2 "value2"
# redis> LPUSH key3 "value3"
redis> BRPOP key1 key2 key3 10
1) "key2"
2) "value2"

给定的列表中均为空列表,连接将被阻塞直到任一列表中插入元素:

redis1> BLPOP key1 key2 key3 10
# redis2> LPUSH key2 "value2"
# (integer) 1
1) "key2"
2) "value2"

示例中主要演示了BLPOP命令,除弹出的元素为队尾元素外,BRPOPBLPOP没有较大的区别。

BRPOPLPUSH

BRPOPLPUSH命令即阻塞版的RPOPLPUSH命令,当source指定的列表不为空时(列表中存在元素),其行为与RPOPLPUSH命令相同。

BRPOPLPUSH source destination timeout

若执行命令时列表不为空,执行操作后返回与RPOPLPUSH命令相同。若等待超时(在timeout时间内无元素可被弹出),则将返回nil及等待的时间。若在等待期间存在元素可被弹出,则在执行操作后返回一个数组,其中包括被弹出元素的值及等待的时间。

关于更多的信息,可参考RPOPLPUSH

正如上文提到,从Redis 6.2.0开始BRPOPLPUSH命令将考虑被弃用,请在新的代码实现中使用BLMOVE代替。

示例

redis> BRPOPLPUSH mykey newkey 10
# 等待10秒后
(nil)
(10.08s)
redis> RPUSH mykey "value1" "value2" "value3"
(integer) 3
redis> BRPOPLPUSH mykey newkey
"value3"
redis> LRANGE mykey 0 -1
1) "value1"
2) "value2"
redis> LRANGE newkey 0 -1
1) "value3"

当给定源列表为空时,将阻塞连接直到有元素可被弹出:

redis1> BRPOPLPUSH mykey newkey 10
# redis2> LPUSH mykey "value"
# (integer) 1
"value"
(2.34s)
redis1> LRANGE newkey 0 -1
1) "value"
redis1> LRANGE mykey
(empty array)

LPOS

LPOS命令返回列表中符合条件的元素的索引,返回的索引从0开始(即0为列表中的第一个元素。在未指定参数的情况下,默认从列表的队首开始扫描,直到找到符合的元素。

LPOS key element [RANK rank] [COUNT num-matches] [MAXLEN len]

LPOS有三个可选参数RANKCOUNT以及MAXLEN

  • RANK 获取第N个符合条件元素;
  • COUNT 获取的元素数量;
  • MAXLEN 只比较给定数量的元素。

LPOS现还未在stable版本中被添加(预计在6.0.6版本中被添加),我们仅对其作简单的介绍,若有兴趣对其深入了解,可参考LPOS文档

示例

redis> RPUSH mykey "value1" "value2" "value3" "value4" "value5"
(integer) 5
redis> LPOS mykey "value3"
(integer) 2
redis> LPOS mykey "value6"
(nil)

使用RANKCOUNT参数实现较为复杂的查询操作:

redis> RPUSH mykey "value1" "value2" "value3" "value1" "value3" "value1"
(integer) 6
# 获取第二个符合的元素
redis> LPOS mykey "value1" RANK 2
(integer) 3
# 获取前两个符合的元素
redis> LPOS mykey "value1" COUNT 2
1) (integer) 0
2) (integer) 3
# 从第二个符合的元素开始获取两个符合的元素
redis> LPOS mykey "value1" RANK 2 COUNT 2
1) (integer) 3
2) (integer) 5

使用MAXLEN参数限定检查的最大数量:

redis> RPUSH mykey "value1" "value2" "value3" "value1" "value3" "value1"
(integer) 6
redis> LPOS mykey "value1" COUNT 5 MAXLEN 4
1) (integer) 0
2) (integer) 3

LMOVE / BLMOVE

LMOVE是Redis 6.2.0中新增的命令,用于将源队列中首/尾元素插入到目标队列的队首/队尾位置,并返回从源队列中弹出并压入到目标队列中的元素。若源队列不存在,将返回nil,且不会插入任何元素到目标队列中。若源队列与目标队列为相同队列,该操作将只在该队列中进行。

LMOVE source destination LEFT|RIGHT LEFT|RIGHT

LMOVE命令将被用于替代RPOPLPUSH命令,RPOPLPUSH命令等同于LMOVE RIGHT LEFT

BLMOVELMOVE命令的阻塞版本,当源队列不为空时效果与LMOVE相同。当源队列为空时将等待timeout参数所指定的时间。同样,若timeout参数的值设置为0则为持续等待。

BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout

示例

redis> RPUSH list1 1 2 3 4 5
(integer) 5
redis> RPUSH list2 6 7
(integer) 2
redis> LMOVE list1 list2 LEFT RIGHT
"1"
redis> LRANGE list1 0 -1
1) "2"
2) "3"
3) "4"
4) "5"
redis> LRANGE list2 0 -1
1) "6"
2) "7"
3) "1"

结束语

我们已经介绍了字符串、列表以及键值对操作的一些命令。在后续的文章中,我们将继续介绍哈希以及集合类型的相关命令。

参考文献