本文的代码基于kafka的0.10.1的版本。

重新设计的原因

0.9以前的consumer是通过zookeeper来进行状态管理里的。

  • 羊群效应

    • 任何Broker或者Consumer的增减都会触发所有的Consumer的Rebalance
  • Split brain(大脑分裂)
    • 每个Consumer分别单独通过Zookeeper判断哪些Broker和Consumer 宕机了,那么不同Consumer在同一时刻从Zookeeper“看”到的View就可能不一样,这是由Zookeeper的特性决定的,这就会造成不正确的Reblance尝试。
  • 调整结果不可控
    • 所有的Consumer都并不知道其它Consumer的Rebalance是否成功,这可能会导致Kafka工作在一个不正确的状态。

实现目标

在0.9, kafka 重新设计了 consumer,主要有以下几个目的:

  1. 更轻便的客户端

    1. 部分用户希望开发和使用non-java的客户端。现阶段使用non-java发SimpleConsumer比较方便,但想开发High Level Consumer并不容易。因为High Level Consumer需要实现一些复杂但必不可少的失败探测和Rebalance。如果能将消费者客户端更精简,使依赖最小化,将会极大的方便non- java用户实现自己的Consumer。
  2. 一个集中的协调者
    1. 如上文所述,当前版本的High Level Consumer存在Herd Effect和Split Brain的问题。如果将失败探测和Rebalance的逻辑放到一个高可用的中心Coordinator,那么这两个问题即可解决。同时还可大大减少 Zookeeper的负载,有利于Kafka Broker的Scale Out。
  3. 允许手动分配partition
    1. 有些系统希望将 partition 和 consumer 进行一一对应。
    2. 在一些高级的消费者中,他们希望停止自动的 rebalance。
    3. 这个实现依赖于集中的协调者。
  4. 允许手动管理 offset
    1. 一些系统希望以特定的时间间隔在自定义的数据库中管理Offset。这就要求Consumer能获取到每条消息的metadata,例如 Topic,Partition,Offset,同时还需要在Consumer启动时得到每个Partition的Offset。实现这些,需要提供新的 Consumer API。同时有个问题不得不考虑,即是否允许Consumer手工管理部分Topic的Offset,而让Kafka自动通过Zookeeper管理其它 Topic的Offset。一个可能的选项是让每个Consumer只能选取1种Offset管理机制,这可极大的简化Consumer API的设计和实现。
  5. 允许用户指定 callback 和 rebalance
    1. 一些应用可能会在内存中为每个Partition维护一些状态,Rebalance时,它们可能需要将该状态持久化。因此该需求希望支持用户实现并指定一些可插拔的并在Rebalance时触发的回调。如果用户使用手动的Offset管理,那该需求可方便得由用户实现,而如果用户希望使用Kafka提供的自动Offset管理,则需要Kafka提供该回调机制
  6. 非阻塞的消费API
    1. 该需求源于那些实现高层流处理操作,如filter by, group by, join等,的系统。现阶段的阻塞式Consumer几乎不可能实现Join操作。

Partition分配

当多个consumer 去消费topic的消息时,首先面临的问题就是哪个consuemr应该消费那些topicAndPartition。可以调用assign手动分配partition。如果需要手动分配,Kafka提供了两种自动分配 的方式,分别为Rangeroundrobin

Range

Range策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。在我们的例子里面,排完序的分区将会是0, 1, 2, 3, 4, 5, 6, 7, 8, 9;消费者线程排完序将会是C1-0, C2-0, C2-1。然后将partitions的个数除于消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。在我们的例子里面,我们有10个分区,3个消费者线程, 10 / 3 = 3,而且除不尽,那么消费者线程 C1-0 将会多消费一个分区,所以最后分区分配的结果看起来是这样的:

  • C1-0 将消费 0, 1, 2, 3 分区
  • C2-0 将消费 4, 5, 6 分区
  • C2-1 将消费 7, 8, 9 分区

假如我们有11个分区,那么最后分区分配的结果看起来是这样的:

  • C1-0 将消费 0, 1, 2, 3 分区
  • C2-0 将消费 4, 5, 6, 7 分区
  • C2-1 将消费 8, 9, 10 分区

