【Kafka从入门到放弃系列 六】Kafka架构深入——高并发读写及Zookeeper管理

分别了解了【Kafka从入门到放弃系列 四】Kafka架构深入——生产者策略【Kafka从入门到放弃系列 五】Kafka架构深入——消费者策略后我们来了解下Zookeeper是如何进行管理的。

Kafka高效读写数据

Kafka是如何保证高效读写数据的呢,有三点支持:分布式读写、顺序写磁盘以及零拷贝技术,其实前两点在之前的blog中也有提到

  • 分布式读写,我们提到的各种策略都是为了满足分布式的可靠高效读写
  • 顺序写磁盘,Kafka 的 producer 生产数据,要写入到 log 文件中,写的过程是一直追加到文件末端,为顺序写。同样的磁盘,顺序写能到 600M/s,而随机写只有 100K/s。这与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间
  • 零拷贝技术,简单来说就是数据不需要经过用户态,详细原理可以参照Kafka是如何利用零拷贝提高性能的

通过以上这几种技术可以实现Kafka的高并发读写

Zookeeper管理

在基于 Kafka 的分布式消息队列中,ZooKeeper 的作用有:broker 注册、topic 注册、producer 和 consumer 负载均衡、维护 partition 与 consumer 的关系、记录消息消费的进度以及 consumer 注册等。
在这里插入图片描述

注册broker

broker是注册在zookeeper中的,还记得在分布式集群搭建的时候,我们在zk的配置文件中添加的服务节点,就是用来注册broker的。

  • 为了记录 broker 的注册信息,在 ZooKeeper 上,专门创建了属于 Kafka 的一个节点,其路径为 /brokers
  • Kafka 的每个 broker 启动时,都会到 ZooKeeper 中进行注册,告诉 ZooKeeper 其 broker.id,在整个集群中,broker.id 应该全局唯一,并在 ZooKeeper 上创建其属于自己的节点,其节点路径为/brokers/ids/{broker.id}
  • 创建完节点后,Kafka 会将该 broker 的 broker.name 及端口号记录到该节点;
  • 另外,该 broker 节点属性为临时节点,当 broker 会话失效时,ZooKeeper 会删除该节点,这样,我们就可以很方便的监控到broker 节点的变化,及时调整负载均衡等。
    在这里插入图片描述
    当然注册完broker还需要注册topic

注册topic

在 Kafka 中,所有 topic 与 broker 的对应关系都由 ZooKeeper 进行维护,在 ZooKeeper 中,建立专门的节点来记录这些信息,其节点路径为 /brokers/topics/{topic_name}。 前面说过,为了保障数据的可靠性,每个 Topic 的 Partitions 实际上是存在备份的,并且备份的数量由 Kafka 机制中的 replicas 来控制。

  • 选举leader,Kafka 为每一个 partition 找一个节点作为 leader,其余备份作为 follower
  • 副本同步,当 producer push 的消息写入 partition(分区) 时,作为 leader 的 broker(Kafka 节点) 会将消息写入自己的分区,同时还会将此消息复制到各个 follower,实现同步
  • 维护ISR如果某个follower 挂掉,leader 会再找一个替代并同步消息
  • 重新选举leader如果 leader 挂了,follower 们会选举出一个新的 leader 替代,继续业务

所有的这些操作都是zookeeper做的

注册consumer

在消费者端zookeeper做的工作有那些呢?

  • 注册新的消费者分组,当新的消费者组注册到 ZooKeeper 中时,ZooKeeper 会创建专用的节点来保存相关信息,其节点路径为 /consumers/{group_id},其节点下有三个子节点,分别为 [ids, owners, offsets]。ids 节点:记录该消费组中当前正在消费的消费者;owners 节点:记录该消费组消费的 topic 信息;offsets 节点:记录每个 topic 的每个分区的 offset当然新版本的不记录在zookeeper中
  • 注册新的消费者,当新的消费者注册到 Kafka 中时,会在 /consumers/{group_id}/ids 节点下创建临时子节点,并记录相关信息。
  • 监听消费者分组中消费者的变化,每个消费者都要关注其所属消费者组中消费者数目的变化,即监听 /consumers/{group_id}/ids 下子节点的变化。一单发现消费者新增或减少,就会触发消费者的负载均衡。

其实不光是注册consumer,还包括对消费者策略的管理。

Producers 负载均衡

对于同一个 topic 的不同 partition,Kafka会尽力将这些 partition 分布到不同的 broker 服务器上,这种均衡策略实际上是基于 ZooKeeper 实现的

  • 监听broker变化,producers 启动后也要到 ZooKeeper 下注册,创建一个临时节点来监听 broker 服务器列表的变化。由于在 ZooKeeper 下 broker 创建的也是临时节点,当 brokers 发生变化时,producers 可以得到相关的通知,从改变自己的 broker list。
  • 监听topic变化,topic 的变化以及broker 和 topic 的关系变化,也是通过 ZooKeeper 的 Watcher 监听实现的

当broker变化以及topic变化的时候,zookeeper能监听到,并控制消息和分区的分布。

Consumer 负载均衡

consumers 在启动时会到 ZooKeeper 下以自己的 conusmer-id 创建临时节点 /consumer/[group-id]/ids/[conusmer-id],并对 /consumer/[group-id]/ids 注册监听事件:

  • 监听消费者列表,当消费者发生变化时,同一 group 的其余消费者会得到通知。
  • 监听broker列表,消费者还要监听 broker 列表的变化。

然后按照我们之前提到的策略进行排序和消费

记录消费进度 Offset

在 consumer 对指定消息 partition 的消息进行消费的过程中,需要定时地将 partition 消息的消费进度 Offset 记录到 ZooKeeper上,以便在该 consumer 进行重启或者其它 consumer 重新接管该消息分区的消息消费权后,能够从之前的进度开始继续进行消息消费,当然现在已经推荐记录在一个特定的topic上了

记录 Partition 与 Consumer 的关系

consumer group 下有多个 consumer(消费者),对于每个消费者组(consumer group),Kafka都会为其分配一个全局唯一的 group ID,group 内部的所有消费者共享该 ID。订阅的 topic 下的每个分区只能分配给某个 group 下的一个consumer(当然该分区还可以被分配给其它 group)。同时,Kafka 为每个消费者分配一个 consumer ID,通常采用 hostname:UUID 形式表示。

  • 记录partition 与 consumer 的关系,在Kafka中,规定了每个 partition 只能被同组的一个消费者进行消费,因此,需要在 ZooKeeper 上记录下 partition 与 consumer 之间的关系

每个 consumer 一旦确定了对一个 partition 的消费权力,需要将其 consumer ID 写入到 ZooKeeper 对应消息分区的临时节点上

部分内容来自:https://gitbook.cn/books/5ae1e77197c22f130e67ec4e/index.html

猜你喜欢

转载自blog.csdn.net/sinat_33087001/article/details/108398136
今日推荐