Kafka Consumer1
本文的代码基于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,主要有以下几个目的:
- 更轻便的客户端
- 部分用户希望开发和使用non-java的客户端。现阶段使用non-java发SimpleConsumer比较方便,但想开发High Level Consumer并不容易。因为High Level Consumer需要实现一些复杂但必不可少的失败探测和Rebalance。如果能将消费者客户端更精简,使依赖最小化,将会极大的方便non- java用户实现自己的Consumer。
- 一个集中的协调者
- 如上文所述,当前版本的High Level Consumer存在Herd Effect和Split Brain的问题。如果将失败探测和Rebalance的逻辑放到一个高可用的中心Coordinator,那么这两个问题即可解决。同时还可大大减少 Zookeeper的负载,有利于Kafka Broker的Scale Out。
- 允许手动分配partition
- 有些系统希望将 partition 和 consumer 进行一一对应。
- 在一些高级的消费者中,他们希望停止自动的 rebalance。
- 这个实现依赖于集中的协调者。
- 允许手动管理 offset
- 一些系统希望以特定的时间间隔在自定义的数据库中管理Offset。这就要求Consumer能获取到每条消息的metadata,例如 Topic,Partition,Offset,同时还需要在Consumer启动时得到每个Partition的Offset。实现这些,需要提供新的 Consumer API。同时有个问题不得不考虑,即是否允许Consumer手工管理部分Topic的Offset,而让Kafka自动通过Zookeeper管理其它 Topic的Offset。一个可能的选项是让每个Consumer只能选取1种Offset管理机制,这可极大的简化Consumer API的设计和实现。
- 允许用户指定 callback 和 rebalance
- 一些应用可能会在内存中为每个Partition维护一些状态,Rebalance时,它们可能需要将该状态持久化。因此该需求希望支持用户实现并指定一些可插拔的并在Rebalance时触发的回调。如果用户使用手动的Offset管理,那该需求可方便得由用户实现,而如果用户希望使用Kafka提供的自动Offset管理,则需要Kafka提供该回调机制
- 非阻塞的消费API
- 该需求源于那些实现高层流处理操作,如filter by, group by, join等,的系统。现阶段的阻塞式Consumer几乎不可能实现Join操作。
Partition分配
当多个consumer 去消费topic的消息时,首先面临的问题就是哪个consuemr应该消费那些topicAndPartition。可以调用assign
手动分配partition。如果需要手动分配,Kafka提供了两种自动分配 的方式,分别为Range
和roundrobin
。
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:
- 新的consumer加入了。
- consumer 挂了。
- consumer 执行了 unsubscribe,离开这个消费组。
- 集群中的coordinator挂了,选举了一个新的。
- topic 增加了 partition。
这些情况都是由 ConsumerCoordinator 进行处理。Coordinator通过一个特定的 broker 对 单个 消费组(consumer group) 进行管理。 Coordinator 主要负责下面几件事情:
- Group Registration : 消费组里面的每个成员会通过自己的 metadata 向 coordinator 进行注册。
- Group/Leader Selection: Coordinator 会从消费组里面的选取一个成员作为一个leader。这个leader 会进行partition的分配,并将分配结果提交给 coordinator。
- State Assignment: Coordinator 会收集消费组里面每个成员的 metadata 信息,然后为它们分配不同的状态。
- Group Stabilization: 消费组里面的每个成员会通过coordinator接收到 leader 设计的分配状态,并开始处理数据。
图1 ConsumerCoordinator 状态图 ConsumerCoordinator
图1中,consumer 首先查找服务器的 coordinator, 然后通过ensureActiveGroup
成功加入消费组里面,并启动heartBeat 线程,当heartBeat线程的通信返回错误后,重新进行上述操作。当然也可能该consumer离开了消费组,这时候其它的consumer会重复上述操作。
这个里面最重要的应该就是ensureActiveGroup
这个动作,它主要负责和服务器的Coordinator node 进行交互,并根据返回的结果做相应的处理。
- 寻找服务器的coordinator。
- 启动HeartBeat线程。
- 将consumer加入group。
- 发送JoinGroupRequest 。
- 调用JoinGroupResponseHandler 处理 response。
- 如果结果成功了,查看返回结果中是不是指定这个consumer 作为leader。如果是leader,那就执行partition分配策略,如果不是,就说明是follower,不执行分配策略。
然后leader 和 follower 都发送SyncGroupRequest给coordinator,不同的是leader的参数里包含了分配策略。 - 如果失败了,根据不同的情况进行处理。
- 如果结果成功了,查看返回结果中是不是指定这个consumer 作为leader。如果是leader,那就执行partition分配策略,如果不是,就说明是follower,不执行分配策略。
- 处理 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的更多相关文章
- Kafka设计解析(四)- Kafka Consumer设计解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/08/09/KafkaColumn4 摘要 本文主要介绍了Kafka High Level Con ...
- Kafka设计解析(一)- Kafka背景及架构介绍
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...
- ELK+Kafka集群日志分析系统
ELK+Kafka集群分析系统部署 因为是自己本地写好的word文档复制进来的.格式有些出入还望体谅.如有错误请回复.谢谢! 一. 系统介绍 2 二. 版本说明 3 三. 服务部署 3 1) JDK部 ...
- Kafka深度解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...
- Kafka深度解析,众人推荐,精彩好文!
作者: Jason Guo 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,并保证即使对TB级以上数据 ...
- kafka设计原理介绍
背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能 高吞吐 ...
- kafka基本原理学习
下载安装地址:http://kafka.apache.org/downloads.html 原文链接:http://www.jasongj.com/2015/01/02/Kafka深度解析 Kafk ...
- kafka概念
一.结构与概念解释 1.基础概念 topics: kafka通过topics维护各类信息. producer:发布消息到Kafka topic的进程. consumer:订阅kafka topic进程 ...
- Kafka入门学习随记(二)
====Kafka消费者模型 参考博客:http://www.tuicool.com/articles/fI7J3m --分区消费模型 分区消费架构图 图中kafka集群有两台服务器(Server), ...
随机推荐
- 动态连通性问题:union-find算法
写在前面的话: 一枚自学Java和算法的工科妹子. 算法学习书目:算法(第四版) Robert Sedgewick 算法视频教程:Coursera Algorithms Part1&2 本文 ...
- jQuery进度条设置
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="con ...
- ROS-opencv-人脸识别-物体追踪-二维码识别
前言:人脸识别是基于人的脸部特征信息进行身份识别的一种生物识别技术.用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相关技术,通常也叫做 ...
- week4_notebooke1
今日大纲:01名称空间,作用域,取值顺序02函数的嵌套03内置函数 globals() locals()04关键字global nonlocal05函数名的应用06闭包07装饰器初识08装饰器进阶 注 ...
- P2216 [HAOI2007]理想的正方形(二维RMQ)
题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行为3个整数,分别表示a,b,n的值 第二行至 ...
- Android 制作类似支付圆圈和打钩界面ProgressWheel
首先要说明的是,制作圆圈旋转的效果并不是博主做的,是参照了github上的一个代码,只是在上面添加了修改,对其优化并增加了一个打钩的动画. 先来看下效果,1+的手机获取root权限真是难,没法录屏,只 ...
- Android 自定义简单控件--星级评价
效果图 实现 package com.easypass.carstong.view; import android.content.Context; import android.content.re ...
- VC工程里,如何编译汇编语言的文件
最近老是有朋友问,VC工程里,如何编译汇编语言的文件,接下来就说一下步骤: 1.将汇编语言文件,加入到工程里: 2.在Solution Explorer窗口中右键单击Visual C++项目,选择Bu ...
- swift使用查阅资料备份4
Swift - RxSwift的使用详解6(观察者2: 自定义可绑定属性) http://www.hangge.com/blog/cache/detail_1946.html extension UI ...
- css——定位
position absolute:绝对定位 1.以页面的左上角为原点 2.不保留原来的位置 3.z-index可以调整图层顺序 如果想实现以父级元素左上角为原点.则:父级相对,子级绝对 在子级绝对的 ...