kafka 什么情况下会丢失消息以及如何保证可靠的数据传递

主要三个部分会造成消息丢失

  1. broke 端消息丢失

  2. 生产者端消息丢失

  3. 消费者端消息丢失

 

 一 broke端消费丢失

        broker端的消息不丢失,其实就是用partition副本机制来保证。

        

        broker 端有三个重要的参数来保证消息可靠

        1.复制系数  主题级别配置参数是  replication.factor ;broker 级别可以通过default.replication.factor 来配置自动创建的主题;

       该参数表示每个分区(或者该分区)会被复制几份、kafka的设计中备份会存放在不同的broker中所以极大程度保证消息的不丢失;

        2.不完全的首领选举 unclean.leader.election 只能再broker级别设置  默认为true    

        该参数配置决定在分区首领不可用时、非同步副本是否可以被选举为首领副本;如果设置为true 则予许不同步的副本成为首领,但我们将面临丢失消息的风险、如果设置为false 就需要等待原先的首领副本重新上线 从而降低了可用性。 

        换个角度说就是:该参数配置为true时 且分区发生重新选举选举出的首领分区为不完全分区时 可能就会发生消息丢失

        3.最小同步副本  在主题级别和broker级别上 min.insync.replicas

            该参数是为了避免在发生不完全选举时数据的写入和读取出现非预期的行为

         假如设置成3 那么至少要存在三个同步副本才能向分区写入数据(注意是 同步副本),如果同步副本数量小于3时broker就会停止接收所有生产者的消息、尝试发送消息的的生产者会受到NotEnoughReplicasException异常,消费者仍然可以读取已有数据、变成只读状态

        如果“所有副本”只包含一个同步副本,那么在这个副本变为不可用时,数据就可能会丢失

 

二  生产者端消息丢失

产生数据丢失的两种情况:

 

1)同步模式:有3种状态保证消息被安全生产,但是在配置为1(只保证写入leader成功)的话,如果刚好leader partition挂了,数据就会丢失。

 

2)异步模式:当缓冲区满了,如果配置为0(还没有收到确认的情况下,缓冲池一满,就清空缓冲池里的消息),数据就会被立即丢弃掉。

 

1. acks

acks = 0 生产者只负责发送数据

acks = 1 某个partitionleader收到数据给出响应

acks = all   某个partition的所有副本都收到数据后给出响应

2 buffer.memory 

 

3 retries = MAX 无限重试,直到你意识到出现了问题


 

4 max.in.flight.requests.per.connection = 1 限制客户端在单个连接上能够发送的未响应请求的个数。设置此值是1表示kafka broker在响应请求之前client不能再向同一个broker发送请求。注意:设置此参数是为了避免消息乱序

使用KafkaProducer.send(record, callback)而不是send(record)方法   自定义回调逻辑处理消息发送失败,比如记录在日志中,用定时脚本扫描重处理

callback逻辑中最好显式关闭producer:close(0) 注意:设置此参数是为了避免消息乱序(仅仅因为一条消息发送没收到反馈就关闭生产者,感觉代价很大)

unclean.leader.election.enable=false   关闭unclean leader选举,即不允许非ISR中的副本被选举为leader,以避免数据丢失

replication.factor >= 3   这个完全是个人建议了,参考了Hadoop及业界通用的三备份原则

min.insync.replicas > 1 消息至少要被写入到这么多副本才算成功,也是提升数据持久性的一个参数。与acks配合使用

保证replication.factor > min.insync.replicas  如果两者相等,当一个副本挂掉了分区也就没法正常工作了。通常设置replication.factor = min.insync.replicas + 1即可


 

三 消费者端消息丢失


consumer端丢失消息的情形比较简单:如果在消息处理完成前就提交了offset,那么就有可能造成数据的丢失

为了避免数据丢失,现给出两点建议:

enable.auto.commit=false  关闭自动提交位移

在消息被完整处理之后再手动提交位移


更多精彩内容