Kafka到底会不会丢数据?( 四 )


文章插图

  • 数据发送到 Leader Partition,部分 ISR 成员同步完成,此时 Leader Partition 异常 Crash, 剩下的 Follower Partition 都可能被选举成新的 Leader Partition,会给 Producer 端发送失败标识, 后续会重新发送数据,数据可能会重复, 如下图所示:

Kafka到底会不会丢数据?

文章插图
因此通过上面分析,我们还需要通过其他参数配置来进行保证:
replication.factor >= 2
min.insync.replicas > 1
这是 Broker 端的配置,下面会详细介绍 。
3)重试次数 retries:
该参数表示 Producer 端发送消息的重试次数 。
需要将 retries 设置为大于0的数, 在 Kafka 2.4 版本中默认设置为Integer.MAX_VALUE 。另外如果需要保证发送消息的顺序性,配置如下:
retries = Integer.MAX_VALUE
max.in.flight.requests.per.connection = 1
这样 Producer 端就会一直进行重试直到 Broker 端返回 ACK 标识,同时只有一个连接向 Broker 发送数据保证了消息的顺序性 。
4)重试时间 retry.backoff.ms:
该参数表示消息发送超时后两次重试之间的间隔时间,避免无效的频繁重试,默认值为100ms, 推荐设置为300ms 。
2.Broker 端解决方案
在剖析 Broker 端丢失场景的时候, 我们得出其是通过「异步批量刷盘」的策略,先将数据存储到 「PageCache」,再进行异步刷盘, 由于没有提供 「同步刷盘」策略, 因此 Kafka 是通过「多分区多副本」的方式来最大限度保证数据不丢失 。
我们可以通过以下参数配合来保证:
1)unclean.leader.election.enable:
该参数表示有哪些 Follower 可以有资格被选举为 Leader , 如果一个 Follower 的数据落后 Leader 太多,那么一旦它被选举为新的 Leader, 数据就会丢失,因此我们要将其设置为false,防止此类情况发生 。
2)replication.factor:
该参数表示分区副本的个数 。建议设置 replication.factor >=3, 这样如果 Leader 副本异常 Crash 掉,Follower 副本会被选举为新的 Leader 副本继续提供服务 。
3)min.insync.replicas:
该参数表示消息至少要被写入成功到 ISR 多少个副本才算"已提交",建议设置min.insync.replicas > 1, 这样才可以提升消息持久性,保证数据不丢失 。
另外我们还需要确保一下 replication.factor > min.insync.replicas, 如果相等,只要有一个副本异常 Crash 掉,整个分区就无法正常工作了,因此推荐设置成: replication.factor = min.insync.replicas +1, 最大限度保证系统可用性 。
3.Consumer 端解决方案
在剖析 Consumer 端丢失场景的时候,我们得出其拉取完消息后是需要提交 Offset 位移信息的,因此为了不丢数据,正确的做法是:拉取数据、业务逻辑处理、提交消费 Offset 位移信息 。
我们还需要设置参数 enable.auto.commit = false, 采用手动提交位移的方式 。
另外对于消费消息重复的情况,业务自己保证幂等性, 保证只成功消费一次即可 。
五、总结
至此,我们一起来总结一下这篇文章的重点 。
  • 从 Kafka 整体架构上概述了可能发生数据丢失的环节 。
  • 带你剖析了「消息传递语义」的概念, 确定了 Kafka 只对「已提交」的消息做「最大限度持久化保证不丢失」 。
  • 带你剖析了 Producer、Broker、Consumer 三端可能导致数据丢失的场景以及具体的高可靠解决方案 。
作者丨王江华
来源丨公众号:华仔聊技术(ID:gh_97b8de4b5b34)




推荐阅读