Redis.列表


列表

  • 列表的基本操作
  • BLPOP/BRPOP 的先到先服务原则
  • 使用消息队列解耦消息发布和消息推送操作

一个列表可以包含一个或以上数量的项(item),每个项按照它们被推入到列表的位置来排列。
每个列表项所处的位置决定了这个项的索引值(index),索引以 0 为开始,从列表的左端到右端依次递增,位于列表最左端(表头)的项的索引为
0 ,而位于列表最右端(表尾)的项的索引为 N-1 ,其中 N 为列表的长度。
列表包含的项可以出现重复,它们不必是唯一的。常用的操作是向列表两端添加元素或者获得列表的某一个片段。
列表内部使用双向链表实现的,所以向两端添加元素的复杂度为0(1)。访问元素则很慢,需要遍历。

列表的基本操作

LPUSH key value

从列表的左端推入值
将一个或以上数量的值依次推入到列表的左端,命令返回新值被推入之后,列表目前包含的项数量。
复杂度为 O(N) ,其中 N 为被推入值的数量,如果只推入一个值,那么命令的复杂度为 O(1) 。
如果执行 LPUSH 命令时给定了多个值,那么各个值将按照给定时的顺序,从左到右依次地被推入到列表的左端。

RPUSH key value

从列表的右端推入值
将一个或以上数量的值依次推入到列表的右端,命令返回新 值被推入之后,列表目前包含的项数量。
复杂度为 O(N) ,其中 N 为被推入值的数量,如果只推入一个值,那么命令的复杂度为 O(1) 。
如果执行 RPUSH 命令时给定了多个值,那么各个值将按照给定时的顺序,从左到右依次地被推入到列表的右端。

LPOP key

移除并返回列表最左端的项。复杂度为 O(1)

RPOP key

移除并返回列表最右端的项。复杂度为 O(1)

LLEN key

获取列表的长度
返回列表键 key 的长度,也即是,返回列表包含的列表 项数量。因为 Redis 会记录每个列表的长度,所以这个命令无须遍历列表,它的复杂度为
O(1) 。

LINDEX key index

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

LRANGE key start stop

返回给定索引范围之内的所有项
返回列表键 key 中,从索引 start 至索引 stop 范围内的所有列表项。两个索引参数都可以是正数或者负数。复杂度为 O(N) , N
为被返回的列表项数量。

LSET key index value

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

LINSERT key BEFORE|AFTER pivot value

在指定位置插入列表项
根据命令调用时传递的是 BEFORE 选项还是 AFTER 选项,将值 value 插入到指定列表项 pivot 的之前或者之后。
当 pivot 不存在于列表 key 时,不执行任何操作。返回 -1 表示 pivot 不存在;返回 0 表示键 key 不存在;插入成功时则返回列表当前的长度。复杂度为
O(N) ,N 为列表长度。

LREM key count value

从列表中删除指定的值
命令返回被移除列表项的数量。 命令的复杂度为 O(N) ,N 为列表的长度。
根据参数 count 的值,移除列表中与参数 value 相等的列表项:

  • 如果 count > 0 ,那么从表头开始向表尾搜索,移除最多 count 个值为 value 的列表项。
  • 如果 count < 0 ,那么从表尾开始向表头搜索,移除最多 abs(count) 个值为 value 的列表项。
  • 如果 count = 0 ,那么移除列表中所有值为 value 的列表项。
LTRIM key start stop

修剪列表
对一个列表进行修剪(trim),让列表只保留指定索引范围内的列表项,而将不在范围内的其他列表项全部删除。两个索引都可以是正数或者负数。命令执行成功时返回
OK ,复杂度为 O(N) ,N 为被移除列表项的数量。

BLPOP key timeout

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

BRPOP key timeout

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

BLPOP/BRPOP 的先到先服务原则

如果有多个客户端同时因为某个列表而被阻塞,那么当有新值被推入到这个列表时,服务器会按照<code>先到先服务</code>(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 的被阻塞时间。

使用消息队列解耦消息发布和消息推送操作

为了解决这个问题,每当用户发送消息的时候,程序都会将这条消息放入到一个消息队列(message
queue)里面,然后由专门的服务器在后台负责将这条消息推送给所有关注者。

注意消息队列也是一个 FIFO 队列,因为它需要优先处理推入时间最长的消息。这种做法有几个好处:

  • web 服务器可以在保存好用户发布的消息、并将消息推入到队列之后,立即返回,这样 web 服务器就可以以最快的速度对用户进行响应。
  • web 服务器不会被消息推送操作影响,这有助于提升效率和简化程序逻辑。
  • 因为推送操作由专门的消息服务器负责,所以我们可以针对性地进行优化。通过使用 Redis 的列表键,以及阻塞弹出操作,我们也可以构建类似的消息队列。

声明:Rock 版权所有,内容均为原创,欢迎转载。

转载:转载请注明原文链接 - Redis.列表


我是一个程序员,致力于网页开发,我还很年轻,什么也不懂。