ZooKeeper
ZooKeeper,它是一个分布式的协调服务,它的核心服务是一个高可用、高可靠的一致性存储,在此基础上,提供了包括读写元数据、节点监控、选举、节点间通信和分布式锁等很多功能。
ZooKeeper分布式协调服务框架主要用来解决分布式集群中,应用系统需要面对的各种通用的一致性问题。ZooKeeper 本身可以部署为一个集群,集群的各个节点之间可以通过选举来产生一个 Leader,选举遵循半数以上的原则,所以一般集群需要部署奇数个节点。
最核心的功能,它提供了一个分布式的存储系统,数据的组织方式类似于UNIX 文件系统的树形结构。由于这是一个可以保证一致性的存储系统,所以你可以放心地在你的应用集群中读写 ZooKeeper 的数据,而不用担心数据一致性的问题。分布式系统中一些需要整个集群所有节点都访问的元数据,比如集群节点信息、公共配置信息等,特别适合保存在 ZooKeeper 中。其中这个树形的存储结构称为ZNode。
临时节点:是一种特殊的ZNode类型,临时节点有一个特性,如果创建临时节点的客户端与ZooKeeper集群失去连接,这个临时节点就会自动消失。通过与ZooKeeper的心跳状态来判断是否移除无用临时节点。
Watcher:是ZooKeeper提供的一种订阅ZNode状态变化的通知机制。一旦 ZNode 或者它的子节点状态发生了变化,订阅的客户端会立即收到通知。
Kafka与ZooKeeper关系
Kafka 主要使用 ZooKeeper 来保存它的元数据、监控 Broker 和分区的存活状态(利用ZooKeeper临时节点以及Watcher机制来监控其集群节点的状态变化),并利用ZooKeeper 来进行选举,保证其高可用性。
Kafka在ZooKeeper中保存元数据信息
其中如图所示 绿色节点为临时节点,其余为持久化节点
左侧树代表着Kafka 的 Broker 信息,/brokers/ids/[0…N],每个临时节点对应着一个在线的 Broker,Broker 启动后会创建一个临时节点,代表Broker 已经加入集群可以提供服务了,节点名称就是 BrokerID,节点内保存了包括Broker 的地址、版本号、启动时间等等一些 Broker 的基本信息。如果 Broker 宕机或者与ZooKeeper 集群失联了,这个临时节点也会随之消失。
右侧部分的这棵树保存的就是主题和分区的信息。/brokers/topics/ 节点下面的每个子节点都是一个主题,节点的名称就是主题名称。每个主题节点下面都包含一个固定的partitions 节点,pattitions 节点的子节点就是主题下的所有分区,节点名称就是分区编号。
每个分区节点下面是一个名为 state 的临时节点,节点中保存着分区当前的 leader 和所有的 ISR 的 BrokerID。这个 state 临时节点是由这个分区当前的 Leader Broker 创建的。如果这个分区的 Leader Broker 宕机了,对应的这个 state 临时节点也会消失,直到新的Leader 被选举出来,再次创建 state 临时节点。
kafka客户端如何找到对应的Broker信息
1、右侧主题、分区中找的state临时节点
2、从state节点中获取分区Leader的BrokerID
3、左侧树中找到BrokerID对应的获取Broker的真正访问地址。
kafka服务端与客户端的信息传输
org.apache.kafka.clients.NetworkClient#poll
->org.apache.kafka.clients.NetworkClient.DefaultMetadataUpdater#maybeUpdate(long)
->org.apache.kafka.clients.NetworkClient.DefaultMetadataUpdater#maybeUpdate(long, org.apache.kafka.common.Node)
kafka处理更新元数据请求
kafka/server/KafkaApis.scala:369
kafka.server.KafkaApis#handle
->handleTopicMetadataRequest(RequestChannel.Request)
注意点
1、不要往 ZooKeeper 里面写入大量数据,它不是一个真正意义上的存储系统,只适合存放少量的数据。依据服务器配置的不同,ZooKeeper 在写入超过几百 MB 数据之后,性能和稳定性都会严重下降。
2、不要让业务集群的可用性依赖于 ZooKeeper 的可用性,什么意思呢?你的系统可以使用 Zookeeper,但你要留一手,要考虑如果 Zookeeper 集群宕机了,你的业务集群最好还能提供服务。因为 ZooKeeper 的选举过程是比较慢的,而它对网络的抖动又比较敏感,一旦触发选举,这段时间内的 ZooKeeper 是不能提供任何服务的。
当需要要部署大规模的 Kafka 集群,建议的方式是,拆分成多个互相独立的小集群部署,每个小集群都使用一组独立的 ZooKeeper 提供服务。这样,每个 ZooKeeper 中存储的数据相对比较少,并且如果某个 ZooKeeper 集群故障,只会影响到一个小的 Kafka 集群,故障的影响面相对小一些。