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。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值