在 Kafka 中,生产者(Producer)向 Kafka 发送消息时,ack(acknowledgment)设置的不同值控制着消息的确认行为,具体来说,设置 acks
参数影响生产者发送消息时的可靠性和性能。
Producer 的 acks
配置值
-
acks = 0
:
- 含义:生产者在发送消息后 不等待任何确认。即生产者发送完消息后,立即返回,不关心消息是否成功写入 Kafka。
- 优点:性能最高,因为生产者发送完消息后不等待确认。
- 缺点:最不可靠,因为消息发送后没有任何确认,可能会丢失数据。如果消息发送到 Kafka 时发生错误,生产者不会知道。
- 场景:用于对消息丢失不敏感的应用场景,例如实时数据传输,不需要保证每一条消息都被成功接收。
-
acks = 1
:
- 含义:生产者在消息发送后 等待 Leader 副本的确认。当 Leader 接收到消息并成功写入本地日志后,生产者会收到确认。此时,如果 Leader 成功写入日志,消息就被认为已经写入 Kafka。
- 优点:可靠性较高,只要 Leader 成功写入,消息就不会丢失。
- 缺点:如果 Leader 崩溃,且消息还没有被同步到 Follower,可能会丢失数据(因为不等到 Follower 确认)。
- 场景:在要求一定可靠性的情况下,且对性能有要求的场景。例如,日志、事件流等,要求一定的可靠性,但也能接受偶尔的消息丢失。
-
acks = -1
(或 acks = all
):
- 含义:生产者在消息发送后 等待所有同步副本(ISR 中的副本)确认。只有当 Leader 和 所有 ISR 副本 都成功接收到消息并将其写入本地日志后,生产者才会收到确认。这样可以确保消息在多个副本中都有备份。
- 优点:最高的可靠性,消息只有在所有同步副本确认后才会被认为成功。这保证了消息的持久性和高可用性。
- 缺点:性能相对较低,因为生产者需要等待所有同步副本确认。
- 场景:用于对数据丢失非常敏感的应用场景,如金融系统、支付系统等,需要保证消息的持久性和一致性。
acks = -1
时,Leader 何时认为消息被 commit
当 acks = -1
时,Leader 会在以下情况认为一条消息已经 "commit"(即成功写入并被确认):
-
所有同步副本(ISR)确认:
- Leader 会等待消息被所有同步副本(即位于 ISR 中的副本)确认。
- 同步副本(ISR) 是指那些与 Leader 保持同步的副本,这些副本的日志已跟上 Leader 的写入。
- 如果消息成功写入到 Leader,并且该消息在所有同步副本上也成功写入并确认,Leader 会认为该消息已成功 "commit"。
-
消息被所有同步副本写入日志:
- 消息首先会被 Leader 写入日志,随后该消息会被复制到所有同步副本(Follower)。
- 只有当所有同步副本(包括 Leader 本身)都确认接收并成功写入该消息时,Leader 才会认为该消息被 "commit" 并向生产者发送确认。
什么时候会出现 Leader 认为消息未 commit
- ISR 中没有足够的副本:如果由于网络分区、节点故障或其他原因,ISR 中没有足够的副本来确认消息,那么该消息就不会被认为 "commit",Leader 会等待直到足够的副本确认。
- 副本未同步:如果某些副本没有及时同步,Leader 会继续等待这些副本同步数据,直到消息被所有同步副本确认,才会提交确认。如果没有副本能够及时同步,生产者可能会长时间等待确认。
如何保证消息的可靠性
- 为了避免在
acks = -1
配置下可能出现的消息丢失或不一致问题,Kafka 提供了以下机制:
min.insync.replicas
配置:指定一个分区的最小同步副本数。在写入时,如果 ISR 中的副本数小于 min.insync.replicas
,则消息不会被写入,这样可以避免出现不一致的数据。
acks
和 min.insync.replicas
的配合:在生产者的 acks = -1
和消费者的 min.insync.replicas
配置共同作用下,Kafka 能确保只有在副本达到同步状态时才允许写入或消费数据,极大提高了数据的可靠性。