面试题答案
一键面试Kafka确保消息不丢失机制
- 生产者端:
- 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次。
- acks参数:
- 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每隔多长时间将数据刷盘。
- 副本机制:
- 消费者端:
- offset管理:
- Kafka 0.9版本之后,消费者的offset由Kafka内部主题
__consumer_offsets
来管理。消费者可以选择自动提交offset(enable.auto.commit = true
),但这种方式可能会在消费者处理完消息前就提交了offset,导致消息丢失。推荐使用手动提交offset(enable.auto.commit = false
),消费者在处理完消息后,调用commitSync()
或commitAsync()
方法手动提交offset,确保消息被处理后才更新offset,从而避免消息丢失。
- Kafka 0.9版本之后,消费者的offset由Kafka内部主题
- offset管理:
Kafka确保消息不重复机制
- 幂等性:
- 生产者开启幂等性只需设置
enable.idempotence = true
。Kafka通过为每个生产者分配一个PID(Producer ID),并在每次发送消息时携带一个单调递增的序列号(Sequence Number)来实现幂等性。当生产者重试发送消息时,broker会根据PID和序列号判断是否为重复消息,如果是则丢弃,保证每个PID发送到同一分区的消息不会重复。
- 生产者开启幂等性只需设置
- 事务:
- 生产者端,首先设置
transactional.id
参数,为生产者指定一个事务ID。开启事务使用initTransactions()
方法,在事务内发送消息,最后使用commitTransaction()
方法提交事务或abortTransaction()
方法回滚事务。消费者端,设置isolation.level
参数为read_committed
,这样消费者只会读取已提交事务的消息,避免读取到未提交事务中的消息,从而防止重复消费已在事务中成功提交的消息。
- 生产者端,首先设置