摘要
Kafka的文档和代码注释表明,当生产者设置acks
设置为all
时,只有当所有同步副本都已捕获时,才会向生产者发送确认,但代码(Partition.Scala
,checkEnoughReplicasReachOffset
)似乎表明,只要 min in-sync副本已经赶上,就会发送确认。< / p>
详情
kafka文档有这个:
acks = all这意味着领导者将等待完整的同步副本集以确认记录。 source
另外,查看Kafka源代码 - partition.scala
checkEnoughReplicasReachOffset()
有以下评论(强调我的):
请注意,只有在requiredAcks = -1时才会调用此方法,并且我们等待ISR中的所有副本完全赶上与此生成请求相对应的(本地)领导者偏移量我们承认产品要求。
最后,Stack Overflow上的this answer(再次强调我的)
同步最小副本设置还指定了分区保持可用于写入所需的最小副本数。当生产者指定ack(-1 / all config)时,它仍将等待来自所有同步副本的确认(与min in-sync副本的设置无关)。
但是当我查看Partition.Scala中的代码时(注意minIsr < curInSyncReplicas.size
):
def checkEnoughReplicasReachOffset(requiredOffset: Long): (Boolean, Errors) = {
...
val minIsr = leaderReplica.log.get.config.minInSyncReplicas
if (leaderReplica.highWatermark.messageOffset >= requiredOffset) {
if (minIsr <= curInSyncReplicas.size)
(true, Errors.NONE)
调用它的代码返回ack:
if (error != Errors.NONE || hasEnough) {
status.acksPending = false
status.responseStatus.error = error
}
因此,只要同步副本集大于min同步副本,代码就会返回ack。但是,文档和注释表明只有在所有同步副本都赶上后才会发送确认。我错过了什么?至少,checkEnoughReplicasReachOffset
上方的评论看起来应该更改。
答案 0 :(得分:1)
感谢ji-dev邮件列表中的Ismael。
关键点是这一行:
if(leaderReplica.highWatermark.messageOffset >= requiredOffset) {
只有当ISR中的所有副本都具有该特定偏移时,高水印才会移动。