首页

9.2发布消息/订阅频道

关灯 护眼    字体:

上一章 目录 下一章




Redis的“发布/订阅”模式是一种消息通信模式,实现了一对多的消息实时发布功能。



9.2.1  实例36:实现一对多的消息发布


实例描述

分别使用Redis的字符串和“发布/订阅”模式实现一对多的消息通信,比较这两种方式的差异。

1.使用字符串实现一对多的消息发布功能

使用字符串来实现一对多的消息发布功能,逻辑非常简单:

(1)定好一个字符串Key,例如message。

(2)发送端使用字符串的set操作把新信息设置到这个Key中。

(3)多个接收端不停获取  message  的值。如果发现值变化了,则认为来了新的消息,接收并保存。

使用字符串实现一对多的消息发布功能,代码分为发送端和接收端。

(1)发送端代码:

代码9-8  使用字符串实现一对多的消息发布(发送端代码)

其中,主要代码说明如下。

●  第8行代码:使用一个无限循环来实现持续发布消息。

●  第9行代码:让用户在命令行输入需要发布的信息。

●  第10行代码:记录当前的时间,时间格式为“2018-08-19  11:29:12”。

●  第11行代码:把信息和时间组装为一个字典。

●  第12行代码:以JSON格式把信息设置到Redis的message字符串中。

(2)接收端的代码如下:

代码9-9  使用字符串实现一对多的消息发布(接收端代码)



其中,主要代码说明如下。

●  第7行代码:初始化时间记录变量。

●  第8行代码:使用一个无限循环来持续接收数据。

●  第9行代码:读取Redis中名字为message的字符串。

●  第10~12行代码:message这个Key可能不存在,此时返回None。遇到这种情况就等待1秒以后跳过本次循环。

●  第  13~15行代码:使用json模块解析JSON字符串,以获取信息和发送时间。

●  第16~19行代码:如果信息的发送时间与上一条信息的发送时间一样,则说明是同一条信息,不需要打印出来。

●  第21行代码:更新时间记录变量。

发送端的运行效果如图9-10所示。

图9-10  发送端运行效果

接收端的运行效果如图9-11所示。

图9-11  接收端运行效果

2.使用字符串的弊端

使用字符串进行消息的发布,虽然说代码简单易懂,但它也存在诸多问题。举例如下:

●  接收端不知道发送端什么时候发布消息,因此必须持续不断检查Redis,浪费系统资源。

●  由于轮询查询,所以消息有延迟。

●  如果发送端在1秒内连续更新10条,则后一条会覆盖前一条,而接收端每1秒才获取一次数据,必然导致最多漏掉9条数据。要减少遗漏数量就需要增加轮询频率,进一步增大系统开销。

3.使用Redis的“发布/订阅”模式实现消息通信

“发布/订阅”模式是  Redis  自带的一对多消息通信模式。使用“发布/订阅”模式不仅可以解决字符串通信遇到的各种问题,而且代码更简洁。

(1)发送端代码如下。

代码9-10  使用“发布/订阅”模式实现一对多消息通信(发送端代码)

其中,主要代码说明如下。

●  第8行代码:进入无限循环,不停发布信息。

●  第9行代码:获取用户在命令行输入的内容。

●  第10行代码:获取当前的时间,并转化为“2018-08-19  13:23:00”这种格式。

●  第11行代码:把信息和当前时间组装为一个字典。

●  第12行代码:把信息以JSON字符串的形式发布到名为pubinfo的频道中。

(2)接收端代码如下。

代码9-11  使用“发布/订阅”模式实现一对多消息通信(接收端代码)

其中,主要代码说明如下。

●  第5行代码:生成一个发布/订阅对象,并忽略订阅成功的消息。

●  第6行代码:订阅名为pubinfo的频道。

●  第7~9行代码:从频道中获取信息并打印。



9.2.2  实例37:在Python中发布消息/订阅频道


实例描述

在Python中操作Redis,使用“发布/订阅”模式实现以下功能:

