Kafka 如何保证高可用?

什么是高可用

「高可用性」,指系统无间断地执行其功能的能力,代表系统的可用性程度

Kafka 从 0.8 版本开始提供了高可用机制,可保障一个或多个 Broker 宕机后,其他 Broker 能继续提供服务

备份机制

Kafka 允许同一个 Partition 存在多个消息副本,每个 Partition 的副本通常由 1 个 Leader 及 0 个以上的 Follower 组成,生产者将消息直接发往对应 Partition 的 Leader,Follower 会周期地向 Leader 发送同步请求

同一 Partition 的 Replica 不应存储在同一个 Broker 上,因为一旦该 Broker 宕机,对应 Partition 的所有 Replica 都无法工作,这就达不到高可用的效果

所以 Kafka 会尽量将所有的 Partition 以及各 Partition 的副本均匀地分配到整个集群的各个 Broker 上

「如下图举个例子:」

ISR 机制

「ISR 副本集合」

ISR 中的副本都是与 Leader 同步的副本,相反,不在 ISR 中的追随者副本就被认为是与 Leader 不同步的

这里的保持同步不是指与 Leader 数据保持完全一致,只需在replica.lag.time.max.ms时间内与 Leader 保持有效连接

Follower 周期性地向 Leader 发送 FetchRequest 请求,发送时间间隔配置在replica.fetch.wait.max.ms中,默认值为 500

public class FetchRequest {
    private final short versionId;
    private final int correlationId;
    private final String clientId;
    private final int replicaId;
    private final int maxWait;    // Follower容忍的最大等待时间: 到点Leader立即返回结果,默认值500
    private final int minBytes;   // Follower容忍的最小返回数据大小:当Leader有足够数据时立即返回,兜底等待maxWait返回,默认值1
    private final Map<TopicAndPartition, PartitionFetchInfo> requestInfo;  // Follower中各Partititon对应的LEO及获取数量
}

各 Partition 的 Leader 负责维护 ISR 列表并将 ISR 的变更同步至 ZooKeeper,被移出 ISR 的 Follower 会继续向 Leader 发 FetchRequest 请求,试图再次跟上 Leader 重新进入 ISR

ISR 中所有副本都跟上了 Leader,通常只有 ISR 里的成员才可能被选为 Leader

「Unclean 领导者选举」

当 Kafka 中unclean.leader.election.enable配置为 true(默认值为 false)且 ISR 中所有副本均宕机的情况下,才允许 ISR 外的副本被选为 Leader,此时会丢失部分已应答的数据

开启 Unclean 领导者选举可能会造成数据丢失,但好处是,它使得分区 Leader 副本一直存在,不至于停止对外提供服务,因此提升了高可用性,反之,禁止 Unclean 领导者选举的好处在于维护了数据的一致性,避免了消息丢失,但牺牲了高可用性

ACK 机制

生产者发送消息中包含 acks 字段,该字段代表 Leader 应答生产者前 Leader 收到的应答数

  • 「acks=0」

生产者无需等待服务端的任何确认,消息被添加到生产者套接字缓冲区后就视为已发送,因此 acks=0 不能保证服务端已收到消息

  • 「acks=1」

只要 Partition Leader 接收到消息而且写入本地磁盘了,就认为成功了,不管它其他的 Follower 有没有同步过去这条消息了

  • 「acks=all」

Leader 将等待 ISR 中的所有副本确认后再做出应答,因此只要 ISR 中任何一个副本还存活着,这条应答过的消息就不会丢失

acks=all 是可用性最高的选择,但等待 Follower 应答引入了额外的响应时间。Leader 需要等待 ISR 中所有副本做出应答,此时响应时间取决于 ISR 中最慢的那台机器

如果说 Partition Leader 刚接收到了消息,但是结果 Follower 没有收到消息,此时 Leader 宕机了,那么客户端会感知到这个消息没发送成功,他会重试再次发送消息过去

Broker 有个配置项min.insync.replicas(默认值为 1)代表了正常写入生产者数据所需要的最少 ISR 个数

当 ISR 中的副本数量小于min.insync.replicas时,Leader 停止写入生产者生产的消息,并向生产者抛出 NotEnoughReplicas 异常,阻塞等待更多的 Follower 赶上并重新进入 ISR

被 Leader 应答的消息都至少有min.insync.replicas个副本,因此能够容忍min.insync.replicas-1个副本同时宕机

「结论:」

发送的 acks=1 和 0 消息会出现丢失情况,为不丢失消息可配置生产者acks=all & min.insync.replicas >= 2

故障恢复机制

「Kafka 从 0.8 版本开始引入了一套 Leader 选举及失败恢复机制」

首先需要在集群所有 Broker 中选出一个 Controller,负责各 Partition 的 Leader 选举以及 Replica 的重新分配

  • 当出现 Leader 故障后,Controller 会将 Leader/Follower 的变动通知到需为此作出响应的 Broker。

Kafka 使用 ZooKeeper 存储 Broker、Topic 等状态数据,Kafka 集群中的 Controller 和 Broker 会在 ZooKeeper 指定节点上注册 Watcher(事件监听器),以便在特定事件触发时,由 ZooKeeper 将事件通知到对应 Broker

Broker

「当 Broker 发生故障后,由 Controller 负责选举受影响 Partition 的新 Leader 并通知到相关 Broker」

  • 当 Broker 出现故障与 ZooKeeper 断开连接后,该 Broker 在 ZooKeeper 对应的 znode 会自动被删除,ZooKeeper 会触发 Controller 注册在该节点的 Watcher;
  • Controller 从 ZooKeeper 的/brokers/ids节点上获取宕机 Broker 上的所有 Partition;
  • Controller 再从 ZooKeeper 的/brokers/topics获取所有 Partition 当前的 ISR;
  • 对于宕机 Broker 是 Leader 的 Partition,Controller 从 ISR 中选择幸存的 Broker 作为新 Leader;
  • 最后 Controller 通过 LeaderAndIsrRequest 请求向的 Broker 发送 LeaderAndISRRequest 请求。

Controller

集群中的 Controller 也会出现故障,因此 Kafka 让所有 Broker 都在 ZooKeeper 的 Controller 节点上注册一个 Watcher

Controller 发生故障时对应的 Controller 临时节点会自动删除,此时注册在其上的 Watcher 会被触发,所有活着的 Broker 都会去竞选成为新的 Controller(即创建新的 Controller 节点,由 ZooKeeper 保证只会有一个创建成功)

竞选成功者即为新的 Controller。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值