Kafka用Zookeeper所做的那些事

内容目录

哪些问题利用Zookeeper来解决
脑裂问题
如果Zookeeper挂了会怎样
如果删掉了Zookeeper的节点会怎样
Zookeeper用量估计
附录:Zookeeper路径的创建与监听表

哪些问题利用Zookeeper来解决

1. 选举Controller

Kafka是高可用的分布式消息系统,首先要解决的就是资源协调分配和多副本状态维护的问题。解决这些问题通常就是两种思路,一是依靠Zookeeper来协调,二是设定一个中心节点,让这个中心节点来协调。如果依靠Zookeeper来协调,会存在大量的竞争条件,对Zookeeper的访问压力增大,而且如果Zookeeper出现了问题(比如网络抖动),系统很容易出现紊乱。Kafka采用的是第二种思路,即选举一个中心节点来进行资源协调与多副本状态维护,这个中心节点被称作Controller(一个特殊的Broker),这个选举过程依靠Zookeeper来完成。
Broker启动时,会竞争创建临时"/controller"。如果创建成功,则成为Controller,并把Broker的id等信息写入这个节点。同时会全程监控"/controller"的数据变化,如果旧的Controller挂掉,则开启新一轮的竞争过程。

2. 注册Broker

Kafka要进行资源协调,第一件需要知道的事情就是各个Broker的存活状态,这个问题利用Zookeeper可以很容易做到。
假设某个Broker,id为0,它启动时,会创建"/brokers/ids/0"临时节点,并把端口等信息写进去。Controller会监控"/brokers/ids"的节点变化,以实时感知各broker的状态,进行资源协调。

3. 协调topic的创建、调整与销毁

在Kafka这个多副本分区的消息系统里,创建一个topic,至少需要以下3个步骤:

  • a 持久化topic的多副本分区信息
  • b 为每个分区挑选一个副本leader
  • c 将上述信息发送给对应的Broker,以完成实际的日志文件创建过程

Controller的存在,可以很容易完成上面的b和c步骤,但a步骤不行,如果Controller挂掉,则这些信息会不可用。Kafka把这些信息保存在Zookeeper中,依靠其高可用特性来保证这些信息的高可用。假设某个topic名字为mytopic,创建时,其分区信息保存在"/brokers/topics/mytopic"中。Controller全程监控"/brokers/topics"的孩子节点变动,实时感知这些信息,以完成后续步骤。
创建完成之后,后续往往会有分区调整和topic删除等需求。普通青年可能会觉得这两个问题很简单,给Controller发个相关请求就可以了。事实远非如此!
拿分区调整来说,假设某分区有三个副本,分别位于Broker-1、Broker-2和Broker-3,leader为1,现在扩容增加了Broker-4、Broker-5、Broker-6,为了平衡机器间压力,需要将副本1 2 3移到4 5 6,至少经历以下步骤:

  • 修改该分区的副本信息为1 2 3 4 5 6,leader为1
  • 等待4 5 6副本追赶1 2 3的进度直至大家都同步(in sync)
  • 从4 5 6中挑选一个新的副本leader,假设为4
  • 修改该分区的副本信息为4 5 6,leader为4

以上每个步骤都有可能失败,如何才能保证这次调整顺利进行呢?
首先,我们不能直接修改该分区的副本信息为 4 5 6,原因很简单,需要等待4 5 6的追赶过程以便产生新leader。其次,操作未完全成功的命令需要保存下来,如果操作过程中,Controller挂掉,则新的Controller可以从头开始直至成功。
Kafka怎么做的呢?

  • (通常是Admin控制台)把调整命令写入"/admin/reassign_partitions"节点
  • Controller监控"/admin/reassign_partitions",拿到调整命令,执行上述步骤
  • 如果操作成功则删除该节点;如果Controller挂掉,新的Controller还会拿到这个命令并从头开始执行

当然,这里一次只能有一个调整命令,但一个调整命令可以同时调整多个topic的多个分区。
在这个过程中,Zookeeper的作用是:持久化操作命令并实时通知操作者,是不是只有Zookeeper可以做这个事情呢,不是,但Zookeeper可以做得很好,保证命令高可用。
类似的操作还有topic删除,副本的leader变更等,都是沿用上面的套路。

