阅读354 返回首页    go 阿里云 go 技术社区[云栖]


解析Kafka High Available

Kafka在HA架设需要两个内容

Replication (主从复制)
Leader Election     (从属选取主级)
在Kafka在0.8以前的版本中,是没有Replication(主从控制)的,一旦某一个Broker(服务器节点)宕机,则其上所有的Partition(topic分区)数据都不可被消费,这与Kafka数据持久性及Delivery Guarantee(消息消费保障的设计目标相悖。同时Producer(生产者)都不能再将数据存于这些Partition(topic分区)中。

一、如何进行Replication主从复制:

1、如何把replica均匀的分布到集群中的每一个或者大多数的节点上(broke)

可以从前面的文章回到一个事实,为了能够提高整个集群的性能需要吧同一个topic下面的所有partition尽可能的分布到整个集群上去,一个典型的解决方案就是topic的partition的数量大于broke的数量.同样的,为了提高卡夫卡的HA,我们需要吧同一个partitio下面的所有replica(备份)尽量的分散到不同的服务器上去.(事实上,如果我们把某一个partition的所有replica全部放到同一个broker上那么同样的这个broker宕机了,也就回到这这个partition下面的所有信息丢失,没有起到HA的效验)

2、kafka分派replica算法:

分配条件
    N 个broker
    x 个 partition
    y 个replica
分配方式
    将所有的broker和所有的partition进行排序
    把第i个partition分配到 [i [ mod] n](i 除以 你的余数)(就是从第一台broker上开始部署,部署到最后一台broker,如果还没部署完,怎进行循环)个broker上(分配topic的分区的部署位置)
    把第i个partition的第j个replica分配到[(i+j) mod n]个broker上,效果和上年的分配partition是一样的.

3、如何进行主从数据propagate

有一个前提,product生产的消息只是和partition的leader进行通信,是不关心partition是有多少个replica的.
    product在发布消息到partition时,先通过zookeeper找到该partition的leader
    leader把数据写入log
    所有的follower都从leader pull拉去数据,而后写入这些follower的log里面
    通过pull的方式可以保证replica的消息顺序是和其leader的消息顺序一致
    然后每个follower都向leader发送ACK
    一但leader收到ISR(同步列表)的所有ACK,则认为该条消息已经被commit了

4、为了保住高吞吐量,kafka同样对replication的过程做了优化,
过程不是纯同步(性能会很忙),也不是纯异步(消息会丢失)

kafka采用了ISR列表的方式来进行维护
    ISR列表标识in-sync Replica 其意义为:与leader保持同步的Replica列表
    如果一个Follower宕机,或者落后太多,Leader将把它从ISR中移除。
    Kafka处理失败需要明确定义一个Broker是否“活着”。对于Kafka而言,Kafka存活包含两个条件,一是它必须维护与ZooKeeper session(这个通过ZooKeeper的Heartbeat机制来实现)。二是Follower必须能够及时将Leader的消息复制过来,不能“落后太多”。

二、如何保证给product ACK之前的备份数量
1、需要说明的是,Kafka只解决fail/recover,不处理“Byzantine”(“拜占庭”)问题。
2、一条消息只有被ISR里的所有Follower都从Leader复制过去才会被认为已提交。
3、而对于Producer而言,它可以选择是否等待消息commit,这可以通过request.required.acks来设置。
4、这种机制确保了只要ISR有一个或以上的Follower,一条被commit的消息就不会丢失。

三、如何进行Leader Election

1、使用的选举Leader方式

Kafka在ZooKeeper中动态维护了一个ISR(in-syncreplicas),这个ISR里的所有Replica都跟上了leader,只有ISR里的成员才有被选为Leader的可能。
        在这种模式下,对于f+1个Replica,一个Partition能在保证不丢失已经commit的消息的前提下容忍f个Replica的失败。在大多数使用场景中,这种模式是非常有利的。

四、如何处理所有的replica都宕机了

1、等待ISR中的任一个Replica“活”过来,并且选它作为Leader
2、选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader

五、如何选举leader

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

六、节点故障企切换过程(broker failover)

1. Controller在ZooKeeper注册Watch,一旦有Broker宕机(这是用宕机代表任何让系统认为其die的情景,包括但不限于机器断电,网络不可用,GC导致的Stop The World,进程crash等),其在ZooKeeper对应的znode会自动被删除,ZooKeeper会fire Controller注册的watch,Controller读取最新的幸存的Broker。
2. Controller决定set_p,该集合包含了宕机的所有Broker上的所有Partition。

3. 对set_p中的每一个Partition

3.1 从/brokers/topics/[topic]/partitions/[partition]/state读取该Partition当前的ISR
3.2 
决定该Partition的新Leader。
如果当前ISR中有至少一个Replica还幸存,则选择其中一个作为新Leader,新的ISR则包含当前ISR中所有幸存的Replica。
否则选择该Partition中任意一个幸存的Replica作为新的Leader以及ISR(该场景下可能会有潜在的数据丢失)。
        如果该Partition的所有Replica都宕机了,则将新的Leader设置为-1。
3.3 将新的Leader,ISR和新的leader_epoch及controller_epoch写入/brokers/topics/[topic]/partitions/[partition]/state。
注意,该操作只有其version在3.1至3.3的过程中无变化时才会执行,否则跳转到3.1

4. 直接通过RPC向set_p相关的Broker发送LeaderAndISRRequest命令。Controller可以在一个RPC操作中发送多个命令从而提高效率。

核心内容以及数据结构请查看该博客

最后更新:2017-11-14 16:34:24

  上一篇:go  《maven实战》读书笔记6——maven聚合和继承
  下一篇:go  U盘数据丢失了怎么免费恢复教程-快速有效