阅读 221

初识kafka集群

kafka常见的集群部署模式

1. Hub架构。一个中心的kafka集群做中央调度,对应多个本地的kafka集群。

变种是一个关键的kafka集群对应一个非关键的跟随者
  • 优点:只有本地用到的数据就在本地使用,多个数据中心需要用到的数据就放在中央,从本地同步到远程的次数也就只有一次,这样读取的时候,需要本地的就本地读,否则远程读,也就是消费者只需要从一个集群读数据即可
  • 缺点:一个数据中心的不能访问另一数据中心的

2. 双活架构。 多个集群之间保持数据同步。

  • 优点:一个集群挂掉可以直接转向另外一个,而且可以就近的提供服务
  • 缺点:集群之间同步数据如何避免冲突,保证数据一致性

3. 主备架构。有两个集群,平常只用主集群, 另外一个集群只有当主集群出了问题才用。

  • 优点:不需要担心数据访问和冲突问题
  • 缺点:有一个集群的资源浪费,同时需要考虑备份的量的问题,以及恢复的过程中是否可以重复数据或者丢失部分数据

4. 延展集群。单个数据中心故障的时候,重新定位到另一个数据中心 。

  • 优点:有一定的灾备能力,一个中心挂了,使用另一个,延展集群不是多个集群而是一个集群,使用的方式是kafka内部的复制机制,把数据放到其他的broker,而不是集群之间的复制与同步
  • 缺点:kafka本身出了问题无法避免


新节点的新建与关闭

  1. 新建节点;每个broker都有一个唯一的标识符,新的broker启动的时候,会创建一个临时节点,把自己的ID注册到zk,如果zk中已经有一个一样的ID存在,会得到错误,注册失败。如果注册成功,且集群中有着一个与新ID一样的旧ID副本,那么新的broker会立即加入集群,并拥有与旧broker相同的分区和主题
  2. 节点异常/关闭;启动时穿件的临时节点会从zk上自动移除,监听broker列表的kafka组件会被告知该broker已经移除,broker对应节点消失,但是它的ID会继续存在于其他数据结构中
比如主题副本列表

什么是副本?

分区数据的拷贝。分为两种类型:
1. 首领副本。负责分清那个跟随者状态与自己一致。每个分区都有一个,所有生产者和消费者请求都会经过它。
2. 跟随者副本。首领以外的副本。不处理客户端的请求。仅从首领复制消息,如果首领崩溃,他们中的同步副本会被提升为新首领。

首领与跟随者之间的消息同步

在有新消息到达时,跟随者会向首领发送获取数据的请求。一个跟随者副本首先请求消息1,然后消息2,然后消息3;如果没有收到这3个消息的响应,不会再次请求消息4。  

持续请求最新消息的副本也被称作同步的副本

如果跟随者发送了请求消息4,,那么知道消息被同步了,如果跟随者10s内没有请求消息,或者没有请求最新的消息,此跟随者被当做不同步。

没有同步的副本是不可能成为新的首领的

首选首领

创建主题时候选定的首领即分区首选首领。如果首选首领不是当前首领,并且该副本是同步的,就会触发首领选举,使得首选首领称为当前首领

如何对消息进行分区?

kafka具备默认的分区器。如果key没有,就通过Round robin算法将消息发送到各个可用的分区上,如果key存在,就对键进行散列

只有主题分区数不可变的时候,映射才有用

如何分配分区?

创建主题的时候,kafka先决定broker的分配。它的总原则是:broker之间平均分步分区副本;每个分区的副本分布在不同的broker上

轮询,比如broker0是首领,那么1是跟随者,类推。如果有机架信息,会尽可能使得副本分配到不同机架上。
分配好副本之后,选择数据存储目录,每个分区会有单独的目录,新的分区总被添加到分区数小的目录里面

假设有新磁盘,那么新分区会在新磁盘上。注意这里没有考虑分区的大小,仅仅看数量

控制器与集群的关系

控制器本身是一个兼具分区首领选举的broker

1. 集群中第一个启动的broker通过在zk中创建一个临时节点 /controller 使自己成为控制器。其它节点启动时同样会进行这个操作,但只会收到 节点点存在 的异常,其它节点只会在 控制器节点上创建zk watch对象接收节点的变更通知
确保集群只有一个控制器
2. 控制器关闭或者异常时,watch对象告知各个broker,他们进而尝试成为控制器,第一个成功的会成为控制器,其它则创建watch对象。新的控制器会获得更大的controller epoch,其它broker获知当前的epoch之后,如果发现比当前要小的epoch则忽略


3. 有节点退出时,如果broker包含首领,则控制器遍历分区确定新首领,然后向包含新首领或现有的跟随者发请求消息,告知谁是新首领和谁是分区跟随者。新broker加入时,检查broker ID是否有现成的分区副本,有的话变更消息发送给新的broker和其它broker,新broker上副本开始从首领复制消息

分区新增时,消费者如何处理?

新增分区会发生分区重分配。

消费者群组新加入消费者怎么处理?

1. 新加入的消费者它读取的消息是原本属于其它消费者读取的消息,一个消费者关闭或者崩溃则离开群组,原本应该被它读取的消息由其它消费者接受。
2. 再均衡。即分区的所有权从一个消费者转移到另一个消费者。这个过程中,消费者群无法处理消息。
3. 分区的所有权则通过消费者向被指派的 群组协调器 的broker发送心跳来维持,同时消费者的心跳行为也用来维持和群组的从属关系。如果消费者停止发送心跳的时间足够长,会话会过期,群组协调器认为它已经死亡,触发再均衡

第一个加入消费组的是群组。负责给每一个消费者分配分区

能不能不要消费组?

可以。一个消费者可以自己订阅主题并加入消费组,或者为自己分配分区

不能同时做这两件事

不过分配分区如果主题添加了新的分区,消费者不会收到通知,需要周期性的调用consumer.partitionsFor方法或者重启。

自己分配分区后是不会发生再均衡以及手动查找分区,其余一样


消费者与消费分区是如何对应的?

消费者从属于一个消费群组,一个群组里的消费者订阅同一个主题,每个消费者接受主题一部分分区的消息。消费者的数量应该小于等于分区的数量,如果消费者的数量超过分区数,那么超过部分会被闲置。不同消费组群互相不影响,如果一个应用要处理多个主题,可以让多个主题公用一个消费者群组