虽然这是一个源码的预热篇一样这也是插曲篇的一个总结,咱们从一开始的集群的各个角色,到集群的设计,到网络模型,到生产者,消费者都已经提了个遍。这一篇会把最后的一个内核提一下,而后对以往的概念三篇作一个总结,把流程梳理一下,增长记忆的同时,也让后面的源码变得更加轻松愉快,好的这是最后一次鸽了🤣。html
概念①:插曲:大白话带你认识Kafkajava
实践的:插曲:Kafka的集群部署实践及运维相关bootstrap
概念②:插曲:Kafka的生产者原理及重要参数说明安全
概念③:插曲:Kafka的生产者案例和消费者原理解析服务器
没啥的:插曲:Kafka源码预热篇--- Java NIO网络
在Kafka的生产者案例和消费者原理解析中咱们提到kafka的内核里还有个 LEO&HW 原理,如今补充回来。架构
首先这里有两个Broker,也就是两台服务器,而后它们的分区中分别存储了两个p0的副本,一个是leader,一个是follower 负载均衡
此时生产者往leader partition发送数据,数据最终确定是要写到磁盘上的。而后follower会从leader那里去同步数据,follower上的数据也会写到磁盘上框架
但是follower是先从leader那里去同步再写入磁盘的,因此它磁盘上面的数据确定会比leader的那块少。运维
LEO(last end offset)就是该副本底层日志文件上的数据的最大偏移量的下一个值,因此上图中leader那里的LEO就是5+1 = 6,follower的LEO是5。以此类推,当我知道了LEO为10,我就知道该日志文件已经保存了10条信息,位移范围为[0,9]
HW(highwater mark)就是水位,它必定会小于LEO的值。这个值规定了消费者仅能消费HW以前的数据。
follower在和leader同步数据的时候,同步过来的数据会带上LEO的值,但是在实际状况中有可能p0的副本可能不只仅只有2个。此时我画多几个follower(p0),它们也向leader partition同步数据,带上本身的LEO。leader partition就会记录这些follower同步过来的LEO,而后取最小的LEO值做为HW值
这个作法是保证了若是leader partition宕机,集群会从其它的follower partition里面选举出一个新的leader partition。这时候不管选举了哪个节点做为leader,都能保证存在此刻待消费的数据,保证数据的安全性。
那么follower自身的HW的值如何肯定,那就是follower获取数据时也带上leader partition的HW的值,而后和自身的LEO值取一个较小的值做为自身的HW值。
如今你再回想一下以前提到的ISR,是否是就更加清楚了。follower若是超过10秒没有到leader这里同步数据,就会被踢出ISR。它的做用就是帮助咱们在leader宕机时快速再选出一个leader,由于在ISR列表中的follower都是和leader同步率高的,就算丢失数据也不会丢失太多。
并且咱们以前没提到什么状况下follower能够返回ISR中,如今解答,当follower的LEO值>=leader的HW值,就能够回到ISR。
但是按照刚刚的流程确实没法避免丢失部分数据的状况,固然也是有办法来保证数据的完整的,我们留到源码篇以后进行总结的时候再提。
在大白话篇中带过你们画,如今再来一遍。
首先来两个Broker(这集群好歹要超过1个服务器才能叫集群吧),而后它们启动的时候会往zookeeper集群中注册,这时候这两台服务器会抢占一个名字叫controller的目录,谁抢到了,谁就是controller。好比如今第一台Broker抢到了。那它就是controller,它要监听zookeeper中各个目录的变化,管理整个集群的元数据。
此时咱们经过客户端来用命令来建立一个主题,这时候会有一个主题的分区方案写入到zookeeper的目录中,而在controller监听到这个目录写入了分区方案(其实就是一些元数据信息)以后,它也会更改本身的元数据信息。以后其余的Broker也会向controller来同步元数据。保证整个集群的Broker的元数据都是一致的
此时再好比咱们如今经过元数据信息得知有一个分区p0,leader partition在第一台Broker,follower partition在第二台Broker。
此时生产者就该出来了,生产者须要往集群发送消息前,要先把每一条消息封装成ProducerRecord对象,这是生产者内部完成的。以后会经历一个序列化的过程。接下来它须要过去集群中拉取元数据(因此你们知道为啥在 插曲:Kafka的生产者原理及重要参数说明 的 1-⑤-1 生产者代码里面为啥要提供一个或多个broker的地址了吧),当时的代码片断以下
props.put("bootstrap.servers", "hadoop1:9092,hadoop2:9092,hadoop3:9092");
复制代码
由于若是不提供服务器的地址,是无法获取到元数据信息的。此时生产者的消息是不知道该发送给哪一个服务器的哪一个分区的。
此时生产者不着急把消息发送出去,而是先放到一个缓冲区。把消息放进缓冲区以后,与此同时会有一个独立线程Sender去把消息分批次包装成一个个Batch。整好一个个batch以后,就开始发送给对应的主机上面。此时通过 大白话篇 中加餐时间所提到的Kafka的三层网络架构模型,写到os cache,再继续写到磁盘上面。
以后写磁盘的过程又要将 Kafka的生产者案例和消费者原理解析 中提到的日志二分查找,和刚刚才提完的ISR,LEO和HW。由于当leader写入完成时,follower又要过去同步数据了。
此时消费者组也进来,这个消费者组会有一个它们的group.id号,根据这个能够计算出哪个broker做为它们的coodinator,肯定了coordinator以后,全部的consumer都会发送一个join group请求注册。以后coordinator就会默认把第一个注册上来的consumer选择成为leader consumer,把整个Topic的状况汇报给leader consumer。以后leader consumer就会根据负载均衡的思路制定消费方案,返回给coordinator,coordinator拿到方案以后再下发给全部的consumer,完成流程。
因此这样就把咱们的插曲系列中提到的全部的知识点都连起来了,基本上囊括了全部必须知道的知识点。这么大一件事情所有都是分开一篇一篇一个个小的知识点按部就班地阐述完整的。若是对Kafka感兴趣的朋友,真的推荐把以前的那几篇均可以读一下,相信对你必定有所帮助。
源码篇中Java NIO的基础知识(看到没有,基础是重点字,不要求高级的)和scala是两个条件,不过若是是对scala没了解的朋友也不须要担忧,它和Java十分相似。相信配合必定的解释的话,必定也能够看懂全部的套路。
Kafka的版本是0.10.1版本,最新的应该是2.2.x了。核心流程都没太大变化,老版本相比新版本更加的稳定,老一点的版本代码结构会更清晰,由于像这种开源的项目,不少人都会去提交一些patch,可是提交patch的人员不必定是最优秀的那一群,会让新的版本代码看起来很混乱,学习起来就天然不太方便了
Kafka一开始出来的时候其源码是用scala写的,可是后面producer端和consumer端的代码用java重写了,可是server端的源码还一直用的scala写的,因此咱们分析Kafka的源码须要安装scala的环境。
我使用的是2.11.8版本,下载好配置环境变量便可(经过度娘能够完美完成,和Java的配置也很相像,这里不展开了)。
IDEA须要安装一个scala的插件,在Settings-plugins那里,直接搜索scala便可。
Kafka的源码没有采用maven去管理,而是用的gradle,你们就把这个想成是一个相似于maven的代码管理工具便可。安装它的方式跟安装maven同样。
KafkaProducer:
(难的,这个行了其它都是行的,并且源码写的很优秀,估计要分好几篇慢慢来)
Server:
(有了上面的Producer以后就不会很难了)
KafkaConsumer:
(很是基础,不太须要讲,其实大数据的框架关于读数据的部分都不算太难)
复制代码
若是要一个一个类地去说明,那确定会很是乱套的,因此要借助场景去阐述巧了,这个场景甚至还不须要我来写。看见源码里面有个example包了吗?大部分的大数据框架都是开源的,为了推广,首先官方文档要写的详细,并且还得本身提供一些不错的示例包才方便。从如今开始,讲解基本依靠代码注释。
下一篇就从这里开始。你们共勉,一块儿努力