1、生产者端
首先,咱们要知道生产者在生产数据时是靠ack应答机制来传输数据的,当session
ack=0时,生成者无需等待brokder的ack,一直发送消息异步
ack=1时,生产者接收到leader的ack信号,就会发送下一条数据ide
ack=-1时,生产者必须等到全部broker返回ack信号,才会发送下一条数据spa
1.1数据丢失的状况
当ack=0时,若是有一台broker挂掉,那么那台broker就会接收不到这条消息.net
当ack=1时,若是有一台follower挂掉,那么这台follower也会丢失这条消息,线程
或者follower还未同步leader的数据,leader挂了,也会丢失消息code
1.2数据重复的状况
当ack=-1时,只要有一台follower没有与leader同步,生产者就会从新发送消息,这就照成了消息的重复blog
1.3避免方法
开启精确一次性,也就是幂等性,get
enable.idempotence=true
开启后,kafka首先会让producer自动将 acks=-1,再将producer端的retry次数设置为Long.MaxValue,再在集群上对每条消息进行标记去重!kafka
去重原理:
在cluster端,对每一个生产者线程生成的每条数据,都会添加由生产者id,分区号,随机的序列号组成的标识符: (producerid,partition,SequenceId),经过标识符对数据进行去重!
可是只能当次会话有效,若是重启了就没有效果
2、消费者端
消费者是以维护offset的方式来消费数据的,因此若是在提交offset的过程当中出问题,就会形成数据的问题,即已经消费了数据,可是offset没提交
大佬博客里已经解释很详细了http://www.javashuo.com/article/p-xarvecsw-n.html
注意:手动提交时,不管是同步提交仍是异步提交,都会有数据重复消费的风险
解决方案:
1.手动维护offset
2.加大这个参数kafka.consumer.session.timeout,以免被错误关闭的状况
3.加大消费能力