kafka-消费者-订阅消费消息
发布消息通常有两种模式:
队列模式(queuing):consumers可以同时从服务端读取消息,每个消息只被其中一个consumer读到
发布-订阅模式(publish-subscribe):消息被广播到所有的consumer中,但这里订阅者是个组而不是单个consumer。
kafka消费消息机制:
一个消息只能被consumer group 内的一个 consumer 所消费,且 consumer 消费消息时不关注 offset,最后一个 offset 由 zookeeper 保存。
因此:
如果所有的consumer都在一个组中,这就成为了传统的队列模式。
如果所有的consumer都不在不同的组中,这就成为了发布-订阅模式,
举个栗子:
说明:
由两个机器组成的集群拥有4个分区 (P0-P3) 2个consumer组. A组有两个consumerB组有4个
注:
①同一组中的consumer可以在不同的程序中,也可以在不同的机器上。
②当consumer正常消费消息时,offset将会"线性"的向前驱动,即消息将依次顺序被消费.但事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值.
kafka 提供了两套 consumer API:
The high-level Consumer API:不需要开发人员更多地关注细节(提供了一个消费数据的高层抽象)
The SimpleConsumer API:需要开发人员更多地关注细节
例如:high-level API而言,offset 是存于Zookeeper 中的,无法存于HDFS,而SimpleConsuemr API的 offset 是由自己去维护的,可以将之存于 HDFS 中。
high-level Consumer API:
consumer 可以同时实现离线处理和实时处理,只要分成不同的组就可以了;
consumer 采用 pull 模式从 broker 中读取数据。
注: 采用 pull 模式,consumer 可自主控制消费消息的速率, 可以自己控制消费方式(批量消费/逐条消费),还可以选择不同的提交方式从而实现不同的传输语义。
思考:若采用push 模式,由 broker 控制消息发送速率(目标是尽可能以最快速度传递消息),很难适应消费速率不同的消费者,容易造成 consumer 来不及处理消息,发生拒绝服务以及网络拥塞的现象;
数据处理与 commit 的顺序
读完消息先 commit 再处理消息: 消息可能没处理 (At most once模式)
读完消息先处理再 commit:消息绝不会丢,但可能会重复处理 (At least once模式)
更好的做法:让 offset 和操作输入存在同一个地方,但注意:许多输出系统可能不支持两阶段提交
如:consumer 拿到数据后可能把数据放到 HDFS,如果把最新的 offset 和数据本身一起写到 HDFS,那就可以保证数据的输出和 offset 的更新要么都完成,要么都不完成,间接实现 Exactly once。
The SimpleConsumer API: 需要自己去管理partition、offset、broker、leader ,要做大量的额外工作:
1. 必须在应用程序中跟踪 offset,从而确定下一条应该消费哪条消息
2. 应用程序需要通过程序获知每个 Partition 的 leader 是谁
3. 需要处理 leader 的变更
Consumer rebalance算法:重新分配消费权
当有 consumer 加入或退出、以及 partition 的改变(如 broker 加入或退出)时会触发 rebalance
1. 将目标 topic 下的所有 partirtion 排序,存于PT
2. 对某 consumer group 下所有 consumer 排序,存于 CG,第 i 个consumer 记为 Ci
3. N=size(PT)/size(CG),向上取整
4. 解除 Ci 对原来分配的 partition 的消费权(i从0开始)
5. 将第i*N到(i+1)*N-1个 partition 分配给 Ci

浙公网安备 33010602011771号