Kafka生产者有很多可以配置的参数,这些在kafka的说明文档中已经有详细的说明,它们大部分都有合理的默认值,一般情况下,我们不需要修改。不过有些参数在内存使用、性能和可靠性方面对生产者的影响比较大,今天就重点来讲讲acks参数对消息可靠性的影响。

acks

acks参数指定了在集群中有多少个分区副本收到消息,kafka producer才会认为消息是被写入成功。这个参数对消息丢失的可能性有很大的影响。接下来对其选项做相关的说明。

如果acks=0,生产者在成功写入消息之前是不会等待任何的来自服务器的响应。也就是说如果当中出现了错误,导致broker没有收到消息,那么生产者是无从得知的,消息也就丢失了。不过,因为生产者不需要等待服务器的响应,从而可以以网络可以支持的最大的速度来发送消息,使得系统能够达到很高的吞吐量。如果acks=1,只要集群的首领节点收到消息,生产者就会收到来自服务器成功的响应。若果消息不能够被首领节点接收(比如说首领节点崩溃,而新的首领尚未选出来),这时候生产者会收到一个错误响应,但是为了避免数据的丢失,生产者会重发消息。不过,如果一个没有收到消息的节点成为新首领,消息还是会丢失的。这个时候的吞吐量取决于使用的同步还是异步发送。如果让发送客户端(生产者)等待服务器的响应(通过调用Futrue对象的get()方法),显然会增加延迟(一次发送和响应的会话延迟)。如果客户端(生产者)使用回调,延迟问题就可以得到解决了,不过吞吐量还是会受到发送中消息数量的限制(比如生产者在收到服务器响应之前可以发送多少个消息)。producer发送数据到首领(leader)节点,leader把消息写入本地磁盘日志成功,响应客户端消息接收成功;此时集群中的其他副本还没有来得及拉取该消息进行复制,这时候首领(leader)节点就宕机了,因此此次发送的消息就会丢失。


如果acks=all / -1,只有在集群所有的跟随副本都接收到消息后,生产者才会受到一个来自服务器的成功响应。这种模式是最安全的,它可以保证集群中不止一个服务器接收到消息,就算有服务器崩溃了,这个集群还是能够正常运行。不过它比acks=1的延迟性更高,因为生产者要等待的所有参与复制消息的节点接收到消息。同步(Kafka默认为同步,即producer.type=sync)的发送模式,replication.factor>=2且min.insync.replicas>=2的情况下,不会丢失数据。有两种典型情况。acks=-1的情况下,数据发送到首领(leader)节点后,集群中的跟随者副本(follower)全部完成数据同步后,首领(leader)节点此时崩溃了,那么会选举出新的首领,这样就可以保证数据不会丢失。


acks=-1的情况下,数据发送到首领(leader)节点后 ,部分集群的跟随者副本同步,首领(leader)节点此时挂掉。比如follower1和follower2都有可能变成新的首领(leader),生产者(producer)端会得到响应异常,生产者(producer)端会重新发送数据,但是数据可能会重复。


当然上图中如果在首领出现故障的时候,follower2还没有同步到任何数据,而且follower2被选举为新的首领的话,这样消息就不会重复。

鉴于小编个人的能力有限,不当之处或者错误在所难免,欢迎广大读者在评论区留言指正,谢谢!