首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

blpop

代码语言:javascript
复制
BLPOP key [key ...] timeout

自2.0.0起可用。

时间复杂度: O(1)

BLPOP是一个阻塞列表pop元素。它是LPOP的阻塞版本,因为它在没有任何元素从给定列表中弹出时阻塞连接。一个元素从第一个非空列表的头部弹出,并按给定的顺序检查给定的键。

非阻塞行为

当调用BLPOP时,如果至少有一个指定键包含非空列表,则会从列表头部弹出一个元素,并将其从弹出的列表中弹出并返回给调用者key

按照它们给出的顺序检查密钥。假设该键list1不存在list2并且list3保存非空列表。考虑下面的命令:

代码语言:javascript
复制
BLPOP list1 list2 list3 0

BLPOP保证从列表中存储的列表中返回一个元素list2(因为它是检查时的第一个非空列表list1list2并按此list3顺序)。

阻止行为

如果没有指定的密钥存在,则BLPOP将阻止该连接,直到另一个客户端对其中一个密钥执行LPUSH或RPUSH操作。

一旦在其中一个列表上出现新数据,客户端将返回解锁它的密钥名称和弹出的值。

当BLPOP导致客户端阻塞且指定了非零超时时,客户端将nil在指定超时过期时解除阻止返回多批量值,而不对至少一个指定键执行推送操作。

超时参数被解释为指定要阻止的最大秒数的整数值。可以使用零超时来无限期地阻塞。

什么关键是先服务?什么客户?什么元素?优先顺序细节。

  • 如果客户端试图阻塞多个密钥,但至少有一个密钥包含元素,则返回的密钥/元素对是从左到右具有一个或多个元素的第一个密钥。在这种情况下,客户端不会被阻止。因此,举例来说BLPOP key1 key2 key3 key4 0,假设两key2key4非空,将总是返回从一个元素key2
  • 如果同一个密钥阻塞了多个客户端,则要服务的第一个客户端是等待更多时间的客户端(为该密钥阻塞的第一个客户端)。一旦客户端被解除封锁,它不保留任何优先权,当它再次阻止下一次BLPOP调用时,它将被相应地服务于已经被相同密钥阻塞的客户端的数量,这将在它之前被服务(从第一个到最后被阻止)。
  • 当客户端同时阻塞多个密钥并且多个密钥中同时有元素时(由于事务或Lua脚本向多个列表添加元素),客户端将使用第一个密钥解除阻塞(假设它有足够的元素为我们的客户提供服务,因为可能有其他客户也在等待此密钥)。基本上,在执行每条命令之后,Redis将运行接收数据并且至少有一个客户端被阻止的所有密钥的列表。该列表按新元素到达时间排序,从接收数据的第一个密钥到最后一个密钥。对于每个已处理的密钥,只要该密钥中包含元素,Redis将以FIFO方式为所有等待该密钥的客户端提供服务。当密钥为空或者不再有客户端等待该密钥时,

多个元素在列表中被推入时BLPOP的行为。

有时候,一个列表可以在相同的概念性命令的上下文中接收多个元素:

  • Variadic推送操作LPUSH mylist a b c
  • 在对同一列表执行多个推动操作的MULTI块的EXEC后。
  • 使用Redis 2.6或更新版本执行Lua脚本。

当有多个客户端阻塞的列表中推入多个元素时,Redis 2.4和Redis 2.6或更新版本的行为是不同的。

对于Redis 2.6来说,执行多次推送的命令会被执行,并且只有在被阻止的客户端执行命令后才会执行。考虑这个命令序列。

代码语言:javascript
复制
Client A:   BLPOP foo 0
Client B:   LPUSH foo a b c

如果使用Redis 2.6或更高版本的服务器发生上述情况,则客户端A将与该c元素一起提供服务,因为在该列表包含LPUSH命令之后c,b,a,因此从左边取一个元素意味着返回c

相反,Redis 2.4以不同的方式工作:客户端在推送操作的上下文中服务,因此只要LPUSH foo a b c开始将第一个元素推送到列表中,它就会被传送到客户端A,客户端A将接收a(第一个元素被推送)。

Redis 2.4的行为在将数据复制或保存到AOF文件时产生了很多问题,因此在Redis 2.6中引入了更通用和语义更简单的行为,以防止出现问题。

请注意,出于同样的原因,Lua脚本或MULTI/EXEC块可能会将元素推入列表中,然后删除列表。在这种情况下,只要在执行单个命令,事务或脚本后没有数据出现在列表中,被阻止的客户端根本就不会被服务,并且将继续被阻止。

BLPOPMULTI/ EXEC交易中

BLPOP可以与流水线一起使用(发送多个命令并批量读取响应),但是这种设置几乎完全在它是流水线的最后一个命令时才有意义。

在MULTI / EXEC模块中使用BLPOP没有多大意义,因为它需要阻塞整个服务器以便以原子方式执行该模块,而这又不允许其他客户端执行推送操作。出于这个原因,当列表为空时,MULTI / EXEC中的BLPOP行为是返回一个nil多批量回复,这与达到超时的时候发生的情况是一样的。

如果你喜欢科幻小说,想想在MULTI / EXEC块内以无限速度流动的时间......

返回值

阵列回复:具体为:

  • nil当没有元件可以被弹出多批量和超时过期。
  • 第一个元素是元素被弹出的键的名称,第二个元素是弹出元素的值的两元素的多块。

例子

代码语言:javascript
复制
redis> DEL list1 list2
(integer) 0
redis> RPUSH list1 a b c
(integer) 3
redis> BLPOP list1 list2 0
1) "list1"
2) "a"

可靠的队列

当BLPOP向客户端返回一个元素时,它也从列表中删除该元素。这意味着该元素只存在于客户端的上下文中:如果客户端在处理返回的元素时崩溃,它将永远丢失。

对于某些需要更可靠的消息传递系统的应用程序,这可能会造成问题。当出现这种情况时,请检查BRPOPLPUSH命令,这是BLPOP的一种变体,它在将返回元素返回给客户机之前将其返回的元素添加到目标列表中。

模式:事件通知

使用阻塞列表操作可以挂载不同的阻塞原语。例如,对于某些应用程序,您可能需要阻止将元素等待到Redis集中,以便只要将新元素添加到Set中,就可以检索它,而无需通过轮询。这将需要SPOP的阻止版本不可用,但使用阻止列表操作,我们可以轻松完成此任务。

使用者会这样做:

代码语言:javascript
复制
LOOP forever
    WHILE SPOP(key) returns elements
        ... process elements ...
    END
    BRPOP helper_key
END

在生产者方面,我们将简单地使用:

代码语言:javascript
复制
MULTI
SADD key element
LPUSH helper_key x
EXEC

扫码关注腾讯云开发者

领取腾讯云代金券