一、Kafka消费者源码介绍

1.分区消费模式源码介绍

分区消费模式直接由客户端(任何高级语言编写)使用Kafka提供的协议向服务器发送RPC请求获取数据,服务器接受到客户端的RPC请求后,将数据构造成RPC响应,返回给客户端,客户端解析相应的RPC响应获取数据。
Kafka支持的协议众多,使用比较重要的有:
获取消息的FetchRequest和FetchResponse
获取offset的OffsetRequest和OffsetResponse
提交offset的OffsetCommitRequest和OffsetCommitResponse
获取Metadata的Metadata Request和Metadata Response
生产消息的ProducerRequest和ProducerResponse

2.组消费模式源码介绍

3.两种消费模式服务器端源码对比

分区消费模式具有以下特点:
指定消费topic、partition和offset通过向服务器发送RPC请求进行消费;
需要自己提交offset;
需要自己处理各种错误,如:leader切换错误
需要自己处理消费者负载均衡策略
组消费模式具有以下特点:
最终也是通过向服务器发送RPC请求完成的(和分区消费模式一样);
组消费模式由Kafka服务器端处理各种错误,然后将消息放入队列再封装为迭代器(队列为FetchedDataChunk对象) ,客户端只需在迭代器上迭代取出消息;
由Kafka服务器端周期性的通过scheduler提交当前消费的offset,无需客户端负责

Kafka服务器端处理消费者负载均衡
监控工具Kafka Offset Monitor 和Kafka Manager 均是基于组消费模式;

所以,尽可能使用组消费模式,除非你需要:
自己管理offset(比如为了实现消息投递的其他语义);
自己处理各种错误(根据自己业务的需求);

二、Kafka生产者源码介绍

1.同步发送模式源码介绍

2.异步发送模式源码介绍

3.两种生产模式服务器端源码对比

同步发送模式具有以下特点:
同步的向服务器发送RPC请求进行生产;
发送错误可以重试;
可以向客户端发送ack;
异步发送模式具有以下特点:
最终也是通过向服务器发送RPC请求完成的(和同步发送模式一样);
异步发送模式先将一定量消息放入队列中,待达到一定数量后再一起发送;
异步发送模式不支持发送ack,但是Client可以调用回调函数获取发送结果;

所以,性能比较高的场景使用异步发送,准确性要求高的场景使用同步发送

三、Kafka Server Reactor设计模型

1.认识Java NIO

Java NIO由以下几个核心部分组成 :
Channels;
Buffers;
Selectors

Selector允许单线程处理多个 Channel。使用Selector,首先得向Selector注册Channel,然后调用它的select()方法。此方法会一直阻塞到某个注册的Channel有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子如新连接进来,数据接收等。
下图为一个单线程中使用一个Selector处理3个Channel:
 

2.认识Linux epoll模型

epoll 是一种IO多路复用技术 ,在linux内核中广泛使用。常见的三种IO多路复用技术为select模型、poll模型和epoll模型。
select 模型需要轮询所有的套接字查看是否有事件发生 。缺点: (1)套接字最大支持1024个;(2)主动轮询效率很低;(3) 事件发生后需要将套接字从内核空间拷贝到用户空间,效率低
poll模型和select模型原理一样,但是修正了select模型最大套接字限制的缺点;
epoll模型修改主动轮询为被动通知,当有事件发生时,被动接收通知。所以epoll模型注册套接字后,主程序可以做其他事情,当事件发生时,接收到通知后再去处理。修正了select模型的三个缺点(第三点使用共享内存修正)。
Java NIO的Selector模型底层使用的就是epoll IO多路复用模型

3.Kafka Server Reactor模型

Kafka SocketServer是基于Java NIO开发的,采用了Reactor的模式(已被大量实践证明非常高效,在Netty和Mina中广泛使用)。Kafka Reactor的模式包含三种角色:
Acceptor;
Processor ;
Handler;
Kafka Reacator包含了1个Acceptor负责接受客户端请求,N个Processor线程负责读写数据(为每个Connection创建出一个Processor去单独处理,每个Processor中均引用独立的Selector),M个Handler来处理业务逻辑。在Acceptor和Processor,Processor和Handler之间都有队列来缓冲请求。

