消息多播机制
1、Redis队列(list)不支持多播,但是使用PubSub模式可以支持消息多播机制,一个消息被多个消费者消费
2、消息多播允许生产者产生一次消息,中间件将消息复制到多个消息队列,每个消息队列由相应的消费组进行消费;这是分布式系统常用的解耦方式,用余江多个消费组的逻辑进行拆分,;支持消息多播之后,多个消费组的逻辑就可以放到不同的子系统中
普通的消息队列,如果要实现不同的消费组逻辑放在一个系统里,接收一条消息处理多种逻辑
PubSub模式
Redis PubSub模式支持消息多播机制,发布者订阅者模型
客户端发起订阅模式之后,Redis会立即给予一个反馈消息通知订阅成功。由于网络传输存在延迟,在subscribe命令发出之后,需要休息一会后通过get\_message才能拿到反馈消息。客户端接下来执行发布命令,发布了一条消息。同样因为网络延迟,在publish命令发出之后,需要休眠一会再通过get\_message才能拿到发布的消息。如果当前没有消息,get\_message会返回空告知当前没有消息;PubSub模式不是阻塞的,也就是说如果生产者产生了一条消息,但是此时没有消费者去消费,那么这条消息将被丢弃;可以使用listen来阻塞监听消息,这点和blpop是类似的
订阅多个主题
Redis中一个消费者可以订阅多个主题,支持订阅多个名称,也支持主题名称是正则表达式的;使用模式订阅订阅主题时,如果生产者新增加了童模是的主题,消费者也可以同时收到消息
> subscribe codehole.image codehole.text codehole.blog # 同时订阅三个主题,会有三条订阅成功反馈信息
1) "subscribe"
2) "codehole.image"
3) (integer) 1
1) "subscribe"
2) "codehole.text"
3) (integer) 2
1) "subscribe"
2) "codehole.blog"
3) (integer) 3
> psubscribe codehole.* # 用模式匹配一次订阅多个主题,主题以 codehole. 字符开头的消息都可以收到
1) "psubscribe"
2) "codehole.*"
3) (integer) 1
Redis消费者收到消息的形式
消费者消息输出时都是下面的这样一个字典形式
{'pattern': None, 'type': 'subscribe', 'channel': 'codehole', 'data': 1L}
{'pattern': None, 'type': 'message', 'channel': 'codehole', 'data': 'python comes'}
{'pattern': None, 'type': 'message', 'channel': 'codehole', 'data': 'java comes'}
{'pattern': None, 'type': 'message', 'channel': 'codehole', 'data': 'golang comes'}
1、data 这个毫无疑问就是消息的内容,一个字符串
2、channel 这个也很明显,它表示当前订阅的主题名称
3、type 它表示消息的类型,如果是一个普通的消息,那么类型就是 message,如果是控制消息,比如订阅指令的反馈,它的类型就是 subscribe,如果是模式订阅的反馈,它的类型就是 psubscribe,还有取消订阅指令的反馈 unsubscribe 和 punsubscribe
4、pattern 它表示当前消息是使用哪种模式订阅到的,如果是通过 subscribe 指令订阅的,那么这个字段就是空
PubSub模式缺点
1、PubSub 的生产者传递过来一个消息,Redis 会直接找到相应的消费者传递过去。如果一个消费者都没有,那么消息直接丢弃。如果开始有三个消费者,一个消费者突然挂掉了,生产者会继续发送消息,另外两个消费者可以持续收到消息。但是挂掉的消费者重新连上的时候,这断连期间生产者发送的消息,对于这个消费者来说就是彻底丢失了
2、如果Redis停机重启,PubSub的消息是不会持久化的,因为Redis宕机就相当于一个消费者没有,所有的消息会被直接丢弃