Kafka的数据丢失与数据重复

目录

ack应答机制

producer端数据丢失和重复生产问题

 Exactly Once(⼀次正好)语义

consumer端数据丢失和重复消费问题

END-TO-END端到端的精准一次语义。

kafka 环节丢失数据,


ack应答机制

        对于某些不太重要的数据,对数据的可靠性要求不是很⾼,能够容忍数据的少量丢失,所以没必要等ISR 中的follower全部接收成功
        所以Kafka 为⽤户提供了三种可靠性级别,⽤户根据对可靠性和延迟的要求进⾏权衡,选择以下的配置。

producer端数据丢失和重复生产问题

 上面三种级别分别为 1 0 -1

当 asks=0 时

        producer发送数据给leader过不够有没有落地到磁盘就发送确认ack,这样一旦leader还没有开始落地数据就立马挂了的话,从follower中选举一个leader,这样的话就丢失了原理发送的数据

当 asks=1 时

        producer发送数据给leader后落地到磁盘成功后发送确认ack,然后开始同步数据到follower中的时候发现leader挂了,从follower中选举一个leader,其他follower同步性leader的数据,但新leader还没有同步原来leader的新数据,所以数据也丢失了

当 asks=-1 时

        producer是要发送数据到leader并且全部的follower同步成功后才会发送确认ack,但follower同步成功中标发送确认ack的时候leader又挂了,这样producer没有收到确认ack就会以为吗发送成功又发送一遍,这样数据就发了两份相同的数据了,这就重复了

 总结:

producer配置:acks = (1,0,-1)
acks=0,大概率会发生数据丢失,吞吐量最高
acks=1,只有leader确认。吞吐量较高,但是还是存在小概率的数据丢失的问题(副本同步时,leader挂了)。
acks=-1,全部副本同步再发ack信号。吞吐量较低,数据不会丢失,但会出现数据重复(发送ack时,leader挂了导致消息重复生产)

最大限度解决生产端数据丢失+重复问题:acks=-1 结合幂等写入(多次写入只写一次)。使用时,只需将enable.idempotence属性设置为true(在生产者的位置),kafka自动将acks属性设为-1

解释:在 acks=-1 时数据会重复写入,哪么结合幂等写入(不够输入多少次重复的,都会算输入异常的特性)实现一次正好 就可以实现不重复写入了

 Exactly Once(⼀次正好)语义

        对于某些⽐较重要的消息,我们需要保证exactly once 语义,即保证每条消息被发送且仅被发送⼀次。
        在0.11 版本之后, Kafka 引⼊了幂等性机制( idempotent ),配合 acks = -1 时的 at least once( 最少⼀次 ) 语义,实现了producer broker exactly once 语义。
*idempotent + at least once = exactly once*
        使⽤时,只需将 enable.idempotence 属性设置为 true( 在⽣产者的位置 ) kafka ⾃动将 acks 属性设为 -1
ps: 幂等性机制是什么意思 , 幂等简单说 1 的⼏次幂都等于 1, 也就是说⼀条消息⽆论发⼏次都只算⼀次 , ⽆论多少条消息但只实例化⼀次
        
        kafka完成幂等性其实就是给消息添加了唯⼀ID, 这个 ID 的组成是 PID(ProducerID) 这样保证每⼀个 Producer 发送的时候是唯⼀的, 还会为 Producer 中每条消息添加⼀个消息 ID, 也就是说当前 Producer 中⽣产的消息会加⼊Producer的 ID 和消息 ID 这样就能保证消息唯⼀了 , 这个消息发送到 Kafka 中的时候回暂时缓存 ID, 写⼊数据后没有收到ack, 那么会从新发送这个消息 , 新消息过来的时候会和缓存中 ID 进⾏⽐较如果发现已经存在就不会再次接受了
详细解析 :
        了实现Producer 的幂等性, Kafka 引⼊了 Producer ID (即 PID )和 Sequence Number
        
        PID。每个新的Producer 在初始化的时候会被分配⼀个唯⼀的 PID ,这个 PID 对⽤户是不可⻅的。
        Sequence Numbler。(对于每个 PID ,该 Producer 发送数据的每个 <Topic, Partition> 都对应⼀个从 0 开始单调递增的Sequence Number
        Kafka可能存在多个⽣产者,会同时产⽣消息,但对 Kafka 来说,只 需要保证每个⽣产者内部的消息幂等 就可以了,所有引⼊了PID 来标识不同的⽣产者。
        对于 Kafka 来说,要解决的是⽣产者发送消息的幂等问题。也即需要区分每条消息是否重复。
        Kafka通过为每条消息增加⼀个Sequence Numbler ,通过 Sequence Numbler 来区分每条消息。每条消息对应⼀个分区,不同的分区产⽣的消息不可能重复。所有Sequence Numbler 对应每个分区
        Broker端在缓存中保存了这seq number ,对于接收的每条消息,如果其序号⽐ Broker 缓存中序号⼤ 1 则接受它,否则将其丢弃。这样就可以实现了消息重复提交了。但是, 只能保证单个 Producer 对于同⼀个 <Topic, Partition>的 Exactly Once 语义 。不能保证同⼀个 Producer ⼀个 topic 不同的 partion 幂等。

consumer端数据丢失和重复消费问题

enable.auto.commit=true  自动提交偏移量

        我们知道消费是从偏移量开始消费的,当我们使用自动提交时,数据还没有处理消费,但偏移量offset已经提交,这样我们下次就无法在消费之前那些的数据了,这就导致数据的丢失

解决:手动提交

enable.auto.commit=true  手动提交偏移量

        数据拿来消费了当手动提交consumer.commit失败了,这样偏移量没有变化,我们下次消费的时候就又会重复消费一次了这就数据重复了

解决:比如处理逻辑是存储mysql,保证幂等写入即可。

END-TO-END端到端的精准一次语义。

1)如何实现分布式系统幂等写入?Kafka支持等写入。
2)2PC(二阶段提交)其他看有没实现分布式事务。

kafka 环节丢失数据,

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

总结:

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



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


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


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

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也提供了相关的配置参数,来让你在性能与可靠性之间权衡(一般默认):


当达到下面的消息数量时,会将数据flush到日志文件中。默认10000
log.flush.interval.messages=10000


当达到下面的时间(ms)时,执行一次强制的flush操作。interval.ms和interval.messages无论哪个达到,都会flush。默认3000ms
log.flush.interval.ms=1000


检查是否需要将日志flush的时间间隔
log.flush.scheduler.interval.ms = 3000
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值