集群下的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会重新生成这些索引。