redis是kv内存数据库,以其设计优雅、性能优良而著称,接下来对redis开始有一系列的文章介绍。
本篇文章对redis中使用pub/sub的模式进行讲解。
模式介绍
对于redis本身,提供了pub/sub的支持。下面简单模拟pub/sub模式的整个过程,打开两个redis客户端,在这里分别pub_cli与sub_cli。
sub_cli:
127.0.0.1:6379> SUBSCRIBE first //订阅一个频道
执行命令之后,消息返回
:
127.0.0.1:6379> SUBSCRIBE first
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "first"
3) (integer) 1
pub_cli:
127.0.0.1:6379> PUBLISH first Hello //向频道first发送消息Hello
这个时候在sub_cli就可以发现一条消息打印出来
sub_cli:
127.0.0.1:6379>
Hello。
除了我们显式指定订阅某一个频道之外,我们还可以通过模式匹配原则,订阅符合某一种模式的所有频道。
127.0.0.1:6379> PSUBSCRIBE first* //订阅所有符合first开头模式的频道
相应的取消订阅就是USUBSCRIBE、PUNSUBSCRIBE 。这里就不再细说,语法格式是一样的。
在pub/sub模式中需要注意,当发布者发布一条消息的时候,如果没有订阅订阅该主题,那么该条消息就永远的丢失了。无论是否该主题在接下来是否有订阅者订阅。在这一点上还有有别于其他的消息队列。比如kafka,它是不会删除消息的,除非你有配置定时删除或者固定大小以后删除。
实现
结合redis自带的pub/sub,可以简单的实现pub/sub模式,在项目中进行运用。下面就通过python模拟整个过程。
对于订阅者,获取pub的信息有三种模式。
get_message、listen,最后一种是创建一个线程来单独负责获取pub信息。
对于get_message是使用了系统的select模式,如果有数据则读取数据并返回,如果没有数据则该方法直接返回空。而listen则是阻塞式读取,只到有信息才返回。
在python的redis客户端2.10之前,get_message方法还没出现是无法使用的,只能是采用listen方法。另外需要注意的是,第三种方法因为是单独创建了一个线程去读取发布者的消息,所以如果在订阅某个主题的时候没有创建默认的处理消息的方法,那么该方式下就不能对发布者的信息进行正常处理了。
pub.py
import time
import redis
r = redis.StrictRedis(host = "127.0.0.1", port = 6379, db=1)
i = 0
while True:
i += 1
r.publish("first channel", "the i is " + str(i))
print("the i is " + str(i))
time.sleep(1)
sub.py
import time
import redis
r = redis.StrictRedis(host = "127.0.0.1", port = 6379, db=1)
p = r.pubsub()
p.subscribe("first channel")
while True:
message = p.listen()
if message:
print message
pub_sub:http://redis.io/topics/pubsub