MST

星途 面试题库

面试题:消息队列 Kafka 在电商高并发业务场景下如何保证消息的可靠性?

在电商场景中,比如大量订单消息的处理,Kafka 怎样确保消息不丢失、不重复,详细阐述其相关机制和配置参数。
33.2万 热度难度
后端开发消息队列

知识考点

AI 面试

面试题答案

一键面试

Kafka确保消息不丢失机制

  1. 生产者端
    • acks参数
      • acks = 0时,生产者发送消息后,不会等待任何来自broker的确认,这种情况下消息容易丢失,不推荐在确保消息不丢失场景使用。
      • acks = 1时,生产者发送消息后,只要leader副本成功写入消息,就会收到确认。如果follower副本还没来得及同步消息,leader副本所在broker发生故障,消息会丢失。
      • acks = all(或acks = -1)时,生产者发送消息后,会等待所有ISR(In - Sync Replicas,同步副本集)中的副本都成功写入消息后才收到确认。这可以最大程度保证消息不丢失,但可能会降低性能。
    • retries参数:设置生产者在发送消息失败时的重试次数。若设置为大于0的值,当消息发送失败时,生产者会根据retry.backoff.ms设置的时间间隔进行重试,避免因临时网络问题等导致消息丢失。例如,retries = 3表示最多重试3次。
  2. Broker端
    • 副本机制
      • Kafka通过多副本机制来保证数据冗余。每个分区都有一个leader副本和多个follower副本。leader负责处理读写请求,follower定期从leader同步数据。
      • 配置参数min.insync.replicas指定了ISR集合中最小副本数。只有当ISR中的副本数大于等于min.insync.replicas时,才会认为消息已成功提交。例如,min.insync.replicas = 2,意味着至少有2个副本(包括leader)同步了消息,消息才被视为已提交。如果在acks = all情况下,ISR中的副本数小于min.insync.replicas,生产者会收到错误,从而触发重试。
    • 日志刷盘机制
      • log.flush.interval.messages参数指定了Kafka在收到多少条消息后将数据刷盘,设置较小的值可以降低消息丢失风险,但频繁刷盘会影响性能。
      • log.flush.interval.ms参数指定了Kafka每隔多长时间将数据刷盘。
  3. 消费者端
    • offset管理
      • Kafka 0.9版本之后,消费者的offset由Kafka内部主题__consumer_offsets来管理。消费者可以选择自动提交offset(enable.auto.commit = true),但这种方式可能会在消费者处理完消息前就提交了offset,导致消息丢失。推荐使用手动提交offset(enable.auto.commit = false),消费者在处理完消息后,调用commitSync()commitAsync()方法手动提交offset,确保消息被处理后才更新offset,从而避免消息丢失。

Kafka确保消息不重复机制

  1. 幂等性
    • 生产者开启幂等性只需设置enable.idempotence = true。Kafka通过为每个生产者分配一个PID(Producer ID),并在每次发送消息时携带一个单调递增的序列号(Sequence Number)来实现幂等性。当生产者重试发送消息时,broker会根据PID和序列号判断是否为重复消息,如果是则丢弃,保证每个PID发送到同一分区的消息不会重复。
  2. 事务
    • 生产者端,首先设置transactional.id参数,为生产者指定一个事务ID。开启事务使用initTransactions()方法,在事务内发送消息,最后使用commitTransaction()方法提交事务或abortTransaction()方法回滚事务。消费者端,设置isolation.level参数为read_committed,这样消费者只会读取已提交事务的消息,避免读取到未提交事务中的消息,从而防止重复消费已在事务中成功提交的消息。