目录
ack应答机制
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(⼀次正好)语义
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