kafka的高可用

2022/2/16 23:13:47

本文主要是介绍kafka的高可用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Replication(主从复制)

在Kafka引入Replication之后,同一个Partition可能会有多个Replica,而这时需要在这些Replication之间选出一个Leader,Producer和Consumer只与这个Leader交互,其它Replica作为Follower从Leader中复制数据。

  因为需要保证同一个Partition的多个Replica之间的数据一致性(其中一个宕机后其它Replica必须要能继续服务并且即不能造成数据重复也不能造成数据丢失)。如果没有一个Leader,所有Replica都可同时读/写数据,那就需要保证多个Replica之间互相(N×N条通路)同步数据,数据的一致性和有序性非常难保证,大大增加了Replication实现的复杂性,同时也增加了出现异常的几率。而引入Leader后,只有Leader负责数据读写,Follower只向Leader顺序Fetch数据(N条通路),系统更加简单且高效。

kafka HA设计解析

Replication分配

Kafka分配Replica的算法如下:

1.将所有Broker(假设共n个Broker)和待分配的Partition排序

2.将第i个Partition分配到第(i % n)个Broker上

3.将第i个Partition的第j个Replica分配到第((i + j) % n)个Broker上

使同一个Partition的Replica尽量分散到不同Broker服务上,保证该Partition的高可用

Data Replication(副本策略)

  • 消息传递同步策略

Producer在发布消息到某个Partition时,先通过ZooKeeper找到该Partition的Leader,Producer只将该消息发送到该Partition的Leader。Leader会将该消息写入其本地Log。每个Follower都从Leader pull数据。这种方式上,Follower存储的数据顺序与Leader保持一致。Follower在收到该消息并写入其Log后,向Leader发送ACK。一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW并且向Producer发送ACK。

Consumer读消息也是从Leader读取,只有被commit过的消息才会暴露给Consumer。

  • ACK前需要保证有多少个备份

对于Kafka而言,定义一个Broker是否“活着”包含两个条件:

  1. 一是它必须维护与ZooKeeper的session(这个通过ZooKeeper的Heartbeat机制来实现)。

  2. 二是Follower必须能够及时将Leader的消息复制过来,不能“落后太多”。

Leader会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)。如果一个Follower宕机,或者落后太多,Leader将把它从ISR中移除。

Kafka的这种使用ISR的方式则很好的均衡了确保数据不丢失以及吞吐率。Follower可以批量的从Leader复制数据,这样极大的提高复制性能(批量写磁盘),极大减少了Follower与Leader的差距。

  • Leader Election算法

Leader选举本质上是一个分布式锁,有两种方式实现基于ZooKeeper的分布式锁:

  1. 节点名称唯一性:多个客户端创建一个节点,只有成功创建节点的客户端才能获得锁

  2. 临时顺序节点:所有客户端在某个目录下创建自己的临时顺序节点,只有序号最小的才获得锁

Kafka在ZooKeeper中动态维护了一个ISR(in-sync replicas),这个ISR里的所有Replica都跟上了leader,只有ISR里的成员才有被选为Leader的可能。

  • 如何处理所有Replica都不工作

在ISR中至少有一个follower时,Kafka可以确保已经commit的数据不丢失,但如果某个Partition的所有Replica都宕机了,就无法保证数据不丢失了。这种情况下有两种可行的方案:

1.等待ISR中的任一个Replica“活”过来,并且选它作为Leader(强一致性)

2.选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader(高可用性)

  • 选举Leader

在所有broker中选出一个controller,所有Partition的Leader选举都由controller决定。controller会将Leader的改变直接通过RPC的方式(比ZooKeeper Queue的方式更高效)通知需为此作为响应的Broker。同时controller也负责增删Topic以及Replica的重新分配。

如果通过ZooKeeper进行通知和选举(类似哨兵作用),会使ZooKeeper负载过重

HA相关ZooKeeper结构

img

  • admin

该目录下znode只有在有相关操作时才会存在,操作结束时会将其删除

/admin/reassign_partitions用于将一些Partition分配到不同的broker集合上。对于每个待重新分配的Partition,Kafka会在该znode上存储其所有的Replica和相应的Broker id。该znode由管理进程创建并且一旦重新分配成功它将会被自动移除。

  • brokers

/brokers/ids/[brokerId])存储“活着”的broker信息。

topic注册信息(/brokers/topics/[topic]),存储该topic的所有partition的所有replica所在的broker id,第一个replica即为preferred replica,对一个给定的partition,它在同一个broker上最多只有一个replica,因此broker id可作为replica id。

  • controller

/controller -> int (broker id of the controller)存储当前controller的信息

/controller_epoch -> int (epoch)直接以整数形式存储controller epoch,而非像其它znode一样以JSON字符串形式存储。

 



这篇关于kafka的高可用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程