Kafka 生产者 ack、min.insync.replicas、replication factor机制剖析

Kafka 有三个很重要的配置参数,acksmin.insync.replicas.以及replication factor 其中acks是 producer 的配置参数,min.insync.replicas是 Broker 端的配置参数,这三个参数对于生产者不丢失数据起到了很大的作用.

一、分区副本


1、Kafka 的 topic 是可以分区的,并且可以为分区配置多个副本,改配置可以通过replication.factor参数实现.

2、Kafka 中的分区副本包括两种类型:领导者副本(Leader Replica)和追随者副本(Follower Replica),每个分区在创建时都要选举一个副本作为领导者副本,其余的副本自动变为追随者副本.

3、在 Kafka 中,追随者副本是不对外提供服务的,也就是说,任何一个追随者副本都不能响应消费者和生产者的读写请求. 所有的请求都必须由领导者副本来处理. 换句话说,所有的读写请求都必须发往领导者副本所在的 Broker,由该 Broker 负责处理. 追随者副本不处理客户端请求,它唯一的任务就是从领导者副本异步拉取消息,并写入到自己的提交日志中,从而实现与领导者副本的同步.

4、Kafka 默认的副本因子replication.factor是 3,即每个分区只有 1 个 leader 副本和 2 个 follower 副本. 具体如下图所示:

5、上面提到生产者客户端仅写入 Leader broker,跟随者异步复制数据。由于 Kafka 是一个分布式系统,必然会存在与 Leader 不能实时同步的风险,所以需要一种方法来判断这些追随者是否跟上了领导者的步伐, 即追随者是否同步了最新的数据. 换句话说,Kafka 要明确地告诉我们,追随者副本到底在什么条件下才算与 Leader 同步?这就是下面所要说的 ISR 同步副本机制.

二、同步副本 (In-sync replicas)


1、In-sync replica(ISR) 称之为同步副本,ISR 中的副本都是与 Leader 进行同步的副本,所以不在该列表的 follower 会被认为与 Leader 是不同步的. 那么,ISR 中存在是什么副本呢?首先可以明确的是:Leader 副本总是存在于 ISR 中. 而 follower 副本是否在 ISR 中,取决于该 follower 副本是否与 Leader 副本保持了 “同步”.

尖叫提示:对于 “follower 副本是否与 Leader 副本保持了同步” 的理解如下:

1、上面所说的同步不是指完全的同步,即并不是说一旦 follower 副本同步滞后与 Leader 副本,就会被踢出 ISR 列表.

2、Kafka 的 broker 端有一个参数replica.lag.time.max.ms, 该参数表示 follower 副本滞后与 Leader 副本的最长时间间隔,默认是 10 秒. 这就意味着,只要 follower 副本落后于 leader 副本的时间间隔不超过 10 秒,就可以认为该 follower 副本与 leader 副本是同步的,所以哪怕当前 follower 副本落后于 Leader 副本几条消息,只要在 10 秒之内赶上 Leader 副本,就不会被踢出出局.

3、如果 follower 副本被踢出 ISR 列表,等到该副本追上了 Leader 副本的进度,该副本会被再次加入到 ISR 列表中,所以 ISR 是一个动态列表,并不是静态不变的。

2、如上图所示:Broker3 上的 partition1 副本超过了规定时间,未与 Leader 副本同步,所以被踢出 ISR 列表,此时的 ISR 为 [1,3].

三、acks 确认机制


1、acks 参数指定了必须要有多少个分区副本收到消息,生产者才认为该消息是写入成功的,这个参数对于消息是否丢失起着重要作用,该参数的配置具体如下:

  • acks=0,表示生产者在成功写入消息之前不会等待任何来自服务器的响应. 换句话说,一旦出现了问题导致服务器没有收到消息,那么生产者就无从得知,消息也就丢失了. 改配置由于不需要等到服务器的响应,所以可以以网络支持的最大速度发送消息,从而达到很高的吞吐量。

  • acks=1,表示只要集群的 leader 分区副本接收到了消息,就会向生产者发送一个成功响应的 ack,此时生产者接收到 ack 之后就可以认为该消息是写入成功的. 一旦消息无法写入 leader 分区副本 (比如网络原因、leader 节点崩溃), 生产者会收到一个错误响应,当生产者接收到该错误响应之后,为了避免数据丢失,会重新发送数据. 这种方式的吞吐量取决于使用的是异步发送还是同步发送.

    尖叫提示:如果生产者收到了错误响应,即便是重新发消息,还是会有可能出现丢数据的现象. 比如,如果一个没有收到消息的节点成为了新的 Leader,消息就会丢失.

  • acks =all, 表示只有所有参与复制的节点 (ISR 列表的副本) 全部收到消息时,生产者才会接收到来自服务器的响应. 这种模式是最高级别的,也是最安全的,可以确保不止一个 Broker 接收到了消息. 该模式的延迟会很高.

四、最小同步副本


1、上面提到,当 acks=all 时,需要所有的副本都同步了才会发送成功响应到生产者. 其实这里面存在一个问题:如果 Leader 副本是唯一的同步副本时会发生什么呢?此时相当于 acks=1. 所以是不安全的.

2、Kafka 的 Broker 端提供了一个参数min.insync.replicas, 该参数控制的是消息至少被写入到多少个副本才算是 “真正写入”, 该值默认值为 1,生产环境设定为一个大于 1 的值可以提升消息的持久性. 因为如果同步副本的数量低于该配置值,则生产者会收到错误响应,从而确保消息不丢失.

4.1、Case 1

1、如下图,当 min.insync.replicas=2 且 acks=all 时,如果此时 ISR 列表只有 [1,2],3 被踢出 ISR 列表,只需要保证两个副本同步了,生产者就会收到成功响应.

4.2、 Case 2

1、如下图,当 min.insync.replicas=2,如果此时 ISR 列表只有 [1],2 和 3 被踢出 ISR 列表,那么当 acks=all 时,则不能成功写入数;当 acks=0 或者 acks=1 可以成功写入数据.

4.3、Case 3

1、这种情况是很容易引起误解的,如果 acks=all 且 min.insync.replicas=2,此时 ISR 列表为 [1,2,3], 那么还是会等到所有的同步副本都同步了消息,才会向生产者发送成功响应的 ack. 因为 min.insync.replicas=2 只是一个最低限制,即同步副本少于该配置值,则会抛异常,而 acks=all,是需要保证所有的 ISR 列表的副本都同步了才可以发送成功响应. 如下图所示:

五、总结


  • acks=0,生产者在成功写入消息之前不会等待任何来自服务器的响应.

  • acks=1, 只要集群的 leader 分区副本接收到了消息,就会向生产者发送一个成功响应的 ack.

  • acks=all, 表示只有所有参与复制的节点 (ISR 列表的副本) 全部收到消息时,生产者才会接收到来自服务器的响应,此时如果 ISR 同步副本的个数小于min.insync.replicas的值,消息不会被写入.

原文地址:Kafka 生产者 ack 机制剖析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值