kafka集群、请求、存储

把书读薄(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是跟随者,类推】;如果有机架信息,会尽可能使得副本分配到不同机架上。
分配好副本之后,选择数据存储目录,每个分区会有单独的目录,新的分区总被添加到分区数小的目录里面【假设有新磁盘,那么新分区会在新磁盘上】。注意这里没有考虑分区的大小,仅仅看数量
【分区是用来做水平扩展的,真正的数据是在副本的逻辑概念,所用请求从首领副本中经过】


数据保留时长是多少?

每个主题可以配置保留时长或者大小。每个分区会有若干个片段【默认1G或者一周,以小的为准,一个片段数据满了则关闭当前文件,打开新的,方便查找和删除】,当前写入数据的片段【活跃片段】,永远不会被删除,假如配置了保留5天的数据,那么会保留5天


数据存储的文件格式?

储存格式与生产者发送,发送给消费者的格式一致。消息里不仅包含建和值,同时有大小,检验和,版本,压缩算法,时间戳


如何直接删除某个键?

应用程序发送一个相同的键,但是值为null的消息【称为墓碑消息】,进行常规清理时,只保留null消息,一段时间后,消费者消费时发现null的记录,知晓应该从数据库中删除,这段时间后,清理线程便清理掉墓碑消息【消费者如果离线了就干不掉了】


kafka的compact策略?

适用场景:消息中存在一样的key,但是只需要保留最新的key的value。执行compact的时候,会早内存中构建一个map,key是消息键的hash,值是消息键的偏移量,读取一定量的污浊消息每个片段后,如果当前的消息key存在且偏移量小,值过期,或者是null,就抛弃,否则保存


kafka的零拷贝?

零拷贝依赖于操作系统。kafka中存在大量数据持久化道磁盘和磁盘文件通过网络发送。传统的方式来说,经历4次拷贝。首先系统将调用文件数据读到内存态Buffer,然后应用程序将内核态读入道用户态buffer,接着用户通过socket发送数据将用户态拷贝到内核态buffer,最后通过DMA拷贝将数据拷贝到NIC 【4次上下文切换】,在linux2.4+操作系统,sendfile系统调用通过零拷贝,数据从DMA拷贝到NIC Buffer,无需CPU拷贝【零拷贝来源,只有两次上下文切换】








猜你喜欢

转载自blog.csdn.net/weixin_39687783/article/details/80148882