概述
生产者
消费者群组再均衡
消费者的配置
深入理解Kafka
集群成员关系
Kafka使用 Zookeeper来维护集群成员的信息.
每个broker都有唯一的标识符,可以配置指定,也可以自动生成。
在broker启动时,他通过创建临时节点把自己注册到zk。
broker订阅zk的/brokers/ids路径,当有broker加入或者退出集群时,这些组件可以获得通知。
在关闭 broker时,它对应的节点也会消失,不过它的 ID会继续存在于其他数据结构中。例如,主题的副本列表(下面会介绍)里就可能包含这些ID。
在完全关闭一个 broker之 后,如果使用相同的 ID 启动另一个全新的 broker,它会立即加入集群,井拥有与旧 broker 相同的分区和主题。
控制器
控制器其实就是 一 个 broker,只不过它除了具有一般 broker 的功能之外,还负责分区 首领的选举。
哪个broker可以成为控制器?
在集群启动时,所有broker都会尝试在zk创建节点/controller,但是只有一个broker可以创建成功,它就是控制器。
非控制器的broker节点会在控制器节点创建zk watch对象,用于接收这个节点的变更通知。
通过watch对象得知控制器节点消失,那么其他broker节点会进入下一轮的首领选举,选举成功会有一个新的递增的ID产生。
新broker加入集群会发生什么?
控制器会检查新broker是否包含现有分区的副本,如果有,则通知其他broker,允许新的broker同步分区副本。
broker退出集群会发生什么?
控制器监听到broker离开集群的消息,check哪些分区首领在该broker上。然后再其他broker上选举新的分区首领,并通知所有broker新的分区首领。
复制
kafka是一个分布式的、可分区的、可复制的提交日志服务。
复制什么?
每个topic由对个partition、每个partition有多个副本,其中一个是首领副本,其他是跟随者副本。
该partition的生产者和消费者请求都会经过首领副本。
复制就发生在首领副本和跟随者副本之间。
当首领副本崩溃时,其中一个跟随者副本可以提升为首领副本。
当首领副本崩溃时,哪个跟随者副本可以提升为首领副本
不同步的跟随者是不能成为首领的
什么标准判断一个跟随者是不同步的?
跟随者请求同步时总是按照offset递增的顺序请求同步的消息,而且总是在收到上一个请求的影响之后才会发出下一个请求。所以当首领收不到follower的请求最新的offset时或者一定时间内收不到follower的同步请求时,认为这个follower是不同步的。这个一定时间可以通过replica.lg.time.max.ms配置。
首选首领是可以优先称为下一届首领的。
首选首领是在创建分区时,为了在broker之间均衡首领选举的分区首领。
处理请求
broker 的大部分工作是处理客户端、分区副本和控制器发送给分区首领的请求。
producer的生产请求和consumer的获取请求都必须发送给分区的首领副本。
那么客户端怎么知道谁是首领副本呢?
客户端使用了另一 种请求类型,也就是元数据请求。请求到元数据后缓存在本地。
通过配置matedata.max.age.ms设置定时刷新元数据。
生产者请求
包含首领副本的 broker在收到生产请求时,会对请求做一些验证
- 发送数据的用户是否有主题的写权限
- 请求里的acks值是否是有效值(只允许0、1、all)
- 如果acks=all,是否有足够的读本保证消息已经被安全写入?
以上都做完给客户端相应。
消费者请求
客户端可以指定broker最多从一个分区里返回多少数据,这是有必要的,因为broker返回大量的数据有可能撑爆客户端的buffer
broke会check请求是否有效,比如请求的偏移量是否存在,如果存在,则用零拷贝的方式返回数据。
客户端也可以指定broker积攒一定的数据再返回,避免频繁的网络IO。
并不是首领副本上的消息都可以返回给客户端,只有被所有follower同步了的消息才可以返回给客户端。
物理存储
kafka的基本存储单元是分区。
log.dirs配置用于指定存储分区的目录。
如何做分区和broker之间的分配
加入要在6个broker的kafka集群上创建分区数为10复制系数为3的主题,那么这30个分区副本如何分配给6个broker?
做分区和broker之间的分配要遵循以下原则:
- 在broker间平均的分布分区副本
- 每个分区的副本尽可能的分布在不同的broker上
- 如果制定了broker的机架信息,尽可能的把每个分区的副本分配到不同的机架上
依照这个规则,分配方式可以如下:
- 先均匀分配首领分区。随机选一个broker,轮训的方式给每个broker分配分区来确定首领分区的位置。
- 再均匀分配分区副本。以首领分区为起点,了轮训分配分区副本。
- 指定机架信息的时候,均匀分配分区的方式。假设 broker0、 broker1和 broker2放置在同一个机架上, broker3、 broker4 和 broker5分别放置在其他不同的机架上,那么在轮训分配的时候,我们不是按照从 0到 5的顺序来选择 broker,而 是按照 0, 3, 1, 4, 2, 5 的顺序来选择。
如何做文件管理
因为在一个大文件中查找和删除是非常耗时的,所以我们把分区分成若干个片段。默认每个片段包含1G或者1周的数据。
当前正在写入数据的片段叫做活跃片段。活跃片段永远不会被删除。
broker会为分区的每个片段打开一个文件句柄,这会导致打开过多的文件句柄,所以操作系统必须根据实际情况做一些调优。
broker如何在一个分区的众多文件中定位指定的offset位置?
kakfa为每个分区文件建立索引,根据索引可以快速定位offset在文件中的位置。
如果有必要,管理员可以删除索引,kafka会重新生成这些索引。