乐趣区

关于kafka:聊聊-KafkaKafka-如何保证可靠性

一、前言

在现在的分布式环境时代,任何一款中间件产品,大多都有一套机制去保障高可用的,Kafka 作为一个商业级消息中间件,音讯可靠性的重要性可想而知,那 Kafka 如何保障可靠性的呢?本文从 Producer 往 Broker 发送音讯、Topic 分区正本以及 Leader 选举几个角度介绍 Kafka 是如何保障可靠性的。

二、Producer 往 Broker 发送音讯

如果咱们要往 Kafka 对应的主题发送音讯,咱们须要通过 Producer 实现。后面咱们讲过 Kafka 主题对应了多个分区,每个分区上面又对应了多个正本;为了让用户设置数据可靠性,Kafka 在 Producer 外面提供了音讯确认机制。把选项提供给用户本人去抉择,咱们能够通过配置来决定音讯发送到对应分区的几个正本才算音讯发送胜利。能够在定义 Producer 时通过 acks 参数指定(在 0.8.2.X 版本之前是通过 request.required.acks 参数设置的,详见 KAFKA-3043)。

这个参数反对以下三种值:

  • acks = 0:意味着如果生产者可能通过网络把音讯发送进来,那么就认为音讯已胜利写入 Kafka。在这种状况下还是有可能产生谬误,比方发送的对象能干被序列化或者网卡产生故障,但如果是分区离线或整个集群长时间不可用,那就不会收到任何谬误。在 acks=0 模式下的运行速度是十分快的(这就是为什么很多基准测试都是基于这个模式),你能够失去惊人的吞吐量和带宽利用率,不过如果抉择了这种模式,肯定会失落一些音讯。
  • acks = 1:意味着 Leader 在收到音讯并把它写入到本地磁盘时会返回确认或谬误响应,不论其它的 Follower 正本有没有同步过这条音讯。在这个模式下,如果产生失常的 Leader 选举,生产者会在选举时收到一个 LeaderNotAvailableException 异样,如果生产者能失当地解决这个谬误,它会重试发送音讯,最终音讯会平安达到新的 Leader 那里。不过在这个模式下依然有可能失落数据,比方音讯曾经胜利写入 Leader,但在音讯被复制到 Follower 正本之前 Leader 产生解体。
  • acks = all(这个和 request.required.acks = -1 含意一样):意味着 Leader 在返回确认或谬误响应之前,会期待所有同步正本都收到音讯。如果和 min.insync.replicas 参数联合起来,就能够决定在返回确认前至多有多少个正本可能收到音讯,生产者会始终重试直到音讯被胜利提交。不过这也是最慢的做法,因为生产者在持续发送其余音讯之前须要期待所有正本都收到以后的音讯。

依据理论的利用场景,咱们设置不同的 acks,以此保证数据的可靠性。

另外,Producer 发送音讯还能够抉择同步(默认,通过 producer.type=sync 配置)或者异步(producer.type=async)模式。如果设置成异步,尽管会极大的进步音讯发送的性能,然而这样会减少失落数据的危险。如果须要确保音讯的可靠性,必须将 producer.type 设置为 sync。

三、Topic 分区正本

在 Kafka 0.8.0 之前,Kafka 是没有正本的概念的,那时候人们只会用 Kafka 存储一些不重要的数据,因为没有正本,数据很可能会失落。然而随着业务的倒退,反对正本的性能越来越强烈,所以为了保证数据的可靠性,Kafka 从 0.8.0 版本开始引入了分区正本(详情请参见 KAFKA-50)。也就是说每个分区能够人为的配置几个正本(比方创立主题的时候指定 replication-factor,也能够在 Broker 级别进行配置 default.replication.factor),个别会设置为 3。

Kafka 能够保障单个分区里的事件是有序的,分区能够在线(可用),也能够离线(不可用)。在泛滥的分区正本外面有一个正本是 Leader,其余的正本是 Follower,所有的读写操作都是通过 Leader 进行的,同时 Follower 会定期地去 Leader 上的复制数据。当 Leader 挂了的时候,其中一个 Follower 会从新成为新的 Leader。通过分区正本,引入了数据冗余,同时也提供了 Kafka 的数据可靠性。

Kafka 的分区多正本架构是 Kafka 可靠性保障的外围,把音讯写入多个正本能够使 Kafka 在产生解体时仍能保障音讯的持久性。

四、Leader 选举

在介绍 Leader 选举之前,让咱们先来理解一下 ISR(in-sync replicas)列表。每个分区的 Leader 会保护一个 ISR 列表,ISR 列表外面包含 Leader 正本和 Follower 正本的 Broker 编号,只有跟得上 Leader 的 Follower 正本能力退出到 ISR 外面,这个是通过 replica.lag.time.max.ms 参数配置的,这个参数的含意是 Follower 正本可能落后 Leader 正本的最长工夫距离,默认值是 10 秒。这就是说,只有一个 Follower 正本落后 Leader 正本的工夫不间断超过 10 秒,那么 Kafka 就认为该 Follower 正本与 Leader 是同步的,即便此时 Follower 正本中保留的音讯显著少于 Leader 正本中的音讯。