Acceptor的主要职责是监听客户端的连接请求,并建立和客户端的数据传输通道,然后为这个客户端指定一个Processor,它的工作就到此结束,这样它就可以去响应下一个客户端的连接请求了;
Processor的主要职责是负责从客户端读取数据和将响应返回给客户端,它本身不处理具体的业务逻辑,每个Processor都有一个Selector,用来监听多个客户端,因此可以非阻塞地处理多个客户端的读写请求,Processor将数据放入RequestChannel的RequestQueue 中和从ResponseQueue读取响应 ;
Handler(kafka.server.KafkaRequestHandler,kafka.server.KafkaApis)的职责是从RequestChannel中的RequestQueue取出Request,处理以后再将Response添加到RequestChannel中的ResponseQueue中;

四、Kafka Partition Leader选举机制

1.大数据常用的选主机制

Leader选举算法非常多,大数据领域常用的有 以下两种:
Zab(zookeeper使用);
Raft;
……

它们都是Paxos算法的变种。

Zab协议有四个阶段:
Leader election;
Discovery(或者epoch establish);
Synchronization(或者sync with followers)
Broadcast
比如3个节点选举leader,编号为1,2,3。1先启动,选择自己为leader,然后2启动首先也选择自己为 leader,由于1,2都没过半,选择编号大的为leader,所以1,2都选择2为leader,然后3启动发现1,2已经协商好且数量过半,于是3也选择2为leader,leader选举结束。

在Raft中,任何时候一个服务器可以扮演下面角色之一
Leader: 处理所有客户端交互,日志复制等,一般只有一个Leader;
Follower: 类似选民,完全被动
Candidate候选人: 可以被选为一个新的领导人

启动时在集群中指定一些机器为Candidate ,然后Candidate开始向其他机器(尤其是Follower)拉票,当某一个Candidate的票数超过半数,它就成为leader。

2.常用选主机制的缺点

由于Kafka集群依赖zookeeper集群,所以最简单最直观的方案是,所有Follower都在ZooKeeper上设置一个Watch,一旦Leader宕机,其对应的ephemeral znode会自动删除,此时所有Follower都尝试创建该节点,而创建成功者(ZooKeeper保证只有一个能创建成功)即是新的Leader,其它Replica即为Follower。

前面的方案有以下缺点:
split-brain (脑裂): 这是由ZooKeeper的特性引起的,虽然ZooKeeper能保证所有Watch按顺序触发,但并不能保证同一时刻所有Replica“看”到的状态是一样的,这就可能造成不同Replica的响应不一致 ;
herd effect (羊群效应): 如果宕机的那个Broker上的Partition比较多,会造成多个Watch被触发,造成集群内大量的调整;
ZooKeeper负载过重 : 每个Replica都要为此在ZooKeeper上注册一个Watch,当集群规模增加到几千个Partition时ZooKeeper负载会过重

3.Kafka Partition选主机制

Kafka 的Leader Election方案解决了上述问题,它在所有broker中选出一个controller,所有Partition的Leader选举都由controller决定。controller会将Leader的改变直接通过RPC的方式(比ZooKeeper Queue的方式更高效)通知需为此作为响应的Broker。
 

Kafka 集群controller的选举过程如下 :
每个Broker都会在Controller Path (/controller)上注册一个Watch。当前Controller失败时,对应的Controller Path会自动消失(因为它是ephemeral Node),此时该Watch被fire,所有“活”着的Broker都会去竞选成为新的Controller(创建新的Controller Path),但是只会有一个竞选成功(这点由Zookeeper保证)。竞选成功者即为新的Leader,竞选失败者则重新在新的Controller Path上注册Watch。因为Zookeeper的Watch是一次性的,被fire一次之后即失效,所以需要重新注册。

Kafka partition leader的选举过程如下 (由controller执行):
从Zookeeper中读取当前分区的所有ISR(in-sync replicas)集合
调用配置的分区选择算法选择分区的leader

所以,对于下图partition 0先选择broker 2,之后选择broker 0作为leader;对于partition 1 先选择broker 0,之后选择broker 1作为leader;partition 2先选择broker 1,之后选择broker 2作为leader。