假如我们有2个主题(T1和T2),分别有10个分区,那么最后分区分配的结果看起来是这样的:

  • C1-0 将消费 T1主题的 0, 1, 2, 3 分区以及 T2主题的 0, 1, 2, 3分区
  • C2-0 将消费 T1主题的 4, 5, 6 分区以及 T2主题的 4, 5, 6分区
  • C2-1 将消费 T1主题的 7, 8, 9 分区以及 T2主题的 7, 8, 9分区

可以看出,C1-0 消费者线程比其他消费者线程多消费了2个分区,这就是Range strategy的一个很明显的弊端。

RoundRobin strategy

RoundRobin 策略会将所有的topicAndPartition 和 消费者进行排序。然后循环遍历每个消费者,依次分配tp。
举例两个消费者C1 和 C2, 两个 topic , t0 和 t1, 每个 topic都有3个partition,这样下来总共有t0p0, t0p1, t0p2, t1p0, t1p1, and t1p2。而最终分配的结果是:

  • C0 将消费 t0p0, t0p2, t1p1 这三个分区
  • C1 将消费t0p1, t1p0, t1p2 这三个分区

如果有的消费者没有订阅其中的topic, 轮训策略会使得topic分配不均匀。
有的时候效果还不如 range assigment。

ConsumerCoordinator

当集群或者消费组出现变化的时候,就会执行partition的分配,我们称这种情况为 reblance。下面几种情况都会触发reblance:

  1. 新的consumer加入了。
  2. consumer 挂了。
  3. consumer 执行了 unsubscribe,离开这个消费组。
  4. 集群中的coordinator挂了,选举了一个新的。
  5. topic 增加了 partition。

这些情况都是由 ConsumerCoordinator 进行处理。Coordinator通过一个特定的 broker 对 单个 消费组(consumer group) 进行管理。 Coordinator 主要负责下面几件事情:

  1. Group Registration : 消费组里面的每个成员会通过自己的 metadata 向 coordinator 进行注册。
  2. Group/Leader Selection: Coordinator 会从消费组里面的选取一个成员作为一个leader。这个leader 会进行partition的分配,并将分配结果提交给 coordinator。
  3. State Assignment: Coordinator 会收集消费组里面每个成员的 metadata 信息,然后为它们分配不同的状态。
  4. Group Stabilization: 消费组里面的每个成员会通过coordinator接收到 leader 设计的分配状态,并开始处理数据。

图1 ConsumerCoordinator 状态图 ConsumerCoordinator

图1中,consumer 首先查找服务器的 coordinator, 然后通过ensureActiveGroup 成功加入消费组里面,并启动heartBeat 线程,当heartBeat线程的通信返回错误后,重新进行上述操作。当然也可能该consumer离开了消费组,这时候其它的consumer会重复上述操作。

这个里面最重要的应该就是ensureActiveGroup 这个动作,它主要负责和服务器的Coordinator node 进行交互,并根据返回的结果做相应的处理。

  1. 寻找服务器的coordinator。
  2. 启动HeartBeat线程。
  3. 将consumer加入group。
    1. 发送JoinGroupRequest 。
    2. 调用JoinGroupResponseHandler 处理 response。
      1. 如果结果成功了,查看返回结果中是不是指定这个consumer 作为leader。如果是leader,那就执行partition分配策略,如果不是,就说明是follower,不执行分配策略。
        然后leader 和 follower 都发送SyncGroupRequest给coordinator,不同的是leader的参数里包含了分配策略。
      2. 如果失败了,根据不同的情况进行处理。
    3. 处理 SyncGroupResponse,从其中获取consumer 消费的topicAndPartition,并触发 ConsumerRebalanceListener。

图2 展示了ensureActiveGroup 的具体行为。

参考:

[1] Kafka设计解析(四):Kafka Consumer解析

[2] Kafka分区分配策略(Partition Assignment Strategy)

[3] Kafka源码深度解析-序列6 -Consumer -消费策略分析