(1)向一个频道中发布消息。

(2)订阅多个频道。

“发布/订阅”模式在Redis中只有6个命令,对应到Python中有6个方法。

1.发布消息

在Python中向一个频道发送消息,代码和向Redis字符串设置值一样简单,差别只是使用的方法名为“publish”,格式如下:

client.publish(’频道名’,  ’消息’)

例如代码9-12。

代码9-12  使用Python向一个频道发布消息

2.订阅频道

订阅频道涉及的步骤稍微多一些。首先需要生成一个“发布/订阅”对象,然后使用这个对象来订阅频道。订阅频道以后,循环从频道里面获取数据。

(1)一个订阅实例只订阅一个频道。

格式为:

代码9-13  使用Python订阅频道

第3行的instener.listen()是一个阻塞式的方法。程序运行到这里,如果频道里面没有数据,则程序就会“卡住”,直到频道里面有了新的信息,才会继续运行后面的代码。

第3行的for循环获得的message是一个字典,它的内容有两种情况。

●  第1次进入for循环时,数据为:

{'type':  'subscribe',  'pattern':  None,  'channel':  b'pubinfo',  'data':  1}

这条信息表明订阅频道“pubinfo”成功。如果不想显示这一条内容,则在初始化“发布/订阅”对象时,可以指定一个参数:ignore_subscribe_messages=True。

●  从第2次循环开始就是正式的频道信息,格式为:

{'type':  'message',  'pattern':  None,  'channel':  b'pubinfo',  'data':  b'{"message":"yy",  "time":  "2018-08-19  13:38:58"}'}

发送端发送的信息,保存在字典的data这个Key对应的值里面,还是bytes型的数据,需要解码为字符串以后做进一步处理。

(2)一个“发布/订阅”实例可以订阅多个频道。

一个“发布/订阅”实例可以订阅多个频道,格式为:

listener  =  client.pubsub()

listener.subscribe(’频道名1',  ’频道名2',  ’频道名n')

例如代码9-14。

代码9-14  在一个发布订阅实例中订阅多个频道

其中,主要代码说明如下。

●  第5行代码:生成“发布/订阅”对象,并且不显示订阅成功信息。

●  第6行代码:订阅computer、math、shopping三个频道。

●  第7行代码:使用for循环获取频道发布的信息。

●  第8行代码:获取这一条信息属于哪一个频道。

●  第9~10行代码:获取信息内容并打印。

运行效果如图9-12所示。

图9-12  订阅多个频道

3.“发布/订阅”模式的注意事项

“发布/订阅”模式的工作过程就像收音机的广播一样,只有调到了这个频道,才能收到信息,而之前的信息就都丢失了。例如,发送端先发送10条信息,再启动接收端,则接收端是没有办法收到先发送的10条信息的。

可以有非常多的接收端同时订阅一个频道。一旦这个频道有消息发布,所有接收端都会收到信息。



9.2.3  实例38:在redis-cli中发布消息/订阅频道


实例描述

在redis-cli中使用“发布/订阅”模式,实现以下功能:

(1)向一个频道中发布消息。

(2)订阅多个频道并接收频道中的消息。

1.发布信息

在redis-cli中向频道发布信息非常简单,使用命令“publish”即可,格式如下:

publish  频道名  信息

例如:

publish  computer  人工智能新突破

运行效果如图9-13所示。

图9-13  在redis-cli发布信息

2.订阅频道

订阅频道使用的命令为“subscribe”,命令格式如下:

subscribe  频道名1  频道名2  频道名n

例如:

subscribe  computer  math

订阅以后,一旦被订阅的频道有新的消息发布,订阅端就会收到信息,如图9-14所示。中文无法正常显示,每一条新发布的信息都会对应redis-cli中的3条返回信息:第1条是信息类型,第2条是频道名,第3条是被发布的内容。

图9-14  在redis-cli订阅频道并接收信息




上一章 目录 下一章