四、Kafka 核心源码剖析的更多相关文章

  1. HashMap的结构以及核心源码分析

    摘要 对于Java开发人员来说,能够熟练地掌握java的集合类是必须的,本节想要跟大家共同学习一下JDK1.8中HashMap的底层实现与源码分析.HashMap是开发中使用频率最高的用于映射(键值对 ...

  2. HTTP流量神器Goreplay核心源码详解

    摘要:Goreplay 前称是 Gor,一个简单的 TCP/HTTP 流量录制及重放的工具,主要用 Go 语言编写. 本文分享自华为云社区<流量回放工具之 goreplay 核心源码分析> ...

  3. Android版数据结构与算法(五):LinkedHashMap核心源码彻底分析

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 上一篇基于哈希表实现HashMap核心源码彻底分析 分析了HashMap的源码,主要分析了扩容机制,如果感兴趣的可以去看看,扩容机制那几行最难懂的 ...

  4. Java内存管理-掌握类加载器的核心源码和设计模式(六)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇文章介绍了类加载器分类以及类加载器的双亲委派模型,让我们能够从整体上对类加载器有 ...

  5. 手撕spring核心源码,彻底搞懂spring流程

    引子 十几年前,刚工作不久的程序员还能过着很轻松的日子.记得那时候公司里有些开发和测试的女孩子,经常有问题解决不了的,不管什么领域的问题找到我,我都能帮她们解决.但是那时候我没有主动学习技术的意识,只 ...

  6. 并发编程之 SynchronousQueue 核心源码分析

    前言 SynchronousQueue 是一个普通用户不怎么常用的队列,通常在创建无界线程池(Executors.newCachedThreadPool())的时候使用,也就是那个非常危险的线程池 ^ ...

  7. iOS 开源库系列 Aspects核心源码分析---面向切面编程之疯狂的 Aspects

    Aspects的源码学习,我学到的有几下几点 Objective-C Runtime 理解OC的消息分发机制 KVO中的指针交换技术 Block 在内存中的数据结构 const 的修饰区别 block ...

  8. Backbone事件机制核心源码(仅包含Events、Model模块)

    一.应用场景 为了改善酷版139邮箱的代码结构,引入backbone的事件机制,按照MVC的分层思想搭建酷版云邮局的代码框架.力求在保持酷版轻量级的基础上提高代码的可维护性.   二.遗留问题 1.b ...

  9. 6 手写Java LinkedHashMap 核心源码

    概述 LinkedHashMap是Java中常用的数据结构之一,安卓中的LruCache缓存,底层使用的就是LinkedHashMap,LRU(Least Recently Used)算法,即最近最少 ...

随机推荐

  1. Internet History, Technology and Security (Week5.1)

    Week5 The Transport layer is built on the Internetwork layer and is what makes our network connectio ...

  2. wait 和 sleep 区别

    /* wait 和 sleep 区别? 1,wait可以指定时间也可以不指定. sleep必须指定时间. 2,在同步中时,对cpu的执行权和锁的处理不同. wait:释放执行权,释放锁. sleep: ...

  3. Java Lock & Condition

    /* jdk1.5以后将同步和锁封装成了对象. 并将操作锁的隐式方式定义到了该对象中, 将隐式动作变成了显示动作. Lock接口: 出现替代了同步代码块或者同步函数.将同步的隐式锁操作变成现实锁操作. ...

  4. WPF里面制作圆角文本框

    转自:http://www.cnblogs.com/mengxin523/archive/2010/04/04/1704448.html 本以为WPF里面的XAML会很强大,可以设置很多属性,比如文本 ...

  5. VS提示“无法启动IIS Express Web服务器”的解决方法

    有时在使用Visual Studio运行项目时,会提示“无法启动IIS Express Web服务器”,如图: 可以依次尝试以下方法(我的情况使用第一种就解决了): 1.可能原因:误操作执行了:Sc ...

  6. 更新ubuntu的源

    什么是Ubuntu的软件源? 我们在使用Debian或者Ubuntu的apt-get工具来安装需要的软件时,其实就是从服务器获取需要安装的软件并把它安装在本地计算机的过程.所谓的软件源,就是我们获取软 ...

  7. String、StringBuffer与StringBuilder比较

    关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下 1.三者在执行速度方面的比较:     StringBuilder > St ...

  8. STM32CubeMX介绍、下载与安装

    一.简介 STM32CubeMX是一个配置STM32代码的工具,它把很多东西封装的比较好,硬件抽象层.中间层.示例代码等.现在ST公司升级和维护的库主要就是STM32CubeMX的HAL库和标准外设库 ...

  9. 解决MySQL Slave 触发 oom-killer

    最近经常有收到MySQL实例类似内存不足的报警信息,登陆到服务器上一看发现MySQL 吃掉了99%的内存,God ! 有时候没有及时处理,内核就会自己帮我们重启下MySQL,然后我们就可以看到 dme ...

  10. 【开发工具IDE】eclipse的SVN提交忽略target等多余文件

    这个build失败的解决方案就是不要把你项目的 target目录放在src repository 里面,还有 .project 和 .classpath最好也别放到src repository 里. ...