咱们在后面说过,Follower 正本惟一的工作就是一直地从 Leader 正本拉取音讯,而后写入到本人的提交日志中。如果这个同步过程的速度继续慢于 Leader 正本的音讯写入速度,那么在 replica.lag.time.max.ms 工夫后,此 Follower 正本就会被认为是与 Leader 正本不同步的,因而不能再放入 ISR 中。此时,Kafka 会主动膨胀 ISR 汇合,将该正本“踢出”ISR。

值得注意的是,假使该正本前面缓缓地追上了 Leader 的进度,那么它是可能从新被加回 ISR 的。这也表明,ISR 是一个动静调整的汇合,而非动态不变的。

所以当 Leader 挂掉了,而且 unclean.leader.election.enable=false 的状况下,Kafka 会从 ISR 列表中抉择第一个 Follower 作为新的 Leader,因为这个分区领有最新的曾经 committed 的音讯。通过这个能够保障曾经 committed 的音讯的数据可靠性。

五、思考

Q1:对于数据的读写操作都在 Leader 正本中,Follower 正本只从 Leader 正本复制数据,不对外提供数据读写操作,只做数据冗余保障可靠性。如果 Follower 正本还没同步完,此时 Leader 正本挂掉了,怎么保证数据的可靠性?
A1:这就要看下面说的 Producer 通过 acks 参数,依据本人的业务场景,设置不同的参数,以此保证数据的可靠性。


Q2:acks = 1,意味着 Leader 在收到音讯并把它写入到本地磁盘时会返回确认或谬误响应,不论其它的 Follower 正本有没有同步过这条音讯。如果 Follower 正本还没同步完,此时 Leader 正本挂掉了,怎么保证数据的可靠性?
A2:这就要看下面说的 Producer 通过 acks 参数,依据本人的业务场景,设置不同的参数,以此保证数据的可靠性。


Q3:acks = all,意味着 Leader 在返回确认或谬误响应之前,会期待所有同步正本都收到音讯。如果 Follower 正本同步实现后,Broker 给 Producer 返回 ack 之前,Leader 正本挂掉了,怎么保证数据的可靠性?
A3:数据发送到 Leader 正本后,局部 ISR 同步实现,也就是局部在 ISR 列表中的 Follower 正本同步实现后,此时 Leader 正本挂掉了,每个 Follower 正本都有可能成为新的 Leader 正本,Producer 端会返回异样,能够设置让 Producer 端从新发送数据来保证数据的可靠性,不过可能会造成数据的反复,如果要保证数据的一致性的话,业务上游须要做幂等操作,避免数据反复生产。


Q4:acks = all,就能够代表数据肯定不会失落吗?
A4

  • Partition 只有一个正本,也就是只有一个 Leader 正本,没有任何一个 Follower 正本的时候,接管完音讯后宕机,还是会存在数据失落。
  • acks = all,必须跟 ISR 列表里至多有两个以上的正本配合应用,min.insync.replicas 这个参数是设置 ISR 中最小正本数是多少,默认值是 1,改为 >= 2,如果 ISR 列表中的正本数小于 min.insync.replicas 配置的数量时,Producer 客户端会返回异样。

Q5:acks = all 时,ISR 列表中有三个正本,一个 Leader 正本,两个 Follower 正本。min.insync.replicas 配置的是 2,比方 Leader 正本和 Follower 1 正本收到音讯,此时 Leader 正本挂掉了,就返回异样给 Producer 了,但 Follower 2 正本选举成 Leader 正本了,Follower 2 正本落后 Leader 正本和 Follower 1 正本一些音讯,尽管都是在同一个 ISR 列表中,但 Follower 2 正本没有落后超过 replica.lag.time.max.ms 配置的值(默认是 10s)就还算是同步正本,Follower 2 正本入选 Leader 正本,后面的音讯岂不是失落了?
A5:社区在 0.11 版本正式引入了 Leader Epoch 概念,来躲避因高水位更新错配导致的各种不统一问题。

  • Epoch。一个枯燥减少的版本号。每当正本领导权产生变更时,都会减少该版本号。小版本号的 Leader 被认为是过期 Leader,不能再行使 Leader 势力。
  • 起始位移(Start Offset)。Leader 正本在该 Epoch 值上写入的首条音讯的位移。

举个例子来阐明一下 Leader Epoch。假如当初有两个 Leader Epoch<0, 0> 和 <1, 120>,那么,第一个 Leader Epoch 示意版本号是 0,这个版本的 Leader 从位移 0 开始保留音讯,一共保留了 120 条音讯。之后,Leader 产生了变更,版本号减少到 1,新版本的起始位移是 120。

这样就能够保障 Follower 2 正本选举成 Leader 正本时,沿用之前的旧的 Leader 正本的最初的音讯位移。

退出移动版