Kafka学习之怎么保证不丢,不重复消费数据

Kafka学习之怎么保证不丢,不重复消费数据

Kafka作为当下流行的高并发消息中间件,大量用于数据采集,实时处理等场景,我们在享受它带来的高并发,高可靠等便利时,同时不得不面对可能存在的问题,最常见的就是丢包,重发问题。


1. 丢包问题

1.1 问题描述

所谓丢包一般是指发送方发送的数据未到达接收方. 常见的丢包可能发生在发送端, 网络,接收端.

例如,消息推送服务,每天早上,手机上各终端都会给用户推送消息,这时候流量剧增,可能会出现kafka发送数据过快,导致服务器网卡爆满,或者磁盘处于繁忙状态,可能会出现丢包现象。

1.2 问题解决

解决方案:

  1. 对kafka进行限速,平滑流量
  2. 启用重试机制,重试间隔时间设置长一些
  3. Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功。

检测方法:使用重放机制,查看问题所在。


2.重发问题

2.1 问题描述

  • 重发问题:当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。当消费者消费的速度很慢的时候,可能在一个session周期内还未完成,导致心跳机制检测报告出问题。

问题场景:
1.设置offset为自动提交,正在消费数据,kill消费者线程;
2.设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe() 则有可能部分offset没提交,下次重启会重复消费;
3.消费kafka与业务逻辑在一个线程中处理,可能出现消费程序业务处理逻辑阻塞超时,导致一个周期内,offset还未提交;继而重复消费,但是业务逻辑可能采用发送kafka或者其他无法回滚的方式;

2.2 问题分析

底层根本原因:已经消费了数据,但是offset没提交。
配置问题:设置了offset自动提交
重复消费最常见的情况:re-balance问题,通常会遇到消费的数据,处理很耗时,导致超过了Kafka的session timeout时间(0.10.x版本默认是30秒),那么就会re-balance重平衡,此时有一定几率offset没提交,会导致重平衡后重复消费。

2.3 问题解决

解决办法:至少成功发送一次+去重操作(幂等性)

2.3.1 如何保证至少成功发送一次

保证不丢失消息:

生产者(ack=all 代表至少成功发送一次)
消费者 (offset手动提交,业务逻辑成功处理后,提交offset)

2.3.2 去重操作(幂等性)

去重问题:消息可以使用唯一id标识

保证不重复消费:落表(主键或者唯一索引的方式,避免重复数据)
业务逻辑处理(选择唯一主键存储到Redis或者mongdb中,先查询是否存在,若存在则不处理;若不存在,先插入Redis或Mongdb,再进行业务逻辑处理)

3. Spring和kafka结合

Spring集成kafka项目: https://github.com/longyu109/spring-kafka

你可能感兴趣的:(java,kafka,kafka学习,kafka-java)