非常教程

Redis参考手册

列表 | Lists

blpop

BLPOP key [key ...] timeout

自2.0.0起可用。

时间复杂度: O(1)

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

非阻塞行为

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

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

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来说,执行多次推送的命令会被执行,并且只有在被阻止的客户端执行命令后才会执行。考虑这个命令序列。

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当没有元件可以被弹出多批量和超时过期。
  • 第一个元素是元素被弹出的键的名称,第二个元素是弹出元素的值的两元素的多块。

例子

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的阻止版本不可用,但使用阻止列表操作,我们可以轻松完成此任务。

使用者会这样做:

LOOP forever
    WHILE SPOP(key) returns elements
        ... process elements ...
    END
    BRPOP helper_key
END

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

MULTI
SADD key element
LPUSH helper_key x
EXEC
Redis

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。 它通常被称为数据结构服务器,因为值( value )可以是 字符串( String ), 哈希(Map),列表(list),集合( sets ) 和 有序集合( sorted sets )等类型。

主页 https://redis.io/
源码 https://github.com/antirez/redis
发布版本 4.0.2

Redis目录

1.集合 | Cluster
2.连接 | Connection
3.Geo
4.Hashes
5.HyperLogLog
6.键 | Keys
7.列表 | Lists
8.Pub/Sub
9.脚本 | Scripting
10.服务器 | Server
11.设定 | Sets
12.排序集 | Sorted Sets
13.字符串 | Strings
14.事务 | Transactions
15.Redis Dump 命令
16.Redis DEL 命令
17.Redis 键(key)
18.Redis 命令
19.Redis 配置
20.Redis 简介
21.Redis RANDOMKEY 命令
22.Redis TTL 命令
23.Redis Pttl 命令
24.Redis PERSIST 命令
25.Redis Move 命令
26.Redis PEXPIREAT 命令
27.Redis Keys 命令
28.Redis Expireat 命令
29.Redis Expire 命令
30.Redis EXISTS 命令
31.Redis Mget 命令
32.Redis Getbit 命令
33.Redis Getset 命令
34.Redis Getrange 命令
35.Redis Get 命令
36.Redis SET 命令
37.Redis 字符串(String)
38.Redis Type 命令
39.Redis Renamenx 命令
40.Redis Rename 命令
41.Redis Incrby 命令
42.Redis Incr 命令
43.Redis Psetex 命令
44.Redis Msetnx 命令
45.Redis Mset 命令
46.Redis Strlen 命令
47.Redis Setrange 命令
48.Redis Setnx 命令
49.Redis Setex 命令
50.Redis Setbit 命令
51.Redis Hincrby 命令
52.Redis Hgetall 命令
53.Redis Hget 命令
54.Redis Hexists 命令
55.Redis Hdel 命令
56.Redis 哈希(Hash)
57.Redis Append 命令
58.Redis Decrby 命令
59.Redis Decr 命令
60.Redis Incrbyfloat 命令
61.Redis Blpop 命令
62.Redis 列表(List)
63.Redis Hvals 命令
64.Redis Hsetnx 命令
65.Redis Hset 命令
66.Redis Hmset 命令
67.Redis Hmget 命令
68.Redis Hlen 命令
69.Redis Hkeys 命令
70.Redis Hincrbyfloat 命令
71.Redis Lrem 命令
72.Redis Lrange 命令
73.Redis Lpushx 命令
74.Redis Lpush 命令
75.Redis Lpop 命令
76.Redis Llen 命令
77.Redis Linsert 命令
78.Redis Lindex 命令
79.Redis Brpoplpush 命令
80.Redis Brpop 命令
81.Redis Sdiff 命令
82.Redis Scard 命令
83.Redis Sadd 命令
84.Redis 集合(Set)
85.Redis Rpushx 命令
86.Redis Rpush 命令
87.Redis Rpoplpush 命令
88.Redis Rpop 命令
89.Redis Ltrim 命令
90.Redis Lset 命令
91.Redis Sunion 命令
92.Redis Srem 命令
93.Redis Srandmember 命令
94.Redis Spop 命令
95.Redis Smove 命令
96.Redis Smembers 命令
97.Redis Sismember 命令
98.Redis Sinterstore 命令
99.Redis Sinter 命令
100.Redis Sdiffstore 命令