[4] Kafka源码深度解析-序列7 -Consumer -coordinator协议与heartbeat实现原理

Kafka Consumer1的更多相关文章

  1. Kafka设计解析(四)- Kafka Consumer设计解析

    本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/08/09/KafkaColumn4 摘要 本文主要介绍了Kafka High Level Con ...

  2. Kafka设计解析(一)- Kafka背景及架构介绍

    本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...

  3. ELK+Kafka集群日志分析系统

    ELK+Kafka集群分析系统部署 因为是自己本地写好的word文档复制进来的.格式有些出入还望体谅.如有错误请回复.谢谢! 一. 系统介绍 2 二. 版本说明 3 三. 服务部署 3 1) JDK部 ...

  4. Kafka深度解析

    本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...

  5. Kafka深度解析,众人推荐,精彩好文!

    作者: Jason Guo 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,并保证即使对TB级以上数据 ...

  6. kafka设计原理介绍

    背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能 高吞吐 ...

  7. kafka基本原理学习

    下载安装地址:http://kafka.apache.org/downloads.html  原文链接:http://www.jasongj.com/2015/01/02/Kafka深度解析 Kafk ...

  8. kafka概念

    一.结构与概念解释 1.基础概念 topics: kafka通过topics维护各类信息. producer:发布消息到Kafka topic的进程. consumer:订阅kafka topic进程 ...

  9. Kafka入门学习随记(二)

    ====Kafka消费者模型 参考博客:http://www.tuicool.com/articles/fI7J3m --分区消费模型 分区消费架构图 图中kafka集群有两台服务器(Server), ...

随机推荐

  1. OC中的类扩展

    类扩展 是在原有类的基础扩展一个新的属性和对象方法 但是方法的实现还是要写在原有的声明中,不然是不会被访问到的 类扩展可以扩展在新的头文件中,然后在主函数中导入. 利用类扩展可以变相的实现属性的私有化 ...

  2. go并发设计模式 --资源生成器模式

    1.简单的生成器 package main import ( "fmt" "math/rand" ) func GenerateIntA()chan int { ...

  3. .NET Core 开发:永远的Hello Word

    从.NET Core发布到现在已经很长一段时间了,园子里的各路大神也和它打的火热,本着与时俱进,啥火学啥的原则,我也开始了我的.NET Core学习之旅. 简介 .NET从2002年发行到现在,从呱呱 ...

  4. usaco 最少找零

    Description 约翰在镇上买了 T 元钱的东西,正在研究如何付钱.假设有 N 种钞票,第 i 种钞票的面值为 Vi,约翰身上带着这样的钞票 Ci 张.商店老板罗伯是个土豪,所有种类的钞票都有无 ...

  5. 快速搭建golden gate环境

    准备操作系统用户和文件系统 准备安装和运行用户(操作系统用户) 建议使用Oracle用户 也可使用新建用户,但需做以下配置 该用户必须加入到oinstall组 该用户使用与oracle相同的profi ...

  6. iOS 处理图片的一些小 Tip

    UIImage 缓存是怎么回事? 通过 imageNamed 创建 UIImage 时,系统实际上只是在 Bundle 内查找到文件名,然后把这个文件名放到 UIImage 里返回,并没有进行实际的文 ...

  7. 细数ZBrush这些年的心路历程

    ZBrush 的出现,带来了一场3D造型的革命.它完全颠覆了传统三维设计工具的工作模式,将3D空间绘图这种全新的设计理念呈现在广大设计师面前,强大的雕塑建模功能和颜色绘制功能释放了艺术家的灵感,让设计 ...

  8. ZBrush软件中Brush特性

    在ZBrush里给用户提供了上百种用于雕刻的笔刷,每种笔刷的显示模式是以红色的两个圆圈,外面的圆圈表示笔刷在进行绘制和雕刻实际影响的范围,而内圆是表示笔刷强度到外圆的衰减的起始位置,可以在Focal ...

  9. maven的pom.xml配置json依赖

    <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</art ...

  10. 字典树Trie Tree

    又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀 ...