Kafka的三种客户端线程模型和一个小惊喜

Kafka 作为一个流式数据平台,对开发者提供了三种客户端:生产者 / 消费者、连接器、流处理。本文着重分析这三种客户端的线程模型。看到最后的通常都有惊喜。
消费者的线程模型
0.8 版本以前的消费者客户端会创建一个基于 ZK 的消费者连接器,一个消费者客户端是一个 Java 进程,消费者可以订阅多个主题,每个主题也可以多个线程。为了让消息在多个节点被分布式地消费,提高消息处理的吞吐量,Kafka 允许多个消费者订阅同一个主题,这些消费者需要满足“一个分区只能被一个消费者中的一个线程处理”的限制条件。通常,我们会将同一份相同业务处理逻辑的应用程序部署在不同机器上,并且指定一个消费组编号。当不同机器上的消费者进程启动后,所有这些消费者进程就组成了一个逻辑意义上的消费组。

消费组中的消费者数量是动态变化的,当有新消费者加入消费组,或者旧消费者离开消费组,都会触发基于 ZK 的消费组“再平衡”操作。当“再平衡”操作发生时,每个消费者都会在客户端执行分区分配算法,然后从全局的分配结果中获取属于自己的分区。它的缺点是消费者会和 ZK 产生频繁的交互,造成 ZK 集群的压力过大,并且容易产生羊群效应和脑裂等问题。

在 0.8 版本以后,Kafka 重新设计了客户端,并且引入了“协调者”和“消费组管理协议”。新的消费者将“消费组管理协议”和“分区分配策略”进行了分离。协调者负责消费组的管理,而分区分配则会在消费组的一个主消费者中完成。采用这种方式,每个消费者都需要发送下面两种请求给协调者。

加入组请求:协调者收集消费组的所有消费者,并选举一个主消费者执行分区分配工作。

同步组请求:主消费者完成分区分配,由协调者将分区的分配结果传播给每个消费者。

新版本的消费者客户端引入了一个客户端协调者的抽象类,它的实现除了消费者的协调者,还有一个连接器的实现。

连接器的线程模型
Kafka 连接器的出现标准化了 Kafka 与各种外部存储系统的数据同步。用户开发和使用连接器就变得非常简单,只需要在配置文件中定义连接器,就可以将外部系统的数据导入 Kafka 或将 Kafka 数据导出到外部系统。如图 1 所示,中间部分都是 Kafka 连接器的内部组件,包括源连接器(Source Connector)和目标连接器(Sink Connector)。

图 1 Kafka 连接器的源连接器与目标连接器

Kafka 连接器的单机模式会在一个进程内启动一个 Worker 以及所有的连接器和任务。分布式模式的每个进程都有一个 Worker,而连接器和任务则分别运行在各个节点上。图 2 列举了连接器和任务在不同 Worker 上的四种分布方式:

一个 Worker,一个源任务、一个目标任务

一个 Worker,两个源任务、两个目标任务

两个 Worker,两个源任务、两个目标任务

三个 Worker,两个源任务、两个目标任务

图 2 分布式模式的 Kafka 连接器集群

分布式模式下,不同 Worker 进程之间的协调工作类似于消费者的协调。消费者通过协调者获取分配的分区,Worker 也会通过协调者获取分配的连接器与任务。如图 3 所示,消费者客户端和 Worker 客户端为了加入到组管理中,分别通过客户端的协调者对象来和服务端的消费组协调(GroupCoordinator)通信。


图 3 消费者和 Worker 的工作都是通过协调者分配的

流处理的线程模型
Kafka 流处理的工作流程简单来看分成三个步骤:消费者读取输入分区的数据、流式地处理每条数据、生产者将处理结果写入输出分区,这里面步骤 1 也充分利用了“消费组管理协议”。Kafka 流处理的输入数据源基于具有分布式分区模型的 Kafka 主题,它的线程模型主要由下面三个类组成:

流实例(KafkaStreams):通常一个节点(一台机器)只运行一个流实例。

流线程(StreamThread):一个流实例可以配置多个流线程。

流任务(StreamTask):一个流线程可以运行多个流任务,根据输入主题的分区数确定任务数。

如图 4 所示,输入主题有六个分区,Kafka 流处理总共就会产生六个流任务。流实例可以动态扩展,流线程的个数也可以动态配置。图中一共有三个流线程,则每个流线程会有两个流任务,每个流任务都对应输入主题的一个分区。


图 4 Kafka 流处理的线程模型

Kafka 的流处理框架使用并行的线程模型处理输入主题的数据集,这种设计思路和 Kafka 的消费者线程模型非常类似。消费者分配到订阅主题的不同分区,流处理框架的流任务也分配到输入主题的不同分区。如图 5 所示,输入主题 1 的分区 P1 和输入主题 2 的分区 P1 分配给流线程 1 的流任务,输入主题 1 的分区 P2 和输入主题 2 的分区 P2 分配给流线程 2 的流任务。流处理相比消费者,还会将拓扑的计算结果写到输出主题。


图 5 消费者模型与流处理的线程模型

消费者和流处理的故障容错机制也是类似的。如图 6 所示,假设消费者 2 进程挂掉,它所持有的分区会被分配给同一个消费组中的消费者 1,这样消费者 1 会分配到订阅主题的所有分区。对于流处理而言,如果流线程 2 挂掉了,流线程 2 中的流任务会分配给流线程 1。即流线程 1 会运行两个流任务,每个流任务分配的分区仍然保持不变。


图 6 消费者与流处理的故障容错机制

小 结
Kafka 客户端抽象出来的的“组管理协议”充分运用在消费者、连接器、流处理三个使用场景中。客户端中的消费者、连接器中的工作者、流处理中的流进程都可以看做“组”的一个成员。当增加或减少组成员时,在这个协议的约束下,每个组成员都可以获取到最新的任务,从而做到无缝的任务迁移。一旦理解了“组管理协议”,对于理解 Kafka 的架构设计是很有帮助的。

原文地址:http://blog.51cto.com/14158311/2339074

时间: 2024-11-09 10:52:26

Kafka的三种客户端线程模型和一个小惊喜的相关文章

IO复用、多进程和多线程三种并发编程模型

I/O复用模型 I/O复用原理:让应用程序可以同时对多个I/O端口进行监控以判断其上的操作是否可以进行,达到时间复用的目的.在书上看到一个例子来解释I/O的原理,我觉得很形象,如果用监控来自10根不同地方的水管(I/O端口)是否有水流到达(即是否可读),那么需要10个人(即10个线程或10处代码)来做这件事.如果利用某种技术(比如摄像头)把这10根水管的状态情况统一传达到某一点,那么就只需要1个人在那个点进行监控就行了,而类似与select或epoll这样的多路I/O复用机制就好比是摄像头的功能

SQL2000的三种“故障还原模型”

一.SQL2000的三种“故障还原模型” 在数据库属性的“选项”页,“故障还原模型”栏,共有三项选择:简单.完全.大容量日志记录.它们的根本差别在于SQL2000对数据库日志的维护方式不同.下面逐个讲述: 1.“完全”模型 我们都想象得出,如果需要实现“时点还原”,则SQL2000必须将所有的事务记录无一遗漏地保存下来,成为一条不中断的链.在日志文件中,每一条事务记录都被编了号(称“LSN”),号码是连续的. 在“完全”模型下,SQL2000对事务日志进行最严格.最彻底的管理.中心原理就是:如果

介绍ISA&TMG的三种客户端模式

IAS (Internet Security and Acceleration) TMG(forefront_threat_management_gateway_2010) ISA客户端分类:三种 Web Proxy客户端 支持web请求(http and ftp) 支持用户的身份验证,也就是ISAserver可以根据用户的身份决定允许访问否 支持DNS转发也就是会自动把FQDN的解析请求转发给ISAserver(需要把ISA server的外网卡的DNS指向公网的DNS) ISA端须同意(网络

kafka的三种部署模式

/************* *kafka 0.8.1.1的安装部署 *blog:www.r66r.net *qq:26571864 **************/ 相关部署视频地址:http://edu.51cto.com/course/course_id-2374.html kafka的部署模式为3种模式 1)单broker模式 2)单机多broker模式 (伪集群) 3)多机多broker模式 (真正的集群模式) 第一种模式安装 1.在hadoopdn2机器上面上传kafka文件,并解压到

详谈内存管理技术(三)、线程模型

一.为什么需要线程模型? 记得几年前,自己写高精度算法时,因为需要一个线程安全的后台(用来保存一些信息),便手动写了一个线程本地存储(TLS)(虽然,后来因为改了计算模型,弃用了):再后来,因为内存池的需要,亦手动再写了一个线程本地存储(TLS):很好,这样一来同一个库里,竟然有两套相同的TLS:于是,意识到了什么地方不对. 不只是代码重复的问题(其实重复的不多):更重要的是,TLS应该是线程模型本身,来提供的功能:但,很可惜,C++并没有这样的东西(线程模型).(PS:我无视了系统提供的TLS

Android 中三种启用线程的方法

在多线程编程这块,我们经常要使用Handler(处理),Thread(线程)和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢? 首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应.  而Runnable是一个接口,Thread是Runnable的子类.所以说,他俩都算一个进程.  HandlerThread顾名思义就是可以处理消息循环的线程,他是一个拥有Looper的线程,可以处理消息

EF三种数据库操作模型比较

https://blog.csdn.net/xiongmeiqin/article/details/80196089 EF 中 Code First 的数据迁移以及创建视图 写在前面: EF 中 Code First 的数据迁移网上有很多资料,我这份并没什么特别.Code First 创建视图网上也有很多资料,但好像很麻烦,而且亲测好像是无效的方法(可能是我太笨,没搞成功),我摸索出了一种简单有效的方法,这里分享给大家. EF是Entity Framework(实体框架)的简写,是微软出品的用来

nginx反代httpd,实现三种tomcat代理模型至后端的tomcat服务器,会话绑定的三种方式

构建tomcat集群,实现前端一台nginx反代,到后端的apache服务器,由apache负责向后端的tomcat服务器进行资源调度,这样的模式比直接用nginx反代到后端主机,tomcat服务器所受到的压力会更小,服务将会更加稳定,这样的模式是经过实践检验出来的.如果nginx直接调度到后端tomcat服务器,则只支持http和https,而不支持ajp,http与https模式的设定,可以让外来客户直接访问tomcat服务器,而不需要经过我们设置好的前端nginx的端口,这样是十分不安全的

三种可视化格式模型:普通文档流、相对定位与绝对定位、浮动

在CSS中是有三种定位机制的:普通文档流.浮动和绝对定位.在未指定其它两种定位机制的情况下,所有框都是在普通文档流中定位的. 普通文档流: 普通文档流,顾名思义,就是根据块级元素的标签在HTML里的顺序,像水流一样,从上至下.当然对于行内元素而言,还是在一行中水平排列的. 这里插入一个积累的小知识点. 行内元素可 以在水平(内间距.边框.外边距)方向上修改它们水平尺寸,但是在垂直方向上对行内元素的高度是毫无影响的,还有就是直接定义行内元素的 width/height也是毫无影响.对与行内元素来说