1.首先可以增加冗余的分区数,降低丢失数据风险,通过维护偏移量保障数据的精确一次性消费。
生产者端
写入需要用到kafka提供的API,通过与kafka的broker建立连接完成写入,很重要的数据为了防止丢失最保险的是可以用数据库记录已经成功写入kafka的数据编号。每次生产者启动时候先读取配置。避免程序终止再次启动数据漏传导致丢失。
集群增加增加一定的broker,如果broker不多和topic分区的冗余数量。建议冗余数量小于或者等于broker总数。减少写入buff的参数大小,让数据尽可能落盘快些。
kafka保存数据的磁盘做raid10或者raud5;硬件的层面做数据冗余。
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端异常,导致的消息丢失。
当所有follower副本的消息同步无法同步leader副本时,就会自动退送ISR集合,这个时候ISR集合只有1条记录,当出现这种情况时,生产端acks设置为-1就退化了1,此时leader分区出现异常时,就会出现消息丢失的情况,所以需要设置min.insync.replicas > 1,这个参数用来控制消息需要最小写入的副本数。
当leader副本出现异常后,kafka回进行重选举,从follower副本中,选出新的leader节点,如果选出的新leader副本的消息落后于此前的leader副本,也会存在消息丢失的情况,所以需要将参数unclean.leader.election.enable = false,表示不允许,非ISR集合中的分区,进行leader选举。
在kafka中,每一条消息就是自己offset偏移量,消费者每次消费完消息后,都会提交自己消费的位移,如下图所示,消费A消费到offset = 9的数据,消费者B消费到offset = 11的数据。consumer会提交自己的消费位移,用来知道自己消费的位置,如果消费位移提交不当,也会产生消息没有消费的情况。
自动提交:设置为enable.auto.commit为true,表示开启自动提交,自动提交会在每次调用poll时,提交上次poll时的消费位移,每次poll时,都是提交上次的offset的位移,如果是在单线程的情况,不会出现消费丢失的情况,但是对应多线程的应用来说,就有可能出现消费丢失的情况,例如我们每次poll到的数据都先放在一个队列中,用一个专门的线程来处理队列中的数据,但是我们poll的时候,上次提交的位移还没有完成消费,消费端出现了宕机,这个时候消费端重启后,就会出现消息丢失的情况。
手动提交,使用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端,将自动提交改为手动提交,确认消息消费完成后,在进行提交。