0


【kafka专栏】如何保证数据生产不重不漏的高可靠性

kafka要保证消息的生产消费可靠性,需要从三个方面进行管理,一是kafka集群服务端,二是kafka生产者客户端,三是kafka消费者客户端。只有这三个方面都保证可靠性,才能实现消息不重复、不漏掉!本文主要从kafka生产者客户端的角度说明可靠性及其相关配置,关于其他两个方面请关注本专栏!

文章目录

通常情况下,我们希望程序向kafka消息队列中发送消息的过程是可靠的,也就是不能出现消息的丢失。但是在某些场景下,实际的需求并不需要消息的高可靠,比如某个网页的点击量数据。在某些异常情况下如果存在少量的数据丢失,也是可以接受的;比如服务器指标的监控数据,在某些异常情况下如果存在少量数据丢失,其实也会产生很大的影响。
在这些场景下其实并不需要kafka保证数据的高可靠性,保证性能和吞吐量可能更加重要。
kafka为了保证数据生产环节数据的高可靠性提供了一些生产者配置参数,这些配置参数能够帮助我们实现

  • 消息不丢失
  • 同一个消息不重复发送2次

但是配置这些参数,通常会存在一些代价,比如处理效率的下降。所以当我们修改这些参数的时候,一定先文自己几个问题:是不是真的需要消息数据的高可靠性?我们的数据是不是真的一条都不能丢?

一、消息发送的确认机制

需要注意的是,本文提到的所有配置都是针对apache kafka生产者客户端的配置,而不是针对kafka服务端的配置。

#新版本中acks=all
#在一些比较旧的apache kafka老版本中,参数名称如下
request.required.acks=all

这个acks参数决定了生产者发送数据的确认方式:

  • acks=0 表示生产者将数据通过网络发送(异步线程)出去之后,就不再关注消息是否发送成功。不需要等待kafka broker服务端消息写入主题分区动作的结果确认,所以这种方式的执行效率是最高的。
  • acks=1 kafka服务端leader副本成功收到数据并得到确认,就可以发送下一批消息。在本专栏前面的文章中我们介绍过,kafka生产者只与Leader分区副本进行消息通信,Follower副本的数据是从Leader分区副本中同步的。所以在一定程度上,我们可以认为只要Leader副本确认接收到消息,那么这条消息就实际上被成功发送了。但是我们没有考虑到异常情况,如果此时由于某些原因该主题的分区副本正在进行重新选举Leader,完成选举后,前任的Leader宕机了,消息没有完成复制到现任Leader那里,数据就丢失了。
  • acks=all 表示Leader分区副本接收到消息,并且所有的Follower也都完成了消息同步。也就是说Leader在向生产者进行消息确认之前,等待所有的副本完成数据同步,所以这种方式是最可靠的,也是执行效率最低的

二、消息发送的重试机制

涉及到消息发送重试机制的若干参数,等号后面为默认值。

retries=Integer.MAX_VALUE
retry.backoff.ms=100
delivery.timeout.ms=120000

当生产者发送消息时出现RetriableException会进行重试,也就是重新发送消息。

retries

配置了允许重试的最大次数;

retry.backoff.ms

配置了2次重试之间的时间间隔,单位ms毫秒;

delivery.timeout.ms

配置了消息完成发送的超时时间,超过这个时间将不再重试,

retries

参数失效。

2.1.什么样的异常是RetriableException?

  • 比如:对于分区Leader正在重新选举造成的异常等属于RetriableException,针对这类的异常生产者会进行重试。因为Leader选举完成之后,重新发送消息是会成功的。
  • 比如:对于配置信息错误导致的异常,生产者是不会进行重试的,因为尝试再多次程序也不能自动修改配置,还是需要人为干预才行。对于这类的异常进行消息发送的重试是没有意义的。

2.2.重试多次仍然失败怎么办?

这种情况是可能出现的,在达到了

retries

上限或

delivery.timeout.ms

上限之后,消息发送重试了多次,仍然没有发送成功。对于这种情况,我们还是要区别对待

  • 如果是用户的订单数据、用户的支付数据等,这类数据是绝对不能丢的。当出现异常的时候,就需要开发者catch异常并做好异常处理。或是将未能成功发送的数据入库、或是写文件先保存起来。等待异常通过人为干预的方式解除之后,再重新发往kafka。
  • 如果消息数据是用户网页点击量、商品阅读量这类的数据,数据量大、对于数据处理延时也没有太多的要求,甚至在异常情况下出现数据丢失也不是不能容忍。对于这类情况,其实也就没有必要做太多的异常处理。做好告警及日志记录,发现问题、解决问题,从程序及kafka服务端、网络性能等角度优化。

2.3.如何避免重试导致的消息重复问题?

上文中我们讨论了消息发送失败之后的重试机制,有一种特殊的情况需要我们额外关注:

  • 生产者第一次发送数据至broker,可能由于网络原因,生产者没有能够得到服务端写入成功的消息的确认,即:实际上消息数据已经在服务端写入成功,但是生产者没有感知到。
  • 由于生产者没有收到消息确认成功写入,它就认为消息发送失败了。所以重新发送了该消息,结果这个消息就有可能被写入多次。

在kafka0.11.0.0版本之前是无法实现exactly once,也就是无法实现消息被发送一次,并且只被发送一次。从0.11.0.0版本开始引入了EOS(exactly once semantics,精确一次处理语义),通过实现消息数据的幂等性和事务处理,来实现消息数据被精确的发送一次。关于EOS(幂等及事务),会在本专栏后面的文章详细介绍。


本文转载自: https://blog.csdn.net/hanxiaotongtong/article/details/125271081
版权归原作者 字母哥哥 所有, 如有侵权,请联系我们删除。

“【kafka专栏】如何保证数据生产不重不漏的高可靠性”的评论:

还没有评论