redis 列表

Jackey Redis 2,722 次浏览 , , 没有评论

列表(list)

一个列表可以包含一个或以上数量的 项(item),每个项按照它们被推入到列表的位置来排列。

每个列表项所处的位置决定了这个项的索引值(index),索引以 0 为开始,从列表的左端到右端依次 递增,位于列表最左端(表 头)的项的索引为 0 ,而位于列表最右端(表尾)的 项的索引为 N-1 ,其中 N 为列表的长度。

列表包含的项可以出现重复,它们不必是唯一的。

从列表的左端推入值

LPUSH key value [value ...]
将一个或以上数量的值依次推入到列表的左端,命令返回新 值被推入之后,列表目前包含的 项数量。
复杂度为 O(N) ,其中 N 为被推入值的数量,如果只推入一个 值,那么命令的复杂度为 O(1) 。
redis> LPUSH lst "Lua"
(integer) 1
redis> LPUSH lst "Python"
(integer) 2
redis> LPUSH lst "C"
(integer) 3

从列表的左端推入多个值

如果执行 LPUSH 命令时给定了多个值,那么各个值将按照给定时的顺序,从左到右依次地被推入到列表的左端。
举个例子,执行命令:
redis> LPUSH lst "Lua" "Python" "C"
(integer) 3
和依次执行以下三个命令的效果一 样:
LPUSH lst "Lua"
LPUSH lst "Python"
LPUSH lst "C"

提示
值被推入的顺序和参数给定的顺序正好相反!

从列表的右端推入值

RPUSH key value [value ...]
将一个或以上数量的值依次推入到列表的右端,命令返回新 值被推入之后,列表目前包含的 项数量。
复杂度为 O(N) ,其中 N 为被推入值的数量,如果只推入一个 值,那么命令的复杂度为 O(1) 。
redis> RPUSH lst "Clojure"
(integer) 1
redis> RPUSH lst "Ruby"
(integer) 2
redis> RPUSH lst "C"
(integer) 3

从列表的右端推入多个值

如果执行 RPUSH 命令时给定了多个值,那么各个值将按照给定时的顺序,从左到右依次地被推入到列表的右端。
举个例子,执行命令:
redis> RPUSH lst "Clojure" "Ruby" "C"
(integer) 3
和依次执行以下三个命令的效果一 样:
RPUSH lst "Clojure"
RPUSH lst "Ruby"
RPUSH lst "C"
提示
值被推入的顺序和参数给定的顺序正好相同!

从列表的两端弹出项

LPOP key 移除并返回列表最左端的 项。
RPOP key 移除并返回列表最右端的 项。

redis> RPUSH lst "Clojure" "Ruby" "C" "Python" "Lua"
(integer) 5
redis> LPOP lst
"Clojure"
redis> LPOP lst
"Ruby"
redis> RPOP lst
"Lua"
redis> RPOP lst
"Python"

获取列表的长度

LLEN key
返回列表键 key 的长度,也即是,返回列表包含的列表 项数量。
因为 Redis 会记录每个列表的长度,所以这个命令无须遍历列表,它的复杂度为 O(1) 。
redis> LLEN lst
(integer) 5
redis> LPOP lst
"Clojure"
redis> LLEN lst
(integer) 4

返回给定索引上的项

LINDEX key index
返回列表键 key 中,指定索引 index 上的列表项。index 索引可以是正数或者负数。
复杂度为 O(N) ,N 列表的长度。


redis> LINDEX lst 1
"Ruby"
redis> LINDEX lst 4
"Lua"
redis> LINDEX lst -3
"C"

返回给定索引范围之内的所有项

LRANGE key start stop
返回列表键 key 中,从索引 start 至索引 stop 范围内的所有列表项。两个索引参数都可以是正数或者负数。
复杂度为 O(N) , N 为被返回的列表项数量。
redis> LRANGE lst 0 2
1) "Clojure"
2) "Ruby"
3) "C"
redis> LRANGE lst -3 -1
1) "C"
2) "Python"
3) "Lua"

设置指定索引上的列表项

LSET key index value
将列表键 key 索引 index 上的列表项设置为value ,设置成功时命令返回 OK 。
如果 index 参数超过了列表的索引范围,那么命令返回一个错误。
针对表头和表尾节点进行处理时(index 为 0 或者 -1),命令的复杂度为 O(1) ;其他情况下,命令的复
杂度为 O(N) ,N 为列表的长度。
redis> RPUSH lst "Clojure" "Ruby" "C" "Python" "Lua"
(integer) 5
redis> LSET lst 0 "Common Lisp"
OK

