幂等性的实现方式

  1. 开启幂等性后,为了保证数据不会重复,那么就需要给每一个请求批次的数据增加唯一性标识,kafka 中,这个标识采用的是连续的序列号数字 sequencenum,但是不同的生产者 Producer 可能序列号是一样的,所以仅仅靠 seqnum 还无法唯一标记数据,所以还需要同时对生产者进行区分,所以 Kafka 采用申请生产者 ID (producerid) 的方式对生产者进行区分。这样,在发送数据前,我们就需要提前申请 producerid 以及序列号 sequencenum。
  2. Broker 中会给每一个分区记录生产者的生产状态: 采用队列的方式缓存最近的 5 个批次数据。队列中的数据按照 seqnum 进行升序排列。这里的数字 5 是经过压力测试,均衡空间效率和时间效率所得到的值,所以为固定值,无法配置且不能修改。
  3. 如果 Borker 当前新的请求批次数据在缓存的 5 个旧的批次中存在相同的,如果有相同的,那么说明有重复,当前批次数据不做任何处理。
  4. 如果 Broker 当前的请求批次数据在缓存中没有相同的,那么判断当前新的请求批次的序列号是否为缓存的最后一个批次的序列号加 1,如果是,说明是连续的,顺序没乱。那么继续,如果不是,那么说明数据已经乱了,发生异常。
  5. Broker 根据异常返回响应,通知 Producer 进行重试。Producer 重试前,需要在缓冲区中将数据重新排序,保证正确的顺序后。再进行重试即可。
  6. 如果请求批次不重复,且有序,那么更新缓冲区中的批次数据。将当前的批次放置再队列的结尾,将队列的第一个移除,保证队列中缓冲的数据最多 5 个。

幂等性的缺点

首先,它只能保证单分区上的幂等性,即一个幂等性 Producer 能够保证某个主题的一个分区上不出现重复消息,它无法实现多个分区的幂等性。

其次,它只能实现单会话上的幂等性,不能实现跨会话的幂等性。这里的会话,你可以理解为 Producer 进程的一次运行。当你重启了 Producer 进程之后,这种幂等性保证就丧失了。