kafka丢消息

kafka会丢消息主要集中在两个环节

  1. 消息落盘时机

消息落盘有异步刷新和同步刷新两种,明显异步刷新的可靠性要高很多。但在某些场景下追求性能而忽略可靠性,可以启用。

  1. 消息存储维护

持久化存储,这句话不是说来玩的。Oracle/MySQL做了这么久的存储,其中的灾难恢复工具等都非常完备并形成体系(出问题你能找到人并能解决问题)kafka的存储谁特么知道~工具又特么的少!

另外就是落盘的存储介质,如果不做raid,那么单盘存在损坏的可能;做了raid,则成本上升。如果做多集copy,则存在网络同步延时所带来的瞬间数据不一致。

小结:kafka你要做到完全不丢数据(在非大灾大难的情况下,比如机房被原子弹轰炸;或者raid被误操作弄错同步时间或者低格等),是完全可以的。代价就是丢失一定的性能。

所以kafka我一般用在业务允许少量数据丢失但整体吞吐量非常大的场景(比如日志采集),数据统计分析(却少几百条数据不会对亿万级的样本空间产生什么影响)。

kafka也可以用在两个可靠存储之间做数据同步,比如MySQL(写)->MySQL(度),因为MySQL(写)保证了数据可被重放,所以kafka出问题时恢复速度和恢复可靠程度是可以得到保证的

 

kafka环节丢失数据,常见的kafka环节丢失数据的原因有:

  1. 如果auto.commit.enable=true,当consumer fetch了一些数据但还没有完全处理掉的时候,刚好到commit interval出发了提交offset操作,接着consumer crash掉了。这时已经fetch的数据还没有处理完成但已经被commit掉,因此没有机会再次被处理,数据丢失。

  2. 网络负载很高或者磁盘很忙写入失败的情况下,没有自动重试重发消息。没有做限速处理,超出了网络带宽限速。kafka一定要配置上消息重试的机制,并且重试的时间间隔一定要长一些,默认1秒钟并不符合生产环境(网络中断时间有可能超过1秒)。

  3. 如果磁盘坏了,会丢失已经落盘的数据

  4. 单批数据的长度超过限制会丢失数据,报kafka.common.MessageSizeTooLargeException异常
    解决:

    Consumer side:fetch.message.max.bytes- this will determine the largest size of a message that can be fetched by the consumer.
    
    Broker side:replica.fetch.max.bytes- this will allow for the replicas in the brokers to send messages within the cluster and make sure the messages are replicated correctly. If this is too small, then the message will never be replicated, and therefore, the consumer will never see the message because the message will never be committed (fully replicated).
    
    Broker side:message.max.bytes- this is the largest size of the message that can be received by the broker from a producer.
    
    Broker side (per topic):max.message.bytes- this is the largest size of the message the broker will allow to be appended to the topic. This size is validated pre-compression. (Defaults to broker'smessage.max.bytes.)
    
  5. partition leader在未完成副本数follows的备份时就宕机的情况,即使选举出了新的leader但是已经push的数据因为未备份就丢失了!
    kafka是多副本的,当你配置了同步复制之后。多个副本的数据都在PageCache里面,出现多个副本同时挂掉的概率比1个副本挂掉的概率就很小了。(官方推荐是通过副本来保证数据的完整性的)

  6. kafka的数据一开始就是存储在PageCache上的,定期flush到磁盘上的,也就是说,不是每个消息都被存储在磁盘了,如果出现断电或者机器故障等,PageCache上的数据就丢失了。
    可以通过log.flush.interval.messages和log.flush.interval.ms来配置flush间隔,interval大丢的数据多些,小会影响性能但在0.8版本,可以通过replica机制保证数据不丢,代价就是需要更多资源,尤其是磁盘资源,kafka当前支持GZip和Snappy压缩,来缓解这个问题 是否使用replica取决于在可靠性和资源代价之间的balance

 

消息发送方式

想清楚Kafka发送的消息是否丢失,需要先了解Kafka消息的发送方式。

Kafka消息发送分同步(sync)、异步(async)两种方式

默认是使用同步方式,可通过producer.type属性进行配置;

Kafka保证消息被安全生产,有三个选项分别是0,1,-1

通过request.required.acks属性进行配置:

0代表:不进行消息接收是否成功的确认(默认值);

1代表:当Leader副本接收成功后,返回接收成功确认信息;

-1代表:当Leader和Follower副本都接收成功后,返回接收成功确认信息;

六种发送场景

两个维度相交,生成六种情况,如下图:

 

消息丢失的场景

网络异常

acks设置为0时,不和Kafka集群进行消息接受确认,当网络发生异常等情况时,存在消息丢失的可能;

客户端异常

异步发送时,消息并没有直接发送至Kafka集群,而是在Client端按一定规则缓存并批量发送。在这期间,如果客户端发生死机等情况,都会导致消息的丢失;

缓冲区满了

异步发送时,Client端缓存的消息超出了缓冲池的大小,也存在消息丢失的可能;

Leader副本异常

acks设置为1时,Leader副本接收成功,Kafka集群就返回成功确认信息,而Follower副本可能还在同步。这时Leader副本突然出现异常,新Leader副本(原Follower副本)未能和其保持一致,就会出现消息丢失的情况;

以上就是消息丢失的几种情况,在日常应用中,我们需要结合自身的应用场景来选择不同的配置。

想要更高的吞吐量就设置:异步、ack=0;想要不丢失消息数据就选:同步、ack=-1策略

附:Kafka备份策略,不理解的可以看我的另一篇文章《Kafka消息的备份策略》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值