• 11 无消息丢失配置


    kafka 什么情况下保证消息不丢失

    kafka对已提交的消息做有限度的持久化保证。

    什么是已提交的消息
    kakfa若干个broker成功收到一条消息并写入日志文件后,会告诉生产者程序这条消息已经成功提交。

    什么是有限度
    消息保留在N个broker上,至少要有一个存活

    “数据丢失”案例

    这里的数据丢失不一定是kafka的锅

    生产者丢失数据

    调用的是 producer.send(msg) 这个 API,那么它会立即返回,不管发送的结果成功与否。原因很多,可能是网络抖动,消息根本没有到broker;可能是消息格式不正确,比如消息太大了broker无法处理。

    解决办法是使用producer.send(msg, callback)这个API,对错误做针对性处理。如果是网络抖动会自动重试;如果是消息格式的问题,调整消息格式再发送。

    补充
    1.为什么将min.insync.replicas设置为大于1保证消息可用性,replication.factor > min.insync.replicas

    kafka权威指南里的解释,生产者指定ack=all, 是要求同步副本也就是ISR(min.insync.replicas指定的就是最小同步副本个数),而不是分区的所有副本(replication.factor指定的是副本数目),都接收到消息,才算成功。

    replication.factor是副本replica总数, min.insync.replicas是要求确保至少有多少个replica副本写入后才算是提交成功,这个参数是个硬指标;acks=all是个动态指标,确保当前能正常工作的replica副本都写入后才算是提交成功。举个例子:比如,此时副本总数3,即replication.factor = 3,设置min.insync.replicas=2,acks=all,那如果所有副本都正常工作,消息要都写入三个副本,才算提交成功,此时这个min.insync.replicas=2下限值不起作用。如果其中一个副本因为某些原因挂了,此时acks=all的动态约束就是写入两个副本即可,触达了min.insync.replicas=2这个下限约束。如果三个副本挂了两个,此时ack=all的约束就变成了1个副本,但是因为有min.insync.replicas=2这个下限约束,写入就会不成功。

    2.什么是ISR
    分区有多个副本,分为leader副本和follower副本,只有leader副本是工作的,读写请求都是走的leader副本,follower副本只是起备份作用

    kafka是由follower周期性或者尝试去pull(拉)过来(其实这个过程与consumer消费过程非常相似)

    leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),每个Partition都会有一个ISR,而且是由leader动态维护

    3.kafka producer异步发送消息是怎么做的
    kafka发送消息有同步和异步的方式,需要在效率和实效性做取舍,调用send方法发送实际上是把消息放到一个请求队列,后台发送线程读取队列的消息进行发送

    https://blog.csdn.net/m0_45406092/article/details/119564881
    https://zhuanlan.zhihu.com/p/427897970

    4.kafka是在消息flush到磁盘、同步到副本后才能被消费吗
    可能在刷盘之前就被消费了,能否被消费看的是leader副本的高水位是否超过了该消息。

    如果此时消息消费了,但是刷盘失败了,消息就丢失了?有容错机制吗?
    这个问题问的不太对,刷盘失败消息丢失是生产消息过程中可能发生的。如果在flush前机器宕机了,这条消息在这台broker确实丢失了,生产者的消息是否丢失取决于生产者配置的ack
    https://cwiki.apache.org/confluence/display/KAFKA/KIP-101±+Alter+Replication+Protocol+to+use+Leader+Epoch+rather+than+High+Watermark+for+Truncation#KIP101AlterReplicationProtocoltouseLeaderEpochratherthanHighWatermarkforTruncation-LeaderEpoch

    5.新增分区后导致消息丢失
    如果配置了配置了auto.offset.reset=latest,可能会导致消息丢失,具体如下
    broker新增分区后生产者先感知到,并将消息发送到新的分区;一段时间后消费者感知到了新分区,但是消费消息是从最新的消息开始消费,也就是会导致消息丢失。

    由于broker的原因丢数据

    所有的broker都挂了。这种情况消息并没有commit,符合开头提出的论点。

    消费者丢数据

    先更新位移,再消费消息,这种情况可能导致消息丢失。原因是消费者自动提交位移或者收到消息后先ack再处理消息,没有确认消息是否真正消费就盲目更新了位移。

    解决办法是关掉消费者自动提交位移,程序手动提交位移。

    还有一种情况是单consumer多线程消费

    避免无消费消息丢失很简单,但极易出现消息被消费了多次的情况。

    参考https://www.cnblogs.com/huxi2b/p/7089854.html

  • 相关阅读:
    NDAttributeList源码解析及测试
    面试官:我看你简历上写了MySQL,对MySQL InnoDB引擎的索引了解吗?
    如何连接智汀智能窗帘电机?打工人回到家后的“躺平”模式
    有价无市是什么意思
    如何控制滚轮横向滑动(原生JS实现方法)
    Ubuntu 23.04 安装es
    让Win11系统更好用的几个设置
    【C++】类和对象 从入门到超神
    驱动开发11-2 编写SPI驱动程序-点亮数码管
    Codeforces Round #829 Div. 2 D. Factorial Divisibility(结论&数学)
  • 原文地址:https://blog.csdn.net/qq_41904699/article/details/133458652