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

BRPOPLPUSH 命令是 RPOPLPUSH 命令的阻塞版本,它接受一个源列表、一个目标列表以及一个秒级精度的超时时限作为参数:

  1. BRPOPLPUSH source target timeout

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

  • 如果源列表非空,那么 BRPOPLPUSH 命令的行为就和 RPOPLPUSH 命令的行为一样:BRPOPLPUSH 命令会弹出位于源列表最右端的元素,并将该元素推入到目标列表的左端,最后向客户端返回被推入的元素。

  • 如果源列表为空,那么 BRPOPLPUSH 命令将阻塞执行该命令的客户端,然后在给定的时限内等待可弹出的元素出现,又或者等待时间超过给定时限为止。

举个例子,假设现在有 list3list4 两个列表如下:

  1. client-1> LRANGE list3 0 -1
  2. 1) "hello"
  3.  
  4. client-1> LRANGE list4 0 -1
  5. 1) "a"
  6. 2) "b"
  7. 3) "c"

如果我们以这两个列表作为输入执行 BRPOPLPUSH 命令,由于源列表 list3 非空,所以 BRPOPLPUSH 命令将不阻塞直接执行,就像 RPOPLPUSH 命令一样:

  1. client-1> BRPOPLPUSH list3 list4 10
  2. "hello"
  3.  
  4. client-1> LRANGE list3 0 -1
  5. (empty list or set)
  6.  
  7. client-1> LRANGE list4 0 -1
  8. 1) "hello"
  9. 2) "a"
  10. 3) "b"
  11. 4) "c"

现在,由于 list3 为空,如果我们再次执行相同的 BRPOPLPUSH 命令,那么客户端 client-1 将被阻塞,直到我们从另一个客户端 client-2list3 推入新元素为止:

  1. client-1> BRPOPLPUSH list3 list4 10
  2. "world"
  3. (1.42s) -- 被阻塞了 1.42
  4.  
  5. client-1> LRANGE list3 0 -1
  6. (empty list or set)
  7.  
  8. client-1> LRANGE list4 0 -1
  9. 1) "world"
  10. 2) "hello"
  11. 3) "a"
  12. 4) "b"
  13. 5) "c"
  1. client-2> RPUSH list3 "world"
  2. (integer) 1

表 4-3 展示了客户端从被阻塞到解除阻塞的整个过程。


表 4-3 阻塞 BRPOPLPUSH 命令的执行过程

时间客户端 client-1客户端 client-2
T1尝试执行 BRPOPLPUSH list3 list4 10 并被阻塞。
T2执行 RPUSH list3 "world" ,向列表 list3 推入新元素。
T3服务器执行 BRPOPLPUSH 命令,并将元素 "world" 返回给客户端。

处理源列表为空的情况

如果源列表在用户给定的时限内一直没有元素可供弹出,那么 BRPOPLPUSH 命令将向客户端返回一个空值,以此来表示此次操作没有弹出和推入任何元素:

  1. redis> BRPOPLPUSH empty-list another-list 5
  2. (nil)
  3. (5.05s) -- 客户端被阻塞了 5.05

BLPOP 命令和 BRPOP 命令一样,redis-cli 客户端也会显示 BRPOPLPUSH 命令的阻塞时长。

其他信息

属性
复杂度O(1)
版本要求BRPOPLPUSH 命令从 Redis 2.2.0 版本开始可用。