Redis6之pub/sub发布与订阅(对比List和Kafka)

时间:2022-07-22
本文章向大家介绍Redis6之pub/sub发布与订阅(对比List和Kafka),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

介绍

Redis中的订阅、发布实现了发布/订阅消息范式,发布者不是计划发送消息给特定的订阅者,而是发布消息到不同的频道,发布者不需要知道是哪些订阅者订阅了消息。订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道是什么样的发布者发布的消息。这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑。

在Redis的发布订阅模式中,有三个部分:

  • Publisher(发布者):发送消息到频道中,每次只能往一个频道发送一条消息;
  • Subscriber(订阅者):订阅频道,订阅者可以同时订阅多个频道;
  • Channel(频道):将发布者发布的消息转发给当前订阅此频道的订阅者;

使用

发布订阅的命令如下:

#发布消息到指定的频道
PUBLISH channel message

#订阅给定的一个或多个频道的信息
SUBSCRIBE channel [channel ...]

#订阅一个或多个符合给定模式的频道
PSUBSCRIBE pattern [pattern ...]

#指退订给定的频道
UNSUBSCRIBE [channel [channel ...]]

#退订所有给定模式的频道
PUNSUBSCRIBE [pattern [pattern ...]]

#查看订阅与发布系统状态
PUBSUB subcommand [argument [argument ...]]

我们使用上篇文章中搭建的集群来测试Redis的订阅发布模式,A节点作为发布者,A,B,C节点作为订阅者消费A节点发布的消息:

订阅者6381:与发布者在同一节点,订阅www,csdn,wyk三个频道;

订阅者6382:订阅符合csdn*和wyk*模式的所有频道;

订阅者6383:订阅csdn频道;

发布者6381:分别往csdn1,csdn2,csdn,wyk四个频道发送消息,验证三个订阅者接收消息的情况以及发布者发布消息后的返回值;

断开后的订阅者重新订阅后会丢失断开期间发布者发布的消息:

在集群模式中,发布者发布消息后的返回值取决于订阅者与发布者在不在同一个节点上:

发布者发布消息后返回值为与发布者相同节点当前订阅了该频道的客户端数量。

对比

在上面的示例中,大家也可以看到,Redis中的发布订阅非常像消息队列,但还是有不同,我们就来对比一下Redis的List实现消息队列以及传统消息队列Kafka看看有哪些不同:

对比List

与Redis中的List对比,基于List实现的消息队列需要结合lpush + brpop来实现。

  • 胜(多消费组):当多个客户端同时消费同一个List消息队列时,消费者A使用brpop消费的数据就从list中弹出了,消费者B就再也读不到该数据,而在发布订阅中,多个订阅者可以订阅相同的频道,频道内的数据会分发到各个订阅者,不会出现某一个订阅者消费了之后,另一个订阅者读不到该数据的情况。
  • 负(断点消费):但对于List的消息队列来说,当消费者断开后重连,仍然可以从List中断点消费还没消费的数据,而发布订阅中,如果订阅者断开重连,会丢失断开期间发布者发布的数据,无法恢复。

对比Kafka

Redis的发布订阅以及List并不是要和专业的消息队列对标,而是可以实现类似的功能,真正在消息队列领域做的好的有很多,RabbitMQ,ActiveMQ,RocketMQ,Kafka,Pulsar等等,发布订阅相比于它们有什么异同呢?

不同点:

  • 持久化:Kafka会将数据持久化到磁盘内,而Redis的发布订阅做不到;
  • 断点消费:上面也提到,当订阅者断开重连会丢失断开期间发布者发布的消息,而kafka中会记录每个消费者消费的topic的offset,因此kafka可以从断开的offset继续消费;
  • 偏移量:基于上一条,同样的kafka的消费者可以指定从某个offset开始重新消费,而Redis发布订阅根本不会记录订阅者消费的偏移量;
  • 消费方式:在Redis发布订阅中,数据消费情况是由发布者控制的,当发布者发布到频道中后,只有当前连接了频道的订阅者才能消费到数据,断开重连的会失去那部分数据。而kafka中消费进度是由消费者控制的,消费者从topic中拉取数据并记录消费的offset。

相同点:

  • 消息模型:在JMS消息模型中有点对点和订阅发布两种,Kafka和Redis发布订阅都是采用发布订阅的模型。
  • 消费者组:Kafka里在不同的消费者组中的消费者消费相同的topic时会各自维护一个offset,因此不会出现A消费之后的数据,B就消费不到的情况。Redis中订阅者订阅相同的频道也不会出现类似的情况。