Redis列表(list)阻塞命令说明

上一篇文章 Redis列表(list)使用 中介绍的命令,都是会立即到数据库中进行操作处理,并返回结果信息,均为非阻塞式命令。Redis的列表中有3个阻塞式命令,blpop(阻塞式左端弹出操作)、brpop(阻塞式右端弹出操作)和brpoplpush(阻塞式弹出并推入操作)命令。阻塞式命令,顾名思义,命令执行过程中会产生阻塞效果。具体情况,下面来看。

blpop:阻塞式左端弹出操作

blpop命令是带有阻塞式功能的左端弹出操作,它接受任意多个列表以及一个秒级精度的超时时间作为参数

blpop list [list ...] timeout

blpop命令会按照从左到右的顺序依次检查用户给定的列表,并对最先遇到的非空列表执行左端元素弹出操作。如果blpop命令在检查了用户给定的所有列表之后都没有发现可以执行弹出操作的非空列表,那么它将阻塞执行该命令的客户端并开始等待,直到某个给定列表变为非空,或者等待时间超出给定时限为止。

当blpop命令成功对某个非空列表执行了弹出操作之后,它将向用户返回一个包含两个元素的数组:

  • 数组的第一个元素记录了执行弹出操作的列表,即被弹出元素的来源列表
  • 数组的第二个元素则是被弹出元素本身。

下面示例,展示blpop命令的使用方法

上图示例中,向列表ll 中推入元素 c b a,列表非空。使用blpop ll 3 命令弹出ll列表中左端的元素a,如果列表中没有元素,则阻塞3秒钟。

如果客户使用的是redis-cli 客户端,并且在执行blpop命令的过程中曾经被阻塞过,那么客户端还会将被阻塞的时长也打印出来。注意这里展示的阻塞时长只是redis-cli 客户端为了方便用户而添加的额外信息,blpop命令返回的结果本身并不包含这一信息。

通过示例来看

扫描二维码关注公众号,回复: 12685219 查看本文章

我们使用的是redis-cli客户端,看到blpop ll 20命令阻塞了9.03秒

解除阻塞状态

正如前面所说,当blpop命令发现用户给定的所有列表都为空时,就会让执行命令的客户端进入阻塞状态,如果在客户端被阻塞的过程中有另一个客户端,向导致阻塞的列表推入了新的元素,那么该列表就会变为飞空,而被阻塞的客户端也会随着捕捞泡沫命令成功弹出元素而重新回到非阻塞状态。
下图示例展示了一个客户端从被阻塞到解除阻塞的整个过程。

根据图例


如果在同一时间有多个客户端,因为同一个列表而被阻塞,那么当导致阻塞的列表变为非空时服务器将按照先阻塞先服务的规则,依次为被阻塞的各个客户端弹出列表元素。
如下图实例展示了一个服务器,按照先组色先服务规则处理被阻塞客户端的例子,在这个例子中ABC这三个客户端先后执行了blpop ll 30,并且都因为列表为空而被阻塞,如果在这些客户端被阻塞期间客户端D执行了命令,那么服务器首先会处理客户端a的blpop命令,并将被弹出的元素返给它;接着处理客户端B的blpop命令,并将被弹出的元素返给它;最后处理客户端C的blpop命令,并将被弹出的元素返回给它。

最后如果被推入列表的元素数量少于被阻塞的客户端数量,那么先被阻塞的客户端将会先解除阻塞而未能解除阻塞的客户端,则需要继续等待,下次推入操作,比如如果有5个客户端因为列表为空而被阻塞,但是推入列表的元素只有三个,那么最先被注册了,三个客户端将会解除阻塞状态,而剩下两个客户端则会继续阻塞。

处理空列表


如果用户blpop后,命令传入的所有列表都是空列表,并且这些列表在给定的时限之内一直没有变化,成为非空列表,那么blpop命令将在给定时限到达之后,向客户端返回一个空值,表示没有任何元素被弹出。

列表名的作用


blpop命令之所以会返回被弹出元素的来源列表,是为了让用户在传入多个列表的情况下,知道被弹出的元素来源于哪个列表
比如在以下这个事例中通过不了靠谱命令的回复,我们可以知道被弹出的元素来自于列表2而不是列表1或者列表3。

阻塞效果的范围

blpop命令的阻塞效果只对执行这个命令的客户端有效,其他客户端以及Redis服务器本身并不会因为这个命令而被阻塞。

brpop:阻塞式右端弹出操作

brpop命令是右端弹出操作,除了弹出的方向不同之外,其他方面都和blpop命令一样。
brpop list [list ...] timeout

brpoplpush:阻塞式弹出并推入操作

brpoplpush命令是rpoplpush命令的阻塞版本。brpoplpush接受一个源列表,一个目标列表以及一个秒级精度的超时时间作为参数。

brpoplpush source-list target-list timeout

根据原列表是否为空命令会产生以下两种行为:

  • 如果源列表非空那么brpoplpush命令的行为就和rpoplpush命令的行为一样命令会弹出位于原列表最右端的元素,并将该元素推入目标列表的左端,最后向客户端返回被弹出的元素。
  • 如果源列表为空,那么brpoplpush命令将阻塞执行该命令的客户端,然后在给定的时间内等待可弹出的元素出现,或者等待时间超过给定时限为止。

下面通过示例看一下brpoplpush命令的用法,有列表list1 和 list2,其中list1 含有一个元素 "hello",list2 含有元素a b c 

如果对list1和list2作为输入执行brpoplpush命令,由于源列表list1非空,所以brpoplpush命令将不阻塞执行,效果类似rpoplpush命令一样

接着,继续执行brpoplpush命令,由于list1为空,那么客户端将被阻塞,直到在另一个客户端向list1推入新元素为止

此时,查看list1 和 list2

处理源列表为空的情况

如果源列表在用户给定的时限内一直没有元素可供弹出,那么brpoplpush命令将向客户端返回一个空值nil,以此来表示此次操作没有弹出和推入任何元素。
与brpop和blpop命令一样,redis-cli客户端也会显示brpoplpush的阻塞时长。

 blpop、brpop和brpoplpush是阻塞版本的弹出和推入命令,如果用户给定的所有列表都为空,那么执行命令的客户端将被阻塞直到给定的阻塞时限到达或者给某个给定列表非空为止。

猜你喜欢

转载自blog.csdn.net/magi1201/article/details/113757966