把书读薄(Kafka权威指南 第五章)
单节点与集群关系
1. 新建节点;每个broker都有一个唯一的标识符,新的broker启动的时候,会创建一个临时节点,把自己的ID注册到zk,如果zk中已经有一个一样的ID存在,会得到错误,注册失败。如果注册成功,且集群中有着一个与新ID一样的旧ID副本,那么新的broker会立即加入集群,并拥有与旧broker相同的分区和主题2. 节点异常/关闭;启动时穿件的临时节点会从zk上自动移除,监听broker列表的kafka组件会被告知该broker已经移除,broker对应节点消失,但是它的ID会继续存在于其他数据结构中【比如主题副本列表】
控制器与集群的关系
1. 控制器本身是一个兼具分区首领选举的broker。集群中第一个启动的broker通过在zk中创建一个临时节点 /controller 使自己成为控制器。其它节点启动时同样会进行这个操作,但只会收到 几点存在 的异常,其它节点只会在 控制器节点上创建zk watch对象接收节点的变更通知【确保集群只有一个控制器】。2. 控制器关闭或者异常时,watch对象告知各个broker,,他们进而尝试成为控制器,第一个成功的会成为控制器,其它则创建watch对象。新的控制器会获得更大的controller epoch,其它broker获知当前的epoch之后,如果发现比当前要小的epoch则忽略
3. 有节点退出时,如果broker包含首领,则控制器遍历分区确定新首领,然后向包含新首领或现有的跟随者发请求消息,告知谁是新首领和谁是分区跟随者。新broker加入时,检查broker ID是否有现成的分区副本,有的话变更消息发送给新的broker和其它broker,新broker上副本开始从首领复制消息
什么是副本?
分区数据的拷贝。分为两种类型:1. 首领副本。负责分清那个跟随者状态与自己一致。每个分区都有一个,所有生产者和消费者请求都会经过它。
2. 跟随者副本。首领意外的副本。不处理客户端的请求。仅从首领复制消息,如果首领崩溃,他们中的同步副本会被提升为新首领。
副本之间的消息同步机制?
1. 跟随者请求消息的原则。请求类型与消费者获取消息发送的请求一样,包括跟随者想要知道的消息偏移量【他们是有序的】。它会先请求消息1,然后消息2,然后消息3;如果没有收到这3个消息的响应,不会再次请求消息4。2. 副本首领知道同步副本的方式。跟随者发出了消息4,那么知道消息被同步了,如果跟随者10s内没有请求消息,或者没有请求最新的消息,,此跟随者被当做不同步
首选首领
创建主题时候选定的首领即分区首选首领。负责broker之间均衡首领,如果首选首领不是当前首领,并且该副本是同步的,就会触发首领选举,使得首选首领称为当前首领常见请求类型?
1. 生产请求:生产者发送的请求,包含客户端写入broker的消息。必须发给分区的首领副本。broker接收到生产请求是,会做一些基本验证,比如是否有写入权限?acks值是否有效【消息是否写成功的标志】?acks=all时是否有足够多的同步副本保证消息被安全写入?。然后消息被写入磁盘【linux上消息被写到文件系统缓存,但不保证何时刷到磁盘】,kafka不等待写到磁盘上,消息写入分区首领后,broker检验acks,ackas条件满足后,返回给客户端2. 获取请求:从broker读取消息是发的请求。必须发给分区的首领副本。它可以指定请求的偏移量,数据量上限和下限,以及等待累积数据的时长,时长满足但未达到下限仍然可以返回结果。只有当所有的同步副本数据完成后,数据才会发送给消费者,否则返回空
3. 元数据请求:客户端获取首领副本的方式。它的请求包含客户端感兴趣的主题列表,响应指明这些主题所包含的分区,每个分区的副本,谁是首领副本【这些信息每个broker都有缓存】
如何处理请求?
1. kafka提供一个二进制协议,指定请求消息格式。broker会在它所监听的端口上运行Acceptor线程,它会创建连接给processor【网络线程】线程处理,processor获取请求消息后扔到请求队列,由IO线程来处理请求,然后结果被写入响应队列,processor从中取出响应给kafka客户端。2. kafka客户端一般会缓存各首领副本的信息,当发送请求接受的broker不是首领副本的时候,返回 非分区首领 异常,这时候客户端会先刷新元数据,再重新发送请求【也会有一个时间间隔来定时更新客户端的元数据】
如何分配分区?
创建主题的时候,kafka先决定broker的分配。它的总原则是:broker之间平均分步分区副本;每个分区的副本分布在不同的broker上【轮询,比如broker0是首领,那么1是跟随者,类推】;如果有机架信息,会尽可能使得副本分配到不同机架上。分配好副本之后,选择数据存储目录,每个分区会有单独的目录,新的分区总被添加到分区数小的目录里面【假设有新磁盘,那么新分区会在新磁盘上】。注意这里没有考虑分区的大小,仅仅看数量
【分区是用来做水平扩展的,真正的数据是在副本的逻辑概念,所用请求从首领副本中经过】