Kafka如何保证消息的可靠性传输
1.消费端弄丢了数据
唯⼀可能导致消费者弄丢数据的情况,就是说,你消费到了这个消息,然后消费者那边⾃动提交了 offt,让 Kafka 以为你已经消费好了这个消息,但其实你才刚准备处理这个消息,你还没处理,你⾃⼰就挂了,此时这条消息就丢咯。
这不是跟 RabbitMQ 差不多吗,⼤家都知道 Kafka 会⾃动提交 offt,那么只要关闭⾃动提交 offt,在处理完之后⾃⼰⼿动提交 offt,就可以保证数据不会丢。但是此时确实还是可能会有重复消费,⽐如你刚处理完,还没提交 offt,结果⾃⼰挂了,此时肯定会重复消费⼀次,⾃⼰保证幂等性就好了。
⽣产环境碰到的⼀个问题,就是说我们的 Kafka 消费者消费到了数据之后是写到⼀个内存的 queue ⾥先缓冲⼀下,结果有的时候,你刚把消息写⼊内存 queue,然后消费者会⾃动提交 offt。然后此时我们重启了系统,就会导致内存 queue ⾥还没来得及处理的数据就丢失了。
2.Kafka 弄丢了数据
这块⽐较常见的⼀个场景,就是 Kafka 某个 broker 宕机,然后重新选举 partition 的 leader。⼤家想想,要是此时其他的 follower 刚好还有些数据没有同步,结果此时 leader 挂了,然后选举某个 follower
成 leader 之后,不就少了⼀些数据?这就丢了⼀些数据啊。
⽣产环境也遇到过,我们也是,之前 Kafka 的 leader 机器宕机了,将 follower 切换为 leader 之后,就会发现说这个数据就丢了。
所以此时⼀般是要求起码设置如下 4 个参数:
给 topic 设置replication.factor参数:这个值必须⼤于 1,要求每个 partition 必须有⾄少 2 个副本。
在 Kafka 服务端设置plicas参数:这个值必须⼤于 1,这个是要求⼀个 leader ⾄少感知到有⾄少⼀个 follower 还跟⾃⼰保持联系,没掉队,这样才能确保 leader 挂了还有⼀个 follower 吧。
在 producer 端设置acks=all:这个是要求每条数据,必须是写⼊所有 replica 之后,才能认为是写成功了。
在 producer 端设置retries=MAX(很⼤很⼤很⼤的⼀个值,⽆限次重试的意思):这个是要求⼀旦写⼊失败,就⽆限重试,卡在这⾥了。
我们⽣产环境就是按照上述要求配置的,这样配置之后,⾄少在 Kafka broker 端就可以保证在 leader 所在 broker 发⽣故障,进⾏ leader 切换时,数据不会丢失。
3. ⽣产者会不会弄丢数据?
如果按照上述的思路设置了acks=all,⼀定不会丢,要求是,你的 leader 接收到消息,所有的 follower 都同步到了消息之后,才认为本次写成功了。如果没满⾜这个条件,⽣产者会⾃动不断的重试,重试⽆限次。