在指定位置插入列表项

LINSERT key BEFORE|AFTER pivot value
根据命令调用时传递的是 BEFORE 选项还是 AFTER 选项,将值 value 插入到指定列表项 pivot 的之前或者之后。当 pivot 不存在于列表 key 时,不执行任何操作。
返回 -1 表示 pivot 不存在;返回 0 表示键 key 不存在;插入成功时则返回列表当前的长度。
复杂度为 O(N) ,N 为列表长度。
redis> RPUSH lst "Clojure" "C" "Python" "Lua"
(integer) 4
redis> LINSERT lst BEFORE "C" "Ruby"
(integer) 5

从列表中删除指定的值

LREM key count value
根据参数 count 的值,移除列表中与参数 value 相等的列表项:
• 如果 count > 0 ,那么从表头开始向表尾搜索,移除最多 count 个值为 value 的列表项。
• 如果 count < 0 ,那么从表尾开始向表 头搜索,移除最多 abs(count) 个值为 value 的列表项。
• 如果 count = 0 ,那么移除列表中所有 值为 value 的列表项。
命令返回被移除列表项的数量。
命令的复杂度为 O(N) ,N 为列表的长度

redis> RPUSH lst "app" "zoo" "spam"
"app" "zoo" "egg" "app"
(integer) 7
redis> LREM lst 0 "zoo"
(integer) 2
redis> LREM lst 1 "app"
(integer) 1
redis> LREM lst -1 "app"
(integer) 1

修剪列表

LTRIM key start stop
对一个列表进行修剪(trim),让列表只保留指定索引范 围内的列表项,而将不在范围内的其他列表项全部删除。两个索引都可以是正数或者 负数。
命令执行成功时返回 OK ,复杂度为 O(N) ,N 为被移除列表项的数量。
redis> RPUSH lst "Clojure" "Ruby" "C" "Python" "Lua"
(integer) 5
redis> LTRIM lst 0 2
OK

阻塞弹出命令

BLPOP key [key ...] timeout

LPOP 命令的阻塞版本;命令会以从左到右的顺序,访问给定的各个列表,并弹出首个非空列表最左端的项;如果所有给定列表都为空,那么客户端将被阻塞,直到等待超时,或者有可弹出的项出现为止;
设置 timeout 参数为 0 表示永远阻塞。

BRPOP key [key ...] timeout

RPOP 命令的阻塞版本:命令会以从左到右的顺序,访问给定的各个列表,并弹出首个非空列表最右端的项;如果所有给定列表都为空,那么客户端将被阻塞,直到等待超时,或者有可弹出的项出现为止;
设置 timeout 参数为 0 表示永远阻塞。

redis> BLPOP empty-1 empty-2 empty-3 5 # 命令依次访问三个列表,发现它们都为空,于是阻塞
(nil) # 返回 nil 表示等待超时
(5.07s) # 客户端被阻塞的时长
redis> RPUSH lst "one" "two" "three"
(integer) 3
redis> BLPOP empty-1 empty-2 lst empty-3 5 # 命令发现 lst 非空,于是弹出
1) "lst" # 执行弹出操作的列表
2) "one" # 被弹出的项
redis> BLPOP empty-1 empty-2 empty-3 5 # 在阻塞的过程中,有列表可以执行弹出操作
1) "empty-3" # 执行弹出操作的列表
2) "hello" # 被弹出的项
(1.84s) # 客户端被阻塞的时长

BLPOP/BRPOP 的先到先服务原则

如果有多个客户端同时因为某个列表而被阻塞,那么当有新 值被推入到这个列表时,服务器会按照先到先服务(first in first service)原则,优先向最早被阻塞的客户端返回新值。

举个例子,假设列表 lst 为空,那么当客户端 X 执行命令 BLPOP lst timeout 时,客户端 X 将被阻塞。

在此之后,客户端 Y 也执行命令 BLPOP lst timeout ,也因此被阻塞。

如果这时,客户端 Z 执行命令 RPUSH lst "hello" ,将值 "hello" 推入列表 lst ,那么这个 "hello" 将被返回给客户端 X ,而不是客户端 Y ,因为客户端 X 的被阻塞时间要早于客户端 Y 的被阻塞时间。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Go