文章目录
- 什么是发布订阅?
- 发布订阅的原理
- Kafka 发布订阅原理及工作机制
- 发布订阅的应用
什么是发布订阅?
- 发布订阅的三要素是生产者、消费者和消息中心,生产者负责产生数据放到消息中心,消费者向消息中心订阅自己感兴趣的消息,当发布者推送数据到消息中心后,消息中心根据消费者订阅情况将相关数据推送给对应的订阅者。
发布订阅的原理
- 在分布式通信领域中,消息系统一般有两种典型的模式。一种是点对点模式(P2P,Point to Point),另一种是发布订阅模式(Pub/Sub,Publish/Subscribe)。
- 点对点模式:生产者将消息发送到消息中心,然后消费者从消息中心取出对应的消息进行消费。消息被消费后,消息中心不再存储该消息,因此其他消费者无法再消费该消息。也就是说,点对点模式虽然支持多个消费者,但一个消息只能被一个消费者消费,不允许重复消费。
- 发布订阅模式:生产者可以发送消息到消息中心,而消息中心通常以主题(Topic)进行划分,每条消息都会有相应的主题,消息会被存储到自己所属的主题中,订阅该主题的所有消费者均可获得该消息进行消费。
- 与点对点模式相比,发布订阅模式中一个消息可以被多个消费者进行消费,这也是和点对点模式的本质区别。
Kafka 发布订阅原理及工作机制
- Kafka 是一种典型的发布订阅消息系统,其系统架构也是包括生产者、消费者和消息中心三部分。
- 生产者(Producer)负责发布消息到消息中心;
- 消费者(Consumer)向消息中心订阅自己感兴趣的消息,获得数据后进行数据处理;
- 消息中心(Broker)负责存储生产者发布的消息和管理消费者订阅信息,根据消费者订阅信息,将消息推送给消费者。在 Kafka 中,消息中心本质上就是一组服务器,也可以说是 Kafka 集群。
Kafka 的架构图
- Zookeeper 集群用来协调和管理 Broker 和 Consumer,实现了 Broker 和 Consumer 的解耦,并为系统提供可靠性保证。ZooKeeper 集群可以看作是一个提供了分布式服务协同能力的第三方组件,Consumer 和 Broker 启动时均会向 ZooKeeper 进行注册,由 ZooKeeper 进行统一管理和协调。ZooKeeper 中会存储一些元数据信息,比如对于 Broker,会存储主题对应哪些 分区(Partition),每个分区的存储位置等;对于 Consumer,会存储 消费组(Consumer Group) 中包含哪些 Consumer,每个 Consumer 会负责消费哪些分区等。
分区和消费组的原理和作用
-
Broker 负责存储消息数据,Consumer 负责消费数据,Consumer 消费数据的能力会影响 Broker 数据存储是否溢出的问题。若 Consumer 消费太慢,会导致 Broker 存储溢出,Broker 就会丢弃一部分消息。因此,Broker 和 Consumer 是 Kafka 的核心。
-
Broker:在 Kafka 中,为了解决消息存储的负载均衡和系统可靠性问题,所以引入了主题和分区的概念。其中,主题是一个逻辑概念,指的是消息类型或数据类型。而分区是针对主题而言的,指的是一个主题的内容可以被划分成多个集合,分布在不同的 Broker 上,不同的 Broker 在不同的节点上。这里的集合就是分区,其中同一个分区只属于一个 Broker。
-
分区的好处主要包括如下两点:
- 实现负载均衡,避免单个 Broker 上的负载过高。比如,Topic 0 被分为 Partiton-0、Partiton-1 和 Partiton-2 三个分区,分别分布在 Broker 0、Broker 1 和 Broker 2 上。这,就使得 Topic 0 的消息可以分布在这 3 个分区中,实现负载均衡。
- 实现消息的备份,从而保证系统的高可靠。比如,Topic 1 包含两个分区 Partiton-0、Partiton-1,每个分区内容一致,分别存储在 Broker 0 和 Broker 1 上,借此实现了数据备份。
-
Consumer:Kafka 中的消费组,指的是多个消费者的一个集合。一个消费组中的消费者共同消费主题消息,并且主题中每个消息只可以由消费组中的某一个消费者进行消费。在消息过多的情况下,单个消费者消费能力有限时,会导致消费效率过低,从而导致 Broker 存储溢出,丢弃一部分消息。Kafka 为了解决这个问题,所以引入了消费组。
发布订阅的应用
- 假设在电商购物平台(为了方便理解,我对电商购物平台做了一定的简化)中,用户首先在订单系统下单,下单后库存系统会进行出货,通知系统则负责通知用户,整个流程可以用发布订阅的模式进行,如下图所示:
- 订单系统对应发布订阅模式中的生产者,消息中心有个主题专门存放下单信息,每次用户下单后,订单系统会向该主题写入数据;
- 库存系统和通知系统对应发布订阅模式中的消费者,它们会向消息中心订阅下单信息相关的主题;
- 订单系统向消息中心发布订单信息后,库存系统和通知系统都会获取到相应的下单信息,然后进行各自后续的操作,即库存系统进行出货,通知系统通过短信或邮件等方式通知用户。
发布订阅模式的关键特征
- 实现了系统解耦,易于维护。生产者 / 发布者只负责消息的发布,不需要知道订阅者 / 消费者的数量,也不需要知道订阅者 / 消费者获取消息用来做什么,而订阅者 / 消费者也不需要知道什么时候生产者 / 发布者会发布消息。所以,生产者 / 发布者和订阅者 / 消费者互相独立,进而实现了系统解耦,每个部分可以单独维护,减少了因为生产者和消费者的耦合引入的一些相互影响。比如,如果两者耦合在一起,当生产者逻辑更改需要修改代码时,消费者部分的代码也受影响,因此每个部分单独维护降低了维护的复杂度。
- 实现了异步执行,避免高负载。生产者 / 发布者发布消息到消息中心,当消息超过消息中心可以存储的容量后,消息中心会丢弃掉超出的消息,这样系统就不会因为消息数量多而导致系统故障。
知识扩展:观察者模式和发布订阅模式的区别是什么?
首先,我们看一下观察者模式。顾名思义,观察者模式下有观察者,那么就有被观察者,两者之间的关系是什么呢?
观察者负责监控被观察者的状态变更,如果被观察者的状态发生了改变,那么观察者根据状态的变更执行相关操作。举个例子,现在进程 A 是被观察者,进程 B 和进程 C 是观察者,当进程 B 观察到进程 A 中变量 X 由 3 变为 4 时,执行 X+1 的操作;当进程 C 观察到进程 A 中变量 X 由 3 变为 4 时,执行 X-1 的操作。也就是说,观察者模式,定义了被观察者与观察者的直接交互或通信关系。
接下来,我们看一下发布订阅模式。发布订阅模式中存在发布者、订阅者和消息中心,订阅者需要向消息中心指定自己对哪些数据感兴趣,发布者推送的数据放入消息中心后,消息中心根据订阅者订阅信息推送数据。也就是说,发布者和订阅者之间引入了消息中心,实现的是间接通信。
总结来讲,观察者模式采用了直接通信,观察者和被观察者通信时延会低一些,但它们的依赖关系比较强,不管是被观察者还是观察者逻辑或接口有更改,另外一个均会受影响。而发布者和订阅者模式采用间接通信,引入了消息中心,相对比较厚重,且通信时延相对会高一点,但实现了订阅者与发布者的解耦。
你知道的越多,你不知道的越多。