4. 保存topic级别和client级别的配置信息

Broker的集群中有全局配置信息,但如果想针对某个topic或者某个client进行配置呢,Kafka把这些信息保存在Zookeeper中,各个Broker实时监控以更新。

脑裂问题

脑裂问题是指,在一个设有中心节点的系统中,出现了两个中心节点。两个中心同时传达命令,自然会造成系统的紊乱。
Kafka利用Zookeeper所做的第一件也是至关重要的一件事情是选举Controller,那么自然就有疑问,有没有可能产生两个Controller呢?
首先,Zookeeper也是有leader的,它有没有可能产生两个leader呢?答案是不会。
quorum机制可以保证,不可能同时存在两个leader获得大多数支持。假设某个leader假死,其余的followers选举出了一个新的leader。这时,旧的leader复活并且仍然认为自己是leader,这个时候它向其他followers发出写请求也是会被拒绝的。因为每当新leader产生时,会生成一个epoch,这个epoch是递增的,followers如果确认了新的leader存在,知道其epoch,就会拒绝epoch小于现任leader epoch的所有请求。那有没有follower不知道新的leader存在呢,有可能,但肯定不是大多数,否则新leader无法产生。Zookeeper的写也遵循quorum机制,因此,得不到大多数支持的写是无效的,旧leader即使各种认为自己是leader,依然没有什么作用。

Kafka的Controller也采用了epoch,具体机制如下:

  • 所有Broker监控"/controller",节点被删除则开启新一轮选举,节点变化则获取新的epoch
  • Controller会注册SessionExpiredListener,一旦因为网络问题导致Session失效,则自动丧失Controller身份,重新参与选举
  • 收到Controller的请求,如果其epoch小于现在已知的controller_epoch,则直接拒绝

理论上来说,如果Controller的SessionExpired处理成功,则可以避免双leader,但假设SessionExpire处理意外失效的情况:旧Controller假死,新的Controller创建。旧Controller复活,SessionExpired处理意外失效,仍然认为自己是leader。
这时虽然有两个leader,但没有关系,leader只会发信息给存活的broker(仍然与Zookeeper在Session内的),而这些存活的broker则肯定能感知到新leader的存在,旧leader的请求会被拒绝。

如果Zookeeper挂了会怎样

每个Broker有一个metaDataCache,缓存有topic和partition的基本信息,可以正常的生产和消费信息,但不能进行topic的创建、调整和删除等操作。
此外,Broker会不断重试连接。

如果删掉了Zookeeper的节点会怎样

待续

Zookeeper用量估计

假设Broker数目为B,topic数目为T,所有topic总partition数目为P,Client数目为C,以下数值均为峰值:

  • qps: 100以内
  • 连接数: B
  • watcher数目:3 * B + 2 * T + 6
  • Zookeeper节点数(叶子节点): B + P + T + C + 8

附录:Zookeeper路径的创建与监听表

路径 创建者 监听者 类型
/controller 各个broker竞争创建 所有broker全程监控data change 临时节点
/controller_epoch controller 永久节点
/brokers/ids broker启动时检查并确保存在 controller全程监控child change 永久节点
/brokers/ids/{id} id对应的broker 临时节点
/brokers/topics broker启动时检查确保存在 controller全程监控child change 永久节点
/brokers/topics/{topic} controller收到创建请求,或者broker启用自动创建topic时,或admin工具 controller全程监控data change 永久节点
/brokers/topics/{topic}/{partition}/state partiton的leader partition reassign时,controller临时监控data change 永久节点
/config/changes broker启动时检查并确保存在 所有broker全程监控child change 永久节点
/config/topics broker启动时检查并确保存在 永久节点
/config/clients broker启动时检查并确保存在 永久节点
/brokers/seqid broker启动时检查并确保存在 待确认 永久节点
/admin/delete_topics broker启动时检查并确保存在 controller全程监控child change 永久节点
/isr_change_notification broker启动时检查并确保存在 controller全程监控child change 永久节点
/admin/reassign_partitions admin 工具 controller全程监控data change 永久节点,reassign结束后会删除
/admin/preferred_replica_election admin 工具 controller全程监控data change 永久节点,replica election结束后会删除

你可能感兴趣的:(Kafka用Zookeeper所做的那些事)