kafka实现消息高可靠性的机制

  • Post author:
  • Post category:其他


消息可靠性维度

消息的可靠性性一般需要从三个维度进行考量。分别是生产端、服务端、消费端。


发送端可靠性:生产者需要确保消费发送到了服务端机器上。


服务端存储可靠性:服务端需要保证消息的持久化不丢失。


消费可靠性:消费端需要确认每条消息都被成功进行消费。

producer可靠性

对于kafka生产端来说,发送消息主要有两类API可以调用,分别是producer.send(msg)和producer.send(msg,callback)。

producer.send(msg):俗称“发后即忘”,不管消息有没有成功写入到broker端,生产者都不会收到任何通知,那么到消息因为某些原因(如:网络异常,消息体过大等)并未被broker接受时,就产生了消息丢失。

producer.send(msg,callback):带有回调函数,通过callback的回调来处理broker端的响应结果,如果未成功发送,那么就可以做响应的处理工作,如进行重试,记录日志等。

在kafka中,对于某些异常,生产者捕获到异常,会进行异常重试,重试的次数是由retries参数来控制的,因此为了保证消费的可靠性,还需要将这个参数的值设置为大于0的值,一般可设置为3~5。

同时对于生产者而言,还有一个重要的参数需要设置,就是acks的值,acks可以设置为 1,0,-1三个值,每个值的含义如下

0:生产者发送消息后,不需要等待任何服务端的响应。

1:其默认值为此值,表示生产者将消息成功写入到leader副本中,服务端就会返回成功响应。

-1 或 all:生产者发送消息后,消息需要写入ISR集合中全部副本,才算提交成功。

因此为了保证消息的可靠性,需要将acks参数设置为-1,这样可以避免leader结点宕机后,follower结点没有及时同步到消息,而产生的数据丢失。

broker端可靠性

在kafka中,每条消费都会被存储到磁盘上进行持久化存储,即使broker因为异常进行重启,也不会消息丢失,并且在生产环境,kafka都是以集群的方式进行部署,同时因为kafka的分区和副本的特性,一般可以保证broker端的消息不丢失的情况,但是也有一些特殊情况下存在消息丢失的可能。

broker端的参数设置不合理:对于每个消费分区而言,副本数replication.factor >= 3,消息进行多余的冗余备份,可以防止因为broker端异常,导致的消息丢失。

consumer可靠性

在kafka中,每一条消息就是自己offset偏移量,消费者每次消费完消息后,都会提交自己消费的位移,如下图所示,消费A消费到offset = 9的数据,消费者B消费到offset = 11的数据。consumer会提交自己的消费位移,用来知道自己消费的位置,如果消费位移提交不当,也会产生消息没有消费的情况。

对于consumer端来说,有两种提交消费位移的方式,分别是自动提交和手动提交。

手动提交,使用commitSync() 和 commitASync()API来进行手动提交,手动提交,可以让我们根据自己的实际消费情况来设置什么时间点进行提交位移,将位移提交交给用户自己,合理设置位移提交点可以保证消费的消费不丢失。

消费不丢失参数配置

在producer端使用,不要使用producer.send(msg)的API,要使用producer.seng(msg,callback)带有回调方法的API,来进行消息发送,可已经消息确认。

producer端设置acks=all,表示消息全部提交到ISR集合中的全部分区,才算消息提交成功。

producer端设置retries > 0,此参数,表示当生产者发送出现异常(如:broker出现网络抖动,导致超时)producer端进行重试的次数。

broker端,unclean.leader.election.enable = false,表示不允许,非ISR集合中的分区,进行leader选举,因为如果一个follower分区,消息落后于leader分区太远,当这个follower成为leader分区后,就会存在消息丢失。

broker端,replication.factor >= 3,表示副本的数量,消息进行多余的冗余备份,可以防止因为broker端异常,导致的消息丢失。

broker端,min.insync.replicas > 1,这个参数用来控制消息需要最小写入的副本数。

consumer端,将自动提交改为手动提交,确认消息消费完成后,在进行提交。