面试热点之kafka乱序与幂等性问题

480 阅读3分钟

Kafka 幂等性原理(单分区单会话)

producer的幂等性(重试引起的乱序和重复)

  1. 重复问题的解决:
    1. Kafka 增加了 pid 和 seq。Producer 中每个 RecordBatch 都有一个单调递增的 seq; Broker 上每个 topic 的 partition 也会维护 pid-seq 的映射,并且每 Commit 都会更新 lastSeq。
    2. recordBatch 到来时,broker 会先检查 RecordBatch 再保存数据: 如果 batch 中 baseSeq(第一条消息的 seq)比 Broker 维护的序号(lastSeq)大 1,则保 存数据,否则不保存。
  2. 乱序问题的解决: 假设我们有 5 个batch的 请求,batch1、batch2、batch3、batch4、batch5; 如果只有 batch2 ack failed,3、4、5 都保存了,那 2 将会随下次 batch 重发而造成重复。 可以通过降低吞吐的情况来保证乱序问题----设置 max.in.flight.requests.per.connection=1(producer netClient每一次发送的等待回复的请求数,默认是5)来解决乱序,但降低了系统吞吐。 新版本 kafka 设置 enable.idempotence=true(开启幂等) 后能够动态调整 max-in-flight-request。正常 情况下 max.in.flight.requests.per.connection 大于 1。当重试请求到来时,batch 会根据 seq 重新添加到队列的合适位置,并把 max.in.flight.requests.per.connection 设为 1,这样它前面的 batch 序号都比它小,只有前面的都发完了,才会继续发送。

Kafka的事务:

配置:

  • 对于Producer,需要设置transactional.id属性,这个属性的作用下文会提到。设置了transactional.id属性后,enable.idempotence(幂等性)属性会自动设置为true。
  • 对于Consumer,需要设置isolation.level = read_committed,这样Consumer只会读取已经提交了事务的消息。另外,需要设置enable.auto.commit = false来关闭自动提交Offset功能。

Kafka的事务主要包括三个功能:原子写操作拒绝僵尸实例(Zombie fencing)和读事务消息

  • 本质是,将一组写操作(如果有)对应的消息与一组读操作(如果有)对应的Offset的更新进行同样的标记(Transaction Marker)来实现事务中涉及的所有读写操作同时对外可见或同时对外不可见。 Kafka只提供对Kafka本身的读写操作的事务性,不提供包含外部系统的事务性。 Kafka事务特性通过transaction-id属性来解决僵尸实例问题。所有具有相同transaction-id的Producer都会被分配相同的pid,同时每一个Producer还会被分配一个递增的epoch。Kafka收到事务提交请求时,如果检查当前事务提交者的epoch不是最新的,那么就会拒绝该Producer的请求。从而达成拒绝僵尸实例的目标。

详情可以参考链接:www.jianshu.com/p/64c930654…

Kafka的数据有序性:

kafka是保证分区有序性的,不保证topic有序性;有强有序性要求情况: a. 有序性要求的数据写入同一个分区,可以通过key分流:或者单分区topic,牺牲吞吐量 b. 解决重试有序性问题:enable.idempotence=true(幂等性开启) 和 调高retries 并且调高delivery.time.out时间(等待回复的时间)