問題如下:
- kafka為什麼監聽不到資料
- kafka為什麼會有重複資料傳送
- kafka資料重複如何解決
- 為什麼kafka會出現倆個消費端都可以消費問題
- kafka監聽配置檔案
一. 解決問題一(kafka監聽不到資料)
首先kafka監聽不得到資料,檢查如下
- 檢查配置檔案是否正確(可能會出現改了監聽地址,監聽Topic,監聽的地址的數量問題)
- 檢查接收資料的正確性(比如原生的程式碼,可能是用byte序列化接收的資料,而你接收使用String。也是配置檔案序列化問題,還有與傳送者商量問題)
- 檢查kafka版本問題(一般的版本其實是沒什麼問題的,只有個別版本會出現監聽不到問題)
- 沒有加
@Component 犯了最不應該出差錯的問題
如果出現監聽不到資料的問題,那麼就試試更改方法一二,如果不可以在去試試方法三,之前出現這個問題也是查過 一般查到都會說 “低版本的伺服器接收不到高版本的生產者傳送的訊息”,但是淨由測試使用 用1.0.5RELEASE 和 2.6.3反覆測試,並沒有任何的問題。
如果按照版本一致,那麼根本就不現實,因為可能不同的專案,springboot版本不一致的話,可能有的springboot版本低,那麼你還得要求自己維護專案版本升級?如果出現第四種情況就無話可說了。
二. 解決問題二(kafka為什麼會有重複資料傳送)
重複資料的傳送問題如下
- 可能在傳送者的那裡的事務問題。mysql儲存事務發生異常導致回滾操作,但是kafka訊息卻是已經傳送到了伺服器中。此事肯定會出現重複問題
- 生產者設定時間問題,生產傳送設定的時間內,訊息沒完成傳送,生產者以為消費者掛掉,便重新傳送一個,導致重複
- offset問題,當專案重啟,offset走到某一個位置已扔到kafka伺服器中,但是專案被重啟.那麼offset會是在原本重啟的那一個點的地方再次傳送一次,這是kafka設計的問題,防止出現丟失資料問題
三. 解決問題三(kafka資料重複如何解決)
目前我是使用的Redis進行的排重法,用的是Redis中的set,保證裡面不存在重複,保證Redis裡面不會存入太多的髒資料。並定期清理
貼上一下我的排重(Redis排重法)
//kafka prefix String cache = "kafka_cache"; //kafka suffix Calendar c = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //0點,目前是為了設定為這一天的固定時間。這個完全可以去寫個工具類自己弄,為了看的更清楚,麻煩了一點的寫入 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd 00:00:00"); String gtimeStart = sdf2.format(c.getTime()); long time = sdf.parse(gtimeStart).getTime(); //此位置為了設定是否是新的一天,新的一天需要設定定時時間,保證redis中不會儲存太多無用資料 Boolean flag = false; //資料接收 Set<String> range = new HashSet<>(); //判斷是否存在 if (redisTemplate.hasKey(cache + time)) { //存在則取出這個set range = redisTemplate.opsForSet().members(cache + time); }else { //不存在,則為下面過期時間的設定鋪墊 flag = true; } //判斷監聽到的資料是否是重複 if (range.contains("測試需要")) { //重複則排出,根據邏輯自己修改 continue; } else { //新增進去 redisTemplate.opsForSet().add(cache + time, i+""); if (flag){ //設定為24小時,保證新一天使用,之前使用的儲存會消失掉 redisTemplate.expire(cache + time,24,TimeUnit.HOURS); //不會在進入這個裡面,如果多次的存入過期時間,那麼這個key的過期時間就永遠是24小時,一直就不會過期 flag = false; } }
四. 解決問題四(為什麼kafka會出現倆個消費端都可以消費問題)
原因是因為在不同group-id之下,kafka接收到以後,會給監聽他的每一個組傳送一個他所收到的訊息,但是兩個消費端監聽同一個group-id,那麼就只有一個消費端可以消費到。
五. 粘一下我的監聽配置檔案
# 指定kafka 代理地址,可以多個,用逗號間隔
spring.kafka.bootstrap-servers= localhost:9092
# 指定預設消費者group id
spring.kafka.consumer.group-id= test
# 是否自動提交
spring.kafka.consumer.enable-auto-commit= true
# 提交間隔的毫秒
spring.kafka.consumer.auto-commit-interval.ms=60000
# 最大輪詢的次數
spring.kafka.consumer.max-poll-records=1
# 將偏移量重置為最新偏移量
spring.kafka.consumer.auto-offset-reset=earliest
# 指定訊息key和訊息體的編解碼方式
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
如有什麼地方錯誤或者不明白請下方評論指出,謝謝。討論解決使我